summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r--org.eclipse.jgit/.settings/.api_filters57
-rw-r--r--org.eclipse.jgit/META-INF/MANIFEST.MF105
-rw-r--r--org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF4
-rw-r--r--org.eclipse.jgit/pom.xml2
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties3
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java7
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java43
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java32
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java18
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.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/ObjectDirectory.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java36
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java64
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogContext.java67
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogRecord.java55
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/storage/pack/PackStatistics.java39
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java5
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java105
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java89
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java21
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/PackedObjectInfo.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java50
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java30
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java44
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java45
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java2
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java11
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java10
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java4
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java63
34 files changed, 933 insertions, 120 deletions
diff --git a/org.eclipse.jgit/.settings/.api_filters b/org.eclipse.jgit/.settings/.api_filters
new file mode 100644
index 0000000000..035ed37c10
--- /dev/null
+++ b/org.eclipse.jgit/.settings/.api_filters
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<component id="org.eclipse.jgit" version="2">
+ <resource path="src/org/eclipse/jgit/lib/ConfigConstants.java" type="org.eclipse.jgit.lib.ConfigConstants">
+ <filter id="1141899266">
+ <message_arguments>
+ <message_argument value="5.9"/>
+ <message_argument value="5.10"/>
+ <message_argument value="CONFIG_PROTOCOL_SECTION"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/lib/TypedConfigGetter.java" type="org.eclipse.jgit.lib.TypedConfigGetter">
+ <filter id="404000815">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.lib.TypedConfigGetter"/>
+ <message_argument value="getPath(Config, String, String, String, FS, File, Path)"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/storage/pack/PackStatistics.java" type="org.eclipse.jgit.storage.pack.PackStatistics$Accumulator">
+ <filter id="336658481">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.storage.pack.PackStatistics.Accumulator"/>
+ <message_argument value="notAdvertisedWants"/>
+ </message_arguments>
+ </filter>
+ <filter id="336658481">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.storage.pack.PackStatistics.Accumulator"/>
+ <message_argument value="reachabilityCheckDuration"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/transport/HttpConfig.java" type="org.eclipse.jgit.transport.HttpConfig">
+ <filter id="336658481">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.transport.HttpConfig"/>
+ <message_argument value="EXTRA_HEADER"/>
+ </message_arguments>
+ </filter>
+ <filter id="336658481">
+ <message_arguments>
+ <message_argument value="org.eclipse.jgit.transport.HttpConfig"/>
+ <message_argument value="USER_AGENT"/>
+ </message_arguments>
+ </filter>
+ </resource>
+ <resource path="src/org/eclipse/jgit/transport/TransferConfig.java" type="org.eclipse.jgit.transport.TransferConfig$ProtocolVersion">
+ <filter id="1175453698">
+ <message_arguments>
+ <message_argument value="5.9"/>
+ <message_argument value="5.10"/>
+ <message_argument value="org.eclipse.jgit.transport.TransferConfig.ProtocolVersion"/>
+ </message_arguments>
+ </filter>
+ </resource>
+</component>
diff --git a/org.eclipse.jgit/META-INF/MANIFEST.MF b/org.eclipse.jgit/META-INF/MANIFEST.MF
index 1348bde29e..886e004218 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: %Bundle-Name
Automatic-Module-Name: org.eclipse.jgit
Bundle-SymbolicName: org.eclipse.jgit
-Bundle-Version: 5.9.1.qualifier
+Bundle-Version: 5.10.1.qualifier
Bundle-Localization: plugin
Bundle-Vendor: %Bundle-Vendor
Eclipse-ExtensibleAPI: true
-Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
- org.eclipse.jgit.api;version="5.9.1";
+Export-Package: org.eclipse.jgit.annotations;version="5.10.1",
+ org.eclipse.jgit.api;version="5.10.1";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.notes,
org.eclipse.jgit.dircache,
@@ -23,18 +23,18 @@ Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
org.eclipse.jgit.revwalk.filter,
org.eclipse.jgit.blame,
org.eclipse.jgit.merge",
- org.eclipse.jgit.api.errors;version="5.9.1";
+ org.eclipse.jgit.api.errors;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.errors",
- org.eclipse.jgit.attributes;version="5.9.1";
+ org.eclipse.jgit.attributes;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk",
- org.eclipse.jgit.blame;version="5.9.1";
+ org.eclipse.jgit.blame;version="5.10.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.9.1";
+ org.eclipse.jgit.diff;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.attributes,
org.eclipse.jgit.revwalk,
@@ -42,47 +42,47 @@ Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util",
- org.eclipse.jgit.dircache;version="5.9.1";
+ org.eclipse.jgit.dircache;version="5.10.1";
uses:="org.eclipse.jgit.events,
org.eclipse.jgit.lib,
org.eclipse.jgit.attributes,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util",
- org.eclipse.jgit.errors;version="5.9.1";
+ org.eclipse.jgit.errors;version="5.10.1";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
org.eclipse.jgit.internal.storage.pack",
- org.eclipse.jgit.events;version="5.9.1";
+ org.eclipse.jgit.events;version="5.10.1";
uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.fnmatch;version="5.9.1",
- org.eclipse.jgit.gitrepo;version="5.9.1";
+ org.eclipse.jgit.fnmatch;version="5.10.1",
+ org.eclipse.jgit.gitrepo;version="5.10.1";
uses:="org.xml.sax.helpers,
org.eclipse.jgit.api,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.xml.sax",
- org.eclipse.jgit.gitrepo.internal;version="5.9.1";x-internal:=true,
- org.eclipse.jgit.hooks;version="5.9.1";uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.ignore;version="5.9.1",
- org.eclipse.jgit.ignore.internal;version="5.9.1";
+ org.eclipse.jgit.gitrepo.internal;version="5.10.1";x-internal:=true,
+ org.eclipse.jgit.hooks;version="5.10.1";uses:="org.eclipse.jgit.lib",
+ org.eclipse.jgit.ignore;version="5.10.1",
+ org.eclipse.jgit.ignore.internal;version="5.10.1";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal;version="5.9.1";
+ org.eclipse.jgit.internal;version="5.10.1";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.http.test",
- org.eclipse.jgit.internal.fsck;version="5.9.1";
+ org.eclipse.jgit.internal.fsck;version="5.10.1";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.ketch;version="5.9.1";
+ org.eclipse.jgit.internal.ketch;version="5.10.1";
x-friends:="org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.revwalk;version="5.9.1";x-internal:=true,
- org.eclipse.jgit.internal.storage.dfs;version="5.9.1";
+ org.eclipse.jgit.internal.revwalk;version="5.10.1";x-internal:=true,
+ org.eclipse.jgit.internal.storage.dfs;version="5.10.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.9.1";
+ org.eclipse.jgit.internal.storage.file;version="5.10.1";
x-friends:="org.eclipse.jgit.test,
org.eclipse.jgit.junit,
org.eclipse.jgit.junit.http,
@@ -91,35 +91,35 @@ Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
org.eclipse.jgit.pgm,
org.eclipse.jgit.pgm.test,
org.eclipse.jgit.ssh.apache",
- org.eclipse.jgit.internal.storage.io;version="5.9.1";
+ org.eclipse.jgit.internal.storage.io;version="5.10.1";
x-friends:="org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.pack;version="5.9.1";
+ org.eclipse.jgit.internal.storage.pack;version="5.10.1";
x-friends:="org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.storage.reftable;version="5.9.1";
+ org.eclipse.jgit.internal.storage.reftable;version="5.10.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.9.1";
+ org.eclipse.jgit.internal.storage.reftree;version="5.10.1";
x-friends:="org.eclipse.jgit.junit,
org.eclipse.jgit.test,
org.eclipse.jgit.pgm",
- org.eclipse.jgit.internal.submodule;version="5.9.1";x-internal:=true,
- org.eclipse.jgit.internal.transport.connectivity;version="5.9.1";
+ org.eclipse.jgit.internal.submodule;version="5.10.1";x-internal:=true,
+ org.eclipse.jgit.internal.transport.connectivity;version="5.10.1";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.http;version="5.9.1";
+ org.eclipse.jgit.internal.transport.http;version="5.10.1";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.parser;version="5.9.1";
+ org.eclipse.jgit.internal.transport.parser;version="5.10.1";
x-friends:="org.eclipse.jgit.http.server,
org.eclipse.jgit.test",
- org.eclipse.jgit.internal.transport.ssh;version="5.9.1";
+ org.eclipse.jgit.internal.transport.ssh;version="5.10.1";
x-friends:="org.eclipse.jgit.ssh.apache,
org.eclipse.jgit.ssh.jsch",
- org.eclipse.jgit.lib;version="5.9.1";
+ org.eclipse.jgit.lib;version="5.10.1";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.util.sha1,
org.eclipse.jgit.dircache,
@@ -133,9 +133,10 @@ Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
org.eclipse.jgit.util,
org.eclipse.jgit.submodule,
org.eclipse.jgit.util.time",
- org.eclipse.jgit.lib.internal;version="5.9.1";
+ org.eclipse.jgit.lib.internal;version="5.10.1";
x-friends:="org.eclipse.jgit.test",
- org.eclipse.jgit.merge;version="5.9.1";
+ org.eclipse.jgit.logging;version="5.10.1",
+ org.eclipse.jgit.merge;version="5.10.1";
uses:="org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
@@ -144,40 +145,40 @@ Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
org.eclipse.jgit.util,
org.eclipse.jgit.api,
org.eclipse.jgit.attributes",
- org.eclipse.jgit.nls;version="5.9.1",
- org.eclipse.jgit.notes;version="5.9.1";
+ org.eclipse.jgit.nls;version="5.10.1",
+ org.eclipse.jgit.notes;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.merge",
- org.eclipse.jgit.patch;version="5.9.1";
+ org.eclipse.jgit.patch;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.diff",
- org.eclipse.jgit.revplot;version="5.9.1";
+ org.eclipse.jgit.revplot;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.revwalk",
- org.eclipse.jgit.revwalk;version="5.9.1";
+ org.eclipse.jgit.revwalk;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.diff,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.revwalk.filter,
org.eclipse.jgit.treewalk",
- org.eclipse.jgit.revwalk.filter;version="5.9.1";
+ org.eclipse.jgit.revwalk.filter;version="5.10.1";
uses:="org.eclipse.jgit.revwalk,
org.eclipse.jgit.lib,
org.eclipse.jgit.util",
- org.eclipse.jgit.storage.file;version="5.9.1";
+ org.eclipse.jgit.storage.file;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.util",
- org.eclipse.jgit.storage.pack;version="5.9.1";
+ org.eclipse.jgit.storage.pack;version="5.10.1";
uses:="org.eclipse.jgit.lib",
- org.eclipse.jgit.submodule;version="5.9.1";
+ org.eclipse.jgit.submodule;version="5.10.1";
uses:="org.eclipse.jgit.lib,
org.eclipse.jgit.diff,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.treewalk,
org.eclipse.jgit.util",
- org.eclipse.jgit.transport;version="5.9.1";
+ org.eclipse.jgit.transport;version="5.10.1";
uses:="javax.crypto,
org.eclipse.jgit.util.io,
org.eclipse.jgit.lib,
@@ -190,21 +191,21 @@ Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
org.eclipse.jgit.transport.resolver,
org.eclipse.jgit.storage.pack,
org.eclipse.jgit.errors",
- org.eclipse.jgit.transport.http;version="5.9.1";
+ org.eclipse.jgit.transport.http;version="5.10.1";
uses:="javax.net.ssl",
- org.eclipse.jgit.transport.resolver;version="5.9.1";
+ org.eclipse.jgit.transport.resolver;version="5.10.1";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.lib",
- org.eclipse.jgit.treewalk;version="5.9.1";
+ org.eclipse.jgit.treewalk;version="5.10.1";
uses:="org.eclipse.jgit.dircache,
org.eclipse.jgit.lib,
org.eclipse.jgit.attributes,
org.eclipse.jgit.revwalk,
org.eclipse.jgit.treewalk.filter,
org.eclipse.jgit.util",
- org.eclipse.jgit.treewalk.filter;version="5.9.1";
+ org.eclipse.jgit.treewalk.filter;version="5.10.1";
uses:="org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util;version="5.9.1";
+ org.eclipse.jgit.util;version="5.10.1";
uses:="org.eclipse.jgit.transport,
org.eclipse.jgit.hooks,
org.eclipse.jgit.revwalk,
@@ -217,12 +218,12 @@ Export-Package: org.eclipse.jgit.annotations;version="5.9.1",
org.eclipse.jgit.treewalk,
javax.net.ssl,
org.eclipse.jgit.util.time",
- org.eclipse.jgit.util.io;version="5.9.1";
+ org.eclipse.jgit.util.io;version="5.10.1";
uses:="org.eclipse.jgit.attributes,
org.eclipse.jgit.lib,
org.eclipse.jgit.treewalk",
- org.eclipse.jgit.util.sha1;version="5.9.1",
- org.eclipse.jgit.util.time;version="5.9.1"
+ org.eclipse.jgit.util.sha1;version="5.10.1",
+ org.eclipse.jgit.util.time;version="5.10.1"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Import-Package: com.googlecode.javaewah;version="[1.1.6,2.0.0)",
javax.crypto,
diff --git a/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF b/org.eclipse.jgit/META-INF/SOURCE-MANIFEST.MF
index c561b7ede1..d6f1f52579 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.9.1.qualifier
-Eclipse-SourceBundle: org.eclipse.jgit;version="5.9.1.qualifier";roots="."
+Bundle-Version: 5.10.1.qualifier
+Eclipse-SourceBundle: org.eclipse.jgit;version="5.10.1.qualifier";roots="."
diff --git a/org.eclipse.jgit/pom.xml b/org.eclipse.jgit/pom.xml
index c899dfd293..4f17be524f 100644
--- a/org.eclipse.jgit/pom.xml
+++ b/org.eclipse.jgit/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit-parent</artifactId>
- <version>5.9.1-SNAPSHOT</version>
+ <version>5.10.1-SNAPSHOT</version>
</parent>
<artifactId>org.eclipse.jgit</artifactId>
diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
index c5e7dc3efa..c52e307814 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -348,6 +348,9 @@ invalidFilter=Invalid filter: {0}
invalidGitdirRef = Invalid .git reference in file ''{0}''
invalidGitModules=Invalid .gitmodules file
invalidGitType=invalid git type: {0}
+invalidHeaderFormat=Invalid header from git config http.extraHeader ignored: no colon or empty key in header ''{0}''
+invalidHeaderKey=Invalid header from git config http.extraHeader ignored: key contains illegal characters; see RFC 7230: ''{0}''
+invalidHeaderValue=Invalid header from git config http.extraHeader ignored: value should be 7bit-ASCII characters only: ''{0}''
invalidHexString=Invalid hex string: {0}
invalidHomeDirectory=Invalid home directory: {0}
invalidHooksPath=Invalid git config core.hooksPath = {0}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
index 0dc5d5e7f7..847ab0a9a8 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CheckoutCommand.java
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
- * Copyright (C) 2011, Matthias Sohn <matthias.sohn@sap.com> and others
+ * Copyright (C) 2011, 2020 Matthias Sohn <matthias.sohn@sap.com> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -503,6 +503,11 @@ public class CheckoutCommand extends GitCommand<Ref> {
editor.add(new PathEdit(path) {
@Override
public void apply(DirCacheEntry ent) {
+ if (ent.getStage() != DirCacheEntry.STAGE_0) {
+ // A checkout on a conflicting file stages the checked
+ // out file and resolves the conflict.
+ ent.setStage(DirCacheEntry.STAGE_0);
+ }
ent.setObjectId(blobId);
ent.setFileMode(mode);
checkoutPath(ent, r,
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
index 30d7f9adc4..aba86fc361 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java
@@ -413,6 +413,10 @@ public class CloneCommand extends TransportCommand<CloneCommand, Git> {
return null;
}
+ if (idHEAD != null && idHEAD.isSymbolic()) {
+ return idHEAD.getTarget();
+ }
+
Ref master = result.getAdvertisedRef(Constants.R_HEADS
+ Constants.MASTER);
ObjectId objectId = master != null ? master.getObjectId() : null;
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 8d427385d4..6a9fbd4f63 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
@@ -9,6 +9,7 @@
*/
package org.eclipse.jgit.api;
+import static org.eclipse.jgit.lib.Constants.R_REFS;
import static org.eclipse.jgit.lib.Constants.R_TAGS;
import java.io.IOException;
@@ -73,6 +74,11 @@ public class DescribeCommand extends GitCommand<String> {
private List<FileNameMatcher> matchers = new ArrayList<>();
/**
+ * Whether to use all refs in the refs/ namespace
+ */
+ private boolean useAll;
+
+ /**
* Whether to use all tags (incl. lightweight) or not.
*/
private boolean useTags;
@@ -153,6 +159,22 @@ public class DescribeCommand extends GitCommand<String> {
}
/**
+ * Instead of using only the annotated tags, use any ref found in refs/
+ * namespace. This option enables matching any known branch,
+ * remote-tracking branch, or lightweight tag.
+ *
+ * @param all
+ * <code>true</code> enables matching any ref found in refs/
+ * like setting option --all in c git
+ * @return {@code this}
+ * @since 5.10
+ */
+ public DescribeCommand setAll(boolean all) {
+ this.useAll = all;
+ return this;
+ }
+
+ /**
* Instead of using only the annotated tags, use any tag found in refs/tags
* namespace. This option enables matching lightweight (non-annotated) tags
* or not.
@@ -186,7 +208,7 @@ public class DescribeCommand extends GitCommand<String> {
private String longDescription(Ref tag, int depth, ObjectId tip)
throws IOException {
return String.format(
- "%s-%d-g%s", tag.getName().substring(R_TAGS.length()), //$NON-NLS-1$
+ "%s-%d-g%s", formatRefName(tag.getName()), //$NON-NLS-1$
Integer.valueOf(depth), w.getObjectReader().abbreviate(tip)
.name());
}
@@ -244,8 +266,7 @@ public class DescribeCommand extends GitCommand<String> {
for (FileNameMatcher matcher : matchers) {
Stream<Ref> m = tags.stream().filter(
tag -> {
- matcher.append(
- tag.getName().substring(R_TAGS.length()));
+ matcher.append(formatRefName(tag.getName()));
boolean result = matcher.isMatch();
matcher.reset();
return result;
@@ -283,7 +304,7 @@ public class DescribeCommand extends GitCommand<String> {
}
Collection<Ref> tagList = repo.getRefDatabase()
- .getRefsByPrefix(R_TAGS);
+ .getRefsByPrefix(useAll ? R_REFS : R_TAGS);
Map<ObjectId, List<Ref>> tags = tagList.stream()
.filter(this::filterLightweightTags)
.collect(Collectors.groupingBy(this::getObjectIdFromRef));
@@ -336,7 +357,7 @@ public class DescribeCommand extends GitCommand<String> {
Optional<Ref> bestMatch = getBestMatch(tags.get(target));
if (bestMatch.isPresent()) {
return longDesc ? longDescription(bestMatch.get(), 0, target) :
- bestMatch.get().getName().substring(R_TAGS.length());
+ formatRefName(bestMatch.get().getName());
}
w.markStart(target);
@@ -408,6 +429,16 @@ public class DescribeCommand extends GitCommand<String> {
}
/**
+ * Removes the refs/ or refs/tags prefix from tag names
+ * @param name the name of the tag
+ * @return the tag name with its prefix removed
+ */
+ private String formatRefName(String name) {
+ return name.startsWith(R_TAGS) ? name.substring(R_TAGS.length()) :
+ name.substring(R_REFS.length());
+ }
+
+ /**
* Whether we use lightweight tags or not for describe Candidates
*
* @param ref
@@ -419,7 +450,7 @@ public class DescribeCommand extends GitCommand<String> {
private boolean filterLightweightTags(Ref ref) {
ObjectId id = ref.getObjectId();
try {
- return this.useTags || (id != null && (w.parseTag(id) != null));
+ return this.useAll || this.useTags || (id != null && (w.parseTag(id) != null));
} catch (IOException e) {
return false;
}
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 ac17d3a642..f4b8ac2e07 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/SubmoduleDeinitCommand.java
@@ -20,8 +20,10 @@ import java.util.Collections;
import java.util.List;
import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.InvalidConfigurationException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoHeadException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.ObjectId;
@@ -119,6 +121,8 @@ public class SubmoduleDeinitCommand
}
}
return results;
+ } catch (ConfigInvalidException e) {
+ throw new InvalidConfigurationException(e.getMessage(), e);
} catch (IOException e) {
throw new JGitInternalException(e.getMessage(), e);
}
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 73d2807eaf..8c342e267d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEditor.java
@@ -1,6 +1,6 @@
/*
- * Copyright (C) 2008-2009, Google Inc.
- * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> and others
+ * Copyright (C) 2008, 2009, Google Inc.
+ * Copyright (C) 2008, 2020 Shawn O. Pearce <spearce@spearce.org> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -139,10 +139,28 @@ public class DirCacheEditor extends BaseDirCacheEditor {
: eIdx;
fastAdd(ent);
} else {
- // Apply to all entries of the current path (different stages)
lastIdx = cache.nextEntry(eIdx);
- for (int i = eIdx; i < lastIdx; i++) {
- final DirCacheEntry ent = cache.getEntry(i);
+ if (lastIdx > eIdx + 1) {
+ // Apply to all entries of the current path (different
+ // stages). If any apply() resets the stage to STAGE_0, take
+ // only that entry and omit all others.
+ DirCacheEntry[] tmp = new DirCacheEntry[lastIdx - eIdx];
+ int n = 0;
+ for (int i = eIdx; i < lastIdx; i++) {
+ DirCacheEntry ent = cache.getEntry(i);
+ e.apply(ent);
+ if (ent.getStage() == DirCacheEntry.STAGE_0) {
+ fastAdd(ent);
+ n = 0;
+ break;
+ }
+ tmp[n++] = ent;
+ }
+ for (int i = 0; i < n; i++) {
+ fastAdd(tmp[i]);
+ }
+ } else {
+ DirCacheEntry ent = cache.getEntry(eIdx);
e.apply(ent);
fastAdd(ent);
}
@@ -257,7 +275,9 @@ public class DirCacheEditor extends BaseDirCacheEditor {
* {@link #apply(DirCacheEntry)} method. The editor will invoke apply once
* for each record in the index which matches the path name. If there are
* multiple records (for example in stages 1, 2 and 3), the edit instance
- * will be called multiple times, once for each stage.
+ * will be called multiple times, once for each stage. If any of these calls
+ * resets the stage to 0, only this entry will be taken and entries for
+ * other stages are discarded.
*/
public abstract static class PathEdit {
final byte[] path;
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 dcb84825fe..67edf50f44 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/dircache/DirCacheEntry.java
@@ -542,6 +542,24 @@ public class DirCacheEntry {
}
/**
+ * Sets the stage of an entry.
+ *
+ * @param stage
+ * to set, in the range [0..3]
+ * @throws IllegalArgumentException
+ * if the stage is outside the range [0..3]
+ * @since 5.10
+ */
+ public void setStage(int stage) {
+ if ((stage & ~0x3) != 0) {
+ throw new IllegalArgumentException(
+ "Invalid stage, must be in range [0..3]"); //$NON-NLS-1$
+ }
+ byte flags = info[infoOffset + P_FLAGS];
+ info[infoOffset + P_FLAGS] = (byte) ((flags & 0xCF) | (stage << 4));
+ }
+
+ /**
* Returns whether this entry should be skipped from the working tree.
*
* @return true if this entry should be skipepd.
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 814811d131..d12a243a8e 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -376,6 +376,9 @@ public class JGitText extends TranslationBundle {
/***/ public String invalidGitdirRef;
/***/ public String invalidGitModules;
/***/ public String invalidGitType;
+ /***/ public String invalidHeaderFormat;
+ /***/ public String invalidHeaderKey;
+ /***/ public String invalidHeaderValue;
/***/ public String invalidHexString;
/***/ public String invalidHomeDirectory;
/***/ public String invalidHooksPath;
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 c18a1895c3..1f2fe1057f 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
@@ -985,7 +985,8 @@ public class GC {
if (base == null || !n.startsWith(base)) {
try {
Path delete = packDir.resolve(n);
- Files.delete(delete);
+ FileUtils.delete(delete.toFile(),
+ FileUtils.RETRY | FileUtils.SKIP_MISSING);
LOG.warn(JGitText.get().deletedOrphanInPackDir, delete);
} catch (IOException e) {
LOG.error(e.getMessage(), e);
@@ -1173,6 +1174,7 @@ public class GC {
// create temporary files
String id = pw.computeName().getName();
File packdir = repo.getObjectDatabase().getPackDirectory();
+ packdir.mkdirs();
tmpPack = File.createTempFile("gc_", ".pack_tmp", packdir); //$NON-NLS-1$ //$NON-NLS-2$
final String tmpBase = tmpPack.getName()
.substring(0, tmpPack.getName().lastIndexOf('.'));
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
index 265b71dd2a..d32182864a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/ObjectDirectory.java
@@ -580,7 +580,7 @@ public class ObjectDirectory extends FileObjectDatabase {
@Override
void selectObjectRepresentation(PackWriter packer, ObjectToPack otp,
- WindowCursor curs) throws IOException {
+ WindowCursor curs) throws IOException {
selectObjectRepresentation(packer, otp, curs, null);
}
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 a51593b509..a369026c97 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/Config.java
@@ -20,6 +20,9 @@ package org.eclipse.jgit.lib;
import static java.nio.charset.StandardCharsets.UTF_8;
+import java.io.File;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
@@ -29,6 +32,7 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
+import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.events.ConfigChangedEvent;
import org.eclipse.jgit.events.ConfigChangedListener;
@@ -36,6 +40,7 @@ import org.eclipse.jgit.events.ListenerHandle;
import org.eclipse.jgit.events.ListenerList;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.RawParseUtils;
/**
@@ -475,6 +480,37 @@ public class Config {
}
/**
+ * Parse a string value and treat it as a file path, replacing a ~/ prefix
+ * by the user's home directory.
+ * <p>
+ * <b>Note:</b> this may throw {@link InvalidPathException} if the string is
+ * not a valid path.
+ * </p>
+ *
+ * @param section
+ * section the key is in.
+ * @param subsection
+ * subsection the key is in, or null if not in a subsection.
+ * @param name
+ * the key name.
+ * @param fs
+ * to use to convert the string into a path.
+ * @param resolveAgainst
+ * directory to resolve the path against if it is a relative
+ * path; {@code null} to use the Java process's current
+ * directory.
+ * @param defaultValue
+ * to return if no value was present
+ * @return the {@link Path}, or {@code defaultValue} if not set
+ * @since 5.10
+ */
+ public Path getPath(String section, String subsection, String name,
+ @NonNull FS fs, File resolveAgainst, Path defaultValue) {
+ return typedGetter.getPath(this, section, subsection, name, fs,
+ resolveAgainst, defaultValue);
+ }
+
+ /**
* Parse a list of {@link org.eclipse.jgit.transport.RefSpec}s from the
* configuration.
*
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
index dd4be345e7..0f2f6cff8a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/TypedConfigGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017, Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2017, 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -10,22 +10,26 @@
package org.eclipse.jgit.lib;
+import java.io.File;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.util.FS;
/**
- * Something that knows how to convert plain strings from a git
- * {@link org.eclipse.jgit.lib.Config} to typed values.
+ * Something that knows how to convert plain strings from a git {@link Config}
+ * to typed values.
*
* @since 4.9
*/
public interface TypedConfigGetter {
/**
- * Get a boolean value from a git {@link org.eclipse.jgit.lib.Config}.
+ * Get a boolean value from a git {@link Config}.
*
* @param config
* to get the value from
@@ -44,7 +48,7 @@ public interface TypedConfigGetter {
String name, boolean defaultValue);
/**
- * Parse an enumeration from a git {@link org.eclipse.jgit.lib.Config}.
+ * Parse an enumeration from a git {@link Config}.
*
* @param config
* to get the value from
@@ -65,7 +69,7 @@ public interface TypedConfigGetter {
String subsection, String name, T defaultValue);
/**
- * Obtain an integer value from a git {@link org.eclipse.jgit.lib.Config}.
+ * Obtain an integer value from a git {@link Config}.
*
* @param config
* to get the value from
@@ -83,7 +87,7 @@ public interface TypedConfigGetter {
int defaultValue);
/**
- * Obtain a long value from a git {@link org.eclipse.jgit.lib.Config}.
+ * Obtain a long value from a git {@link Config}.
*
* @param config
* to get the value from
@@ -102,7 +106,7 @@ public interface TypedConfigGetter {
/**
* Parse a numerical time unit, such as "1 minute", from a git
- * {@link org.eclipse.jgit.lib.Config}.
+ * {@link Config}.
*
* @param config
* to get the value from
@@ -124,10 +128,50 @@ public interface TypedConfigGetter {
long getTimeUnit(Config config, String section, String subsection,
String name, long defaultValue, TimeUnit wantUnit);
+ /**
+ * Parse a string value from a git {@link Config} and treat it as a file
+ * path, replacing a ~/ prefix by the user's home directory.
+ * <p>
+ * <b>Note:</b> this may throw {@link InvalidPathException} if the string is
+ * not a valid path.
+ * </p>
+ *
+ * @param config
+ * to get the path from.
+ * @param section
+ * section the key is in.
+ * @param subsection
+ * subsection the key is in, or null if not in a subsection.
+ * @param name
+ * the key name.
+ * @param fs
+ * to use to convert the string into a path.
+ * @param resolveAgainst
+ * directory to resolve the path against if it is a relative
+ * path.
+ * @param defaultValue
+ * to return if no value was present
+ * @return the {@link Path}, or {@code defaultValue} if not set
+ * @since 5.10
+ */
+ default Path getPath(Config config, String section, String subsection,
+ String name, @NonNull FS fs, File resolveAgainst,
+ Path defaultValue) {
+ String value = config.getString(section, subsection, name);
+ if (value == null) {
+ return defaultValue;
+ }
+ File file;
+ if (value.startsWith("~/")) { //$NON-NLS-1$
+ file = fs.resolve(fs.userHome(), value.substring(2));
+ } else {
+ file = fs.resolve(resolveAgainst, value);
+ }
+ return file.toPath();
+ }
/**
- * Parse a list of {@link org.eclipse.jgit.transport.RefSpec}s from a git
- * {@link org.eclipse.jgit.lib.Config}.
+ * Parse a list of {@link RefSpec}s from a git {@link Config}.
*
* @param config
* to get the list from
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogContext.java b/org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogContext.java
new file mode 100644
index 0000000000..fab0dd102a
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogContext.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2020, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.logging;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Singleton that collects performance logs.
+ *
+ * @since 5.10
+ */
+public class PerformanceLogContext {
+ /** Singleton instance that stores the statistics. */
+ private static final PerformanceLogContext INSTANCE = new PerformanceLogContext();
+
+ /** List that stores events as performance logs. */
+ private static final ThreadLocal<List<PerformanceLogRecord>> eventRecords = ThreadLocal
+ .withInitial(ArrayList::new);
+
+ private PerformanceLogContext() {
+ }
+
+ /**
+ * Get the instance of the context.
+ *
+ * @return instance of performance log context.
+ */
+ public static PerformanceLogContext getInstance() {
+ return INSTANCE;
+ }
+
+ /**
+ * Get the unmodifiable list of events as performance records.
+ *
+ * @return unmodifiable list of events as performance logs.
+ */
+ public List<PerformanceLogRecord> getEventRecords() {
+ return Collections.unmodifiableList(eventRecords.get());
+ }
+
+ /**
+ * Adds a performance log record to the current list of events.
+ *
+ * @param record
+ * performance log record that is going to be added.
+ */
+ public void addEvent(PerformanceLogRecord record) {
+ eventRecords.get().add(record);
+ }
+
+ /**
+ * Removes all of the existing records from the current list of events.
+ */
+ public void cleanEvents() {
+ eventRecords.remove();
+ }
+} \ No newline at end of file
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogRecord.java b/org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogRecord.java
new file mode 100644
index 0000000000..3dc5f20156
--- /dev/null
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/logging/PerformanceLogRecord.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2020, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+package org.eclipse.jgit.logging;
+
+/**
+ * Class to register a performance log record.
+ *
+ * @since 5.10
+ */
+public class PerformanceLogRecord {
+ /** Name of the recorded event. */
+ private String name;
+
+ /** Duration of the recorded event in milliseconds. */
+ private long durationMs;
+
+ /**
+ * Create a new performance log record for an event.
+ *
+ * @param name
+ * name of the event.
+ * @param durationMs
+ * duration in milliseconds of the event.
+ */
+ public PerformanceLogRecord(String name, long durationMs) {
+ this.name = name;
+ this.durationMs = durationMs;
+ }
+
+ /**
+ * Get the name of the recorded event.
+ *
+ * @return name of the recorded event.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Get the duration in milliseconds of the recorded event.
+ *
+ * @return duration in milliseconds of the recorded event.
+ */
+ public long getDurationMs() {
+ return durationMs;
+ }
+} \ No newline at end of file
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 645da0a068..4d18337fae 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
@@ -188,6 +188,13 @@ public class PackStatistics {
public long haves;
/**
+ * The count of wants that were not advertised by the server.
+ *
+ * @since 5.10
+ */
+ public long notAdvertisedWants;
+
+ /**
* Time in ms spent in the negotiation phase. For non-bidirectional
* transports (e.g., HTTP), this is only for the final request that
* sends back the pack file.
@@ -266,8 +273,16 @@ public class PackStatistics {
/** Time in ms spent writing the pack. */
public long timeWriting;
+ /** Time in ms spent checking reachability.
+ *
+ * @since 5.10
+ */
+ public long reachabilityCheckDuration;
+
/** Number of trees traversed in the walk when writing the pack.
- * @since 5.4*/
+ *
+ * @since 5.4
+ */
public long treesTraversed;
/**
@@ -349,6 +364,16 @@ public class PackStatistics {
}
/**
+ * Get the count of client wants that were not advertised by the server.
+ *
+ * @return count of client wants that were not advertised by the server.
+ * @since 5.10
+ */
+ public long getNotAdvertisedWants() {
+ return statistics.notAdvertisedWants;
+ }
+
+ /**
* Time in ms spent in the negotiation phase. For non-bidirectional
* transports (e.g., HTTP), this is only for the final request that sends
* back the pack file.
@@ -604,6 +629,18 @@ public class PackStatistics {
}
/**
+ * Get time in milliseconds spent checking if the client has access to the
+ * commits they are requesting.
+ *
+ * @return time in milliseconds spent checking if the client has access to the
+ * commits they are requesting.
+ * @since 5.10
+ */
+ public long getReachabilityCheckDuration() {
+ return statistics.reachabilityCheckDuration;
+ }
+
+ /**
* @return number of trees traversed in the walk when writing the pack.
* @since 5.4
*/
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 0ba5eb542d..bf77021b0c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/submodule/SubmoduleWalk.java
@@ -657,8 +657,11 @@ public class SubmoduleWalk implements AutoCloseable {
*
* @since 4.10
* @return name
+ * @throws ConfigInvalidException
+ * @throws IOException
*/
- public String getModuleName() {
+ public String getModuleName() throws IOException, ConfigInvalidException {
+ lazyLoadModulesConfig();
return getModuleName(path);
}
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 1417faee80..3a36398629 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
@@ -21,8 +21,11 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.errors.InvalidObjectIdException;
@@ -35,6 +38,7 @@ import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.SymbolicRef;
import org.eclipse.jgit.util.io.InterruptTimer;
import org.eclipse.jgit.util.io.TimeoutInputStream;
import org.eclipse.jgit.util.io.TimeoutOutputStream;
@@ -49,6 +53,8 @@ import org.eclipse.jgit.util.io.TimeoutOutputStream;
*/
abstract class BasePackConnection extends BaseConnection {
+ protected static final String CAPABILITY_SYMREF_PREFIX = "symref="; //$NON-NLS-1$
+
/** The repository this transport fetches into, or pushes out of. */
protected final Repository local;
@@ -228,10 +234,109 @@ abstract class BasePackConnection extends BaseConnection {
throw duplicateAdvertisement(name);
}
}
+ updateWithSymRefs(avail, extractSymRefsFromCapabilities(remoteCapablities));
available(avail);
}
/**
+ * Finds values in the given capabilities of the form:
+ *
+ * <pre>
+ * symref=<em>source</em>:<em>target</em>
+ * </pre>
+ *
+ * And returns a Map of source->target entries.
+ *
+ * @param capabilities
+ * the capabilities lines
+ * @return a Map of the symref entries from capabilities
+ * @throws NullPointerException
+ * if capabilities, or any entry in it, is null
+ */
+ static Map<String, String> extractSymRefsFromCapabilities(Collection<String> capabilities) {
+ final Map<String, String> symRefs = new LinkedHashMap<>();
+ for (String option : capabilities) {
+ if (option.startsWith(CAPABILITY_SYMREF_PREFIX)) {
+ String[] symRef = option
+ .substring(CAPABILITY_SYMREF_PREFIX.length())
+ .split(":", 2); //$NON-NLS-1$
+ if (symRef.length == 2) {
+ symRefs.put(symRef[0], symRef[1]);
+ }
+ }
+ }
+ return symRefs;
+ }
+
+ /**
+ * Updates the given refMap with {@link SymbolicRef}s defined by the given
+ * symRefs.
+ * <p>
+ * For each entry, symRef, in symRefs, whose value is a key in refMap, adds
+ * a new entry to refMap with that same key and value of a new
+ * {@link SymbolicRef} with source=symRef.key and
+ * target=refMap.get(symRef.value), then removes that entry from symRefs.
+ * <p>
+ * If refMap already contains an entry for symRef.key, it is replaced.
+ * </p>
+ * </p>
+ * <p>
+ * For example, given:
+ * </p>
+ *
+ * <pre>
+ * refMap.put("refs/heads/main", ref);
+ * symRefs.put("HEAD", "refs/heads/main");
+ * </pre>
+ *
+ * then:
+ *
+ * <pre>
+ * updateWithSymRefs(refMap, symRefs);
+ * </pre>
+ *
+ * has the <em>effect</em> of:
+ *
+ * <pre>
+ * refMap.put("HEAD",
+ * new SymbolicRef("HEAD", refMap.get(symRefs.remove("HEAD"))))
+ * </pre>
+ * <p>
+ * Any entry in symRefs whose value is not a key in refMap is ignored. Any
+ * circular symRefs are ignored.
+ * </p>
+ * <p>
+ * Upon completion, symRefs will contain only any unresolvable entries.
+ * </p>
+ *
+ * @param refMap
+ * a non-null, modifiable, Map to update, and the provider of
+ * symref targets.
+ * @param symRefs
+ * a non-null, modifiable, Map of symrefs.
+ * @throws NullPointerException
+ * if refMap or symRefs is null
+ */
+ static void updateWithSymRefs(Map<String, Ref> refMap, Map<String, String> symRefs) {
+ boolean haveNewRefMapEntries = !refMap.isEmpty();
+ while (!symRefs.isEmpty() && haveNewRefMapEntries) {
+ haveNewRefMapEntries = false;
+ final Iterator<Map.Entry<String, String>> iterator = symRefs.entrySet().iterator();
+ while (iterator.hasNext()) {
+ final Map.Entry<String, String> symRef = iterator.next();
+ if (!symRefs.containsKey(symRef.getValue())) { // defer forward reference
+ final Ref r = refMap.get(symRef.getValue());
+ if (r != null) {
+ refMap.put(symRef.getKey(), new SymbolicRef(symRef.getKey(), r));
+ haveNewRefMapEntries = true;
+ iterator.remove();
+ }
+ }
+ }
+ }
+ }
+
+ /**
* Create an exception to indicate problems finding a remote repository. The
* caller is expected to throw the returned exception.
*
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 79cba80e11..dc82f46197 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpConfig.java
@@ -14,9 +14,13 @@ package org.eclipse.jgit.transport;
import java.io.IOException;
import java.net.URISyntaxException;
import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
+import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Config;
@@ -56,6 +60,20 @@ public class HttpConfig {
public static final String SSL_VERIFY_KEY = "sslVerify"; //$NON-NLS-1$
/**
+ * git config key for the "userAgent" setting.
+ *
+ * @since 5.10
+ */
+ public static final String USER_AGENT = "userAgent"; //$NON-NLS-1$
+
+ /**
+ * git config key for the "extraHeader" setting.
+ *
+ * @since 5.10
+ */
+ public static final String EXTRA_HEADER = "extraHeader"; //$NON-NLS-1$
+
+ /**
* git config key for the "cookieFile" setting.
*
* @since 5.4
@@ -103,6 +121,8 @@ public class HttpConfig {
}
}).get().intValue();
+ private static final String ENV_HTTP_USER_AGENT = "GIT_HTTP_USER_AGENT"; //$NON-NLS-1$
+
/**
* Config values for http.followRedirect.
*/
@@ -143,6 +163,10 @@ public class HttpConfig {
private int maxRedirects;
+ private String userAgent;
+
+ private List<String> extraHeaders;
+
private String cookieFile;
private boolean saveCookies;
@@ -186,6 +210,27 @@ public class HttpConfig {
}
/**
+ * Get the "http.userAgent" setting
+ *
+ * @return the value of the "http.userAgent" setting
+ * @since 5.10
+ */
+ public String getUserAgent() {
+ return userAgent;
+ }
+
+ /**
+ * Get the "http.extraHeader" setting
+ *
+ * @return the value of the "http.extraHeader" setting
+ * @since 5.10
+ */
+ @NonNull
+ public List<String> getExtraHeaders() {
+ return extraHeaders == null ? Collections.emptyList() : extraHeaders;
+ }
+
+ /**
* Get the "http.cookieFile" setting
*
* @return the value of the "http.cookieFile" setting
@@ -265,11 +310,25 @@ public class HttpConfig {
if (redirectLimit < 0) {
redirectLimit = MAX_REDIRECTS;
}
+ String agent = config.getString(HTTP, null, USER_AGENT);
+ if (agent != null) {
+ agent = UserAgent.clean(agent);
+ }
+ userAgent = agent;
+ String[] headers = config.getStringList(HTTP, null, EXTRA_HEADER);
+ // https://git-scm.com/docs/git-config#Documentation/git-config.txt-httpextraHeader
+ // "an empty value will reset the extra headers to the empty list."
+ int start = findLastEmpty(headers) + 1;
+ if (start > 0) {
+ headers = Arrays.copyOfRange(headers, start, headers.length);
+ }
+ extraHeaders = Arrays.asList(headers);
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
postBufferSize = config.getInt(HTTP, match, POST_BUFFER_KEY,
@@ -283,6 +342,22 @@ public class HttpConfig {
if (newMaxRedirects >= 0) {
redirectLimit = newMaxRedirects;
}
+ String uriSpecificUserAgent = config.getString(HTTP, match,
+ USER_AGENT);
+ if (uriSpecificUserAgent != null) {
+ userAgent = UserAgent.clean(uriSpecificUserAgent);
+ }
+ String[] uriSpecificExtraHeaders = config.getStringList(HTTP, match,
+ EXTRA_HEADER);
+ if (uriSpecificExtraHeaders.length > 0) {
+ start = findLastEmpty(uriSpecificExtraHeaders) + 1;
+ if (start > 0) {
+ uriSpecificExtraHeaders = Arrays.copyOfRange(
+ uriSpecificExtraHeaders, start,
+ uriSpecificExtraHeaders.length);
+ }
+ extraHeaders = Arrays.asList(uriSpecificExtraHeaders);
+ }
String urlSpecificCookieFile = config.getString(HTTP, match,
COOKIE_FILE_KEY);
if (urlSpecificCookieFile != null) {
@@ -291,12 +366,26 @@ public class HttpConfig {
saveCookies = config.getBoolean(HTTP, match, SAVE_COOKIES_KEY,
saveCookies);
}
+ // Environment overrides config
+ agent = SystemReader.getInstance().getenv(ENV_HTTP_USER_AGENT);
+ if (!StringUtils.isEmptyOrNull(agent)) {
+ userAgent = UserAgent.clean(agent);
+ }
postBuffer = postBufferSize;
sslVerify = sslVerifyFlag;
followRedirects = followRedirectsMode;
maxRedirects = redirectLimit;
}
+ private int findLastEmpty(String[] values) {
+ for (int i = values.length - 1; i >= 0; i--) {
+ if (values[i] == null) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
/**
* Determines the best match from a set of subsection names (representing
* prefix URLs) for the given {@link URIish}.
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
index 0801b8a86a..715cbb48fb 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackParser.java
@@ -679,7 +679,8 @@ public abstract class PackParser {
verifySafeObject(tempObjectId, type, visit.data);
if (isCheckObjectCollisions() && readCurs.has(tempObjectId)) {
- checkObjectCollision(tempObjectId, type, visit.data);
+ checkObjectCollision(tempObjectId, type, visit.data,
+ visit.delta.sizeBeforeInflating);
}
PackedObjectInfo oe;
@@ -999,6 +1000,7 @@ public abstract class PackParser {
UnresolvedDelta n = onEndDelta();
n.position = streamPosition;
n.next = baseByPos.put(base, n);
+ n.sizeBeforeInflating = streamPosition() - streamPosition;
deltaCount++;
break;
}
@@ -1020,6 +1022,7 @@ public abstract class PackParser {
inflateAndSkip(Source.INPUT, sz);
UnresolvedDelta n = onEndDelta();
n.position = streamPosition;
+ n.sizeBeforeInflating = streamPosition() - streamPosition;
r.add(n);
deltaCount++;
break;
@@ -1071,9 +1074,11 @@ public abstract class PackParser {
verifySafeObject(tempObjectId, type, data);
}
+ long sizeBeforeInflating = streamPosition() - pos;
PackedObjectInfo obj = newInfo(tempObjectId, null, null);
obj.setOffset(pos);
obj.setType(type);
+ obj.setSize(sizeBeforeInflating);
onEndWholeObject(obj);
if (data != null)
onInflatedObjectData(obj, type, data);
@@ -1148,6 +1153,8 @@ public abstract class PackParser {
sz -= n;
}
}
+ stats.incrementObjectsDuplicated();
+ stats.incrementNumBytesDuplicated(obj.getSize());
} catch (MissingObjectException notLocal) {
// This is OK, we don't have a copy of the object locally
// but the API throws when we try to read it as usually it's
@@ -1155,15 +1162,17 @@ public abstract class PackParser {
}
}
- private void checkObjectCollision(AnyObjectId obj, int type, byte[] data)
- throws IOException {
+ private void checkObjectCollision(AnyObjectId obj, int type, byte[] data,
+ long sizeBeforeInflating) throws IOException {
try {
final ObjectLoader ldr = readCurs.open(obj, type);
final byte[] existingData = ldr.getCachedBytes(data.length);
if (!Arrays.equals(data, existingData)) {
- throw new IOException(MessageFormat.format(
- JGitText.get().collisionOn, obj.name()));
+ throw new IOException(MessageFormat
+ .format(JGitText.get().collisionOn, obj.name()));
}
+ stats.incrementObjectsDuplicated();
+ stats.incrementNumBytesDuplicated(sizeBeforeInflating);
} catch (MissingObjectException notLocal) {
// This is OK, we don't have a copy of the object locally
// but the API throws when we try to read it as usually its
@@ -1653,6 +1662,8 @@ public abstract class PackParser {
UnresolvedDelta next;
+ long sizeBeforeInflating;
+
/** @return offset within the input stream. */
public long getOffset() {
return position;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackedObjectInfo.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackedObjectInfo.java
index fc906de2a8..fe1209b6af 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackedObjectInfo.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/PackedObjectInfo.java
@@ -29,6 +29,8 @@ public class PackedObjectInfo extends ObjectIdOwnerMap.Entry {
private int type = Constants.OBJ_BAD;
+ private long sizeBeforeInflating;
+
PackedObjectInfo(final long headerOffset, final int packedCRC,
final AnyObjectId id) {
super(id);
@@ -108,4 +110,12 @@ public class PackedObjectInfo extends ObjectIdOwnerMap.Entry {
public void setType(int type) {
this.type = type;
}
+
+ void setSize(long sizeBeforeInflating) {
+ this.sizeBeforeInflating = sizeBeforeInflating;
+ }
+
+ long getSize() {
+ return sizeBeforeInflating;
+ }
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java
index bd8f5585d2..d7bc40006b 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/ReceivedPackStatistics.java
@@ -19,6 +19,7 @@ import org.eclipse.jgit.lib.Constants;
*/
public class ReceivedPackStatistics {
private long numBytesRead;
+ private long numBytesDuplicated;
private long numWholeCommit;
private long numWholeTree;
@@ -26,6 +27,7 @@ public class ReceivedPackStatistics {
private long numWholeTag;
private long numOfsDelta;
private long numRefDelta;
+ private long numObjectsDuplicated;
private long numDeltaCommit;
private long numDeltaTree;
@@ -42,6 +44,17 @@ public class ReceivedPackStatistics {
}
/**
+ * Get number of bytes of objects already in the local database
+ *
+ * @return number of bytes of objects appeared in both the pack sent by the
+ * client and the local database
+ * @since 5.10
+ */
+ public long getNumBytesDuplicated() {
+ return numBytesDuplicated;
+ }
+
+ /**
* Get number of whole commit objects in the pack
*
* @return number of whole commit objects in the pack
@@ -96,6 +109,17 @@ public class ReceivedPackStatistics {
}
/**
+ * Get number of objects already in the local database
+ *
+ * @return number of objects appeared in both the pack sent by the client
+ * and the local database
+ * @since 5.10
+ */
+ public long getNumObjectsDuplicated() {
+ return numObjectsDuplicated;
+ }
+
+ /**
* Get number of delta commit objects in the pack
*
* @return number of delta commit objects in the pack
@@ -134,6 +158,7 @@ public class ReceivedPackStatistics {
/** A builder for {@link ReceivedPackStatistics}. */
public static class Builder {
private long numBytesRead;
+ private long numBytesDuplicated;
private long numWholeCommit;
private long numWholeTree;
@@ -141,6 +166,7 @@ public class ReceivedPackStatistics {
private long numWholeTag;
private long numOfsDelta;
private long numRefDelta;
+ private long numObjectsDuplicated;
private long numDeltaCommit;
private long numDeltaTree;
@@ -157,6 +183,17 @@ public class ReceivedPackStatistics {
}
/**
+ * @param size
+ * additional bytes already in the local database
+ * @return this
+ * @since 5.10
+ */
+ Builder incrementNumBytesDuplicated(long size) {
+ numBytesDuplicated += size;
+ return this;
+ }
+
+ /**
* Increment a whole object count.
*
* @param type OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, or OBJ_TAG
@@ -196,6 +233,17 @@ public class ReceivedPackStatistics {
}
/**
+ * Increment the duplicated object count.
+ *
+ * @return this
+ * @since 5.10
+ */
+ Builder incrementObjectsDuplicated() {
+ numObjectsDuplicated++;
+ return this;
+ }
+
+ /**
* Increment a delta object count.
*
* @param type OBJ_COMMIT, OBJ_TREE, OBJ_BLOB, or OBJ_TAG
@@ -226,6 +274,7 @@ public class ReceivedPackStatistics {
ReceivedPackStatistics build() {
ReceivedPackStatistics s = new ReceivedPackStatistics();
s.numBytesRead = numBytesRead;
+ s.numBytesDuplicated = numBytesDuplicated;
s.numWholeCommit = numWholeCommit;
s.numWholeTree = numWholeTree;
s.numWholeBlob = numWholeBlob;
@@ -236,6 +285,7 @@ public class ReceivedPackStatistics {
s.numDeltaTree = numDeltaTree;
s.numDeltaBlob = numDeltaBlob;
s.numDeltaTag = numDeltaTag;
+ s.numObjectsDuplicated = numObjectsDuplicated;
return s;
}
}
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java
index b1fac2cffb..fff2938e5d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/SshConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 Thomas Wolf <thomas.wolf@paranor.ch> and others
+ * Copyright (C) 2018, 2020 Thomas Wolf <thomas.wolf@paranor.ch> and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Distribution License v. 1.0 which is available at
@@ -117,6 +117,34 @@ public final class SshConstants {
/** Key in an ssh config file. */
public static final String PROXY_COMMAND = "ProxyCommand";
+ /**
+ * Comma-separated list of jump hosts, defining a jump host chain <em>in
+ * reverse order</em>. Each jump host is a SSH URI or "[user@]host[:port]".
+ * <p>
+ * Reverse order means: to connect A->B->target, one can do in
+ * {@code ~/.ssh/config} either of:
+ * </p>
+ *
+ * <pre>
+ * Host target
+ * ProxyJump B,A
+ * </pre>
+ * <p>
+ * <em>or</em>
+ * </p>
+ *
+ * <pre>
+ * Host target
+ * ProxyJump B
+ *
+ * Host B
+ * ProxyJump A
+ * </pre>
+ *
+ * @since 5.10
+ */
+ public static final String PROXY_JUMP = "ProxyJump";
+
/** Key in an ssh config file. */
public static final String REMOTE_COMMAND = "RemoteCommand";
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 16169f028b..6768387e65 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportHttp.java
@@ -49,6 +49,7 @@ import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -900,7 +901,9 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
conn.setRequestProperty(HDR_ACCEPT_ENCODING, ENCODING_GZIP);
}
conn.setRequestProperty(HDR_PRAGMA, "no-cache"); //$NON-NLS-1$
- if (UserAgent.get() != null) {
+ if (http.getUserAgent() != null) {
+ conn.setRequestProperty(HDR_USER_AGENT, http.getUserAgent());
+ } else if (UserAgent.get() != null) {
conn.setRequestProperty(HDR_USER_AGENT, UserAgent.get());
}
int timeOut = getTimeout();
@@ -909,6 +912,7 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
conn.setConnectTimeout(effTimeOut);
conn.setReadTimeout(effTimeOut);
}
+ addHeaders(conn, http.getExtraHeaders());
// set cookie header if necessary
if (!relevantCookies.isEmpty()) {
setCookieHeader(conn);
@@ -923,6 +927,44 @@ public class TransportHttp extends HttpTransport implements WalkTransport,
return conn;
}
+ /**
+ * Adds a list of header strings to the connection. Headers are expected to
+ * separate keys from values, i.e. "Key: Value". Headers without colon or
+ * key are ignored (and logged), as are headers with keys that are not RFC
+ * 7230 tokens or with non-ASCII values.
+ *
+ * @param conn
+ * The target HttpConnection
+ * @param headersToAdd
+ * A list of header strings
+ */
+ static void addHeaders(HttpConnection conn, List<String> headersToAdd) {
+ for (String header : headersToAdd) {
+ // Empty values are allowed according to
+ // https://tools.ietf.org/html/rfc7230
+ int colon = header.indexOf(':');
+ String key = null;
+ if (colon > 0) {
+ key = header.substring(0, colon).trim();
+ }
+ if (key == null || key.isEmpty()) {
+ LOG.warn(MessageFormat.format(
+ JGitText.get().invalidHeaderFormat, header));
+ } else if (HttpSupport.scanToken(key, 0) != key.length()) {
+ LOG.warn(MessageFormat.format(JGitText.get().invalidHeaderKey,
+ header));
+ } else {
+ String value = header.substring(colon + 1).trim();
+ if (!StandardCharsets.US_ASCII.newEncoder().canEncode(value)) {
+ LOG.warn(MessageFormat
+ .format(JGitText.get().invalidHeaderValue, header));
+ } else {
+ conn.setRequestProperty(key, value);
+ }
+ }
+ }
+ }
+
private void setCookieHeader(HttpConnection conn) {
StringBuilder cookieHeaderValue = new StringBuilder();
for (HttpCookie cookie : relevantCookies) {
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 9889015261..1242ef1b4a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UploadPack.java
@@ -42,6 +42,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.UncheckedIOException;
import java.text.MessageFormat;
+import java.time.Duration;
+import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -1008,7 +1010,7 @@ public class UploadPack {
else
advertised = refIdSet(getAdvertisedOrDefaultRefs().values());
- long negotiateStart = System.currentTimeMillis();
+ Instant negotiateStart = Instant.now();
accumulator.advertised = advertised.size();
ProtocolV0Parser parser = new ProtocolV0Parser(transferConfig);
@@ -1050,8 +1052,8 @@ public class UploadPack {
if (!req.getClientShallowCommits().isEmpty())
walk.assumeShallow(req.getClientShallowCommits());
sendPack = negotiate(req, accumulator, pckOut);
- accumulator.timeNegotiating += System.currentTimeMillis()
- - negotiateStart;
+ accumulator.timeNegotiating = Duration
+ .between(negotiateStart, Instant.now()).toMillis();
if (sendPack && !biDirectionalPipe) {
// Ensure the request was fully consumed. Any remaining input must
@@ -1137,6 +1139,9 @@ public class UploadPack {
advertised = refIdSet(getAdvertisedOrDefaultRefs().values());
}
+ PackStatistics.Accumulator accumulator = new PackStatistics.Accumulator();
+ Instant negotiateStart = Instant.now();
+
ProtocolV2Parser parser = new ProtocolV2Parser(transferConfig);
FetchV2Request req = parser.parseFetchRequest(pckIn);
currentRequest = req;
@@ -1186,7 +1191,8 @@ public class UploadPack {
if (req.wasDoneReceived()) {
processHaveLines(req.getPeerHas(), ObjectId.zeroId(),
- new PacketLineOut(NullOutputStream.INSTANCE));
+ new PacketLineOut(NullOutputStream.INSTANCE),
+ accumulator);
} else {
pckOut.writeString("acknowledgments\n"); //$NON-NLS-1$
for (ObjectId id : req.getPeerHas()) {
@@ -1195,7 +1201,8 @@ public class UploadPack {
}
}
processHaveLines(req.getPeerHas(), ObjectId.zeroId(),
- new PacketLineOut(NullOutputStream.INSTANCE));
+ new PacketLineOut(NullOutputStream.INSTANCE),
+ accumulator);
if (okToGiveUp()) {
pckOut.writeString("ready\n"); //$NON-NLS-1$
} else if (commonBase.isEmpty()) {
@@ -1238,7 +1245,11 @@ public class UploadPack {
// But sideband-all is not used, so we have to write it ourselves.
pckOut.writeString("packfile\n"); //$NON-NLS-1$
}
- sendPack(new PackStatistics.Accumulator(),
+
+ accumulator.timeNegotiating = Duration
+ .between(negotiateStart, Instant.now()).toMillis();
+
+ sendPack(accumulator,
req,
req.getClientCapabilities().contains(OPTION_INCLUDE_TAG)
? db.getRefDatabase().getRefsByPrefix(R_TAGS)
@@ -1641,7 +1652,7 @@ public class UploadPack {
}
if (PacketLineIn.isEnd(line)) {
- last = processHaveLines(peerHas, last, pckOut);
+ last = processHaveLines(peerHas, last, pckOut, accumulator);
if (commonBase.isEmpty() || multiAck != MultiAck.OFF)
pckOut.writeString("NAK\n"); //$NON-NLS-1$
if (noDone && sentReady) {
@@ -1656,7 +1667,7 @@ public class UploadPack {
peerHas.add(ObjectId.fromString(line.substring(5)));
accumulator.haves++;
} else if (line.equals("done")) { //$NON-NLS-1$
- last = processHaveLines(peerHas, last, pckOut);
+ last = processHaveLines(peerHas, last, pckOut, accumulator);
if (commonBase.isEmpty())
pckOut.writeString("NAK\n"); //$NON-NLS-1$
@@ -1672,11 +1683,12 @@ public class UploadPack {
}
}
- private ObjectId processHaveLines(List<ObjectId> peerHas, ObjectId last, PacketLineOut out)
+ private ObjectId processHaveLines(List<ObjectId> peerHas, ObjectId last,
+ PacketLineOut out, PackStatistics.Accumulator accumulator)
throws IOException {
preUploadHook.onBeginNegotiateRound(this, wantIds, peerHas.size());
if (wantAll.isEmpty() && !wantIds.isEmpty())
- parseWants();
+ parseWants(accumulator);
if (peerHas.isEmpty())
return last;
@@ -1773,7 +1785,7 @@ public class UploadPack {
return last;
}
- private void parseWants() throws IOException {
+ private void parseWants(PackStatistics.Accumulator accumulator) throws IOException {
List<ObjectId> notAdvertisedWants = null;
for (ObjectId obj : wantIds) {
if (!advertised.contains(obj)) {
@@ -1782,9 +1794,18 @@ public class UploadPack {
notAdvertisedWants.add(obj);
}
}
- if (notAdvertisedWants != null)
+ if (notAdvertisedWants != null) {
+ accumulator.notAdvertisedWants = notAdvertisedWants.size();
+
+ Instant startReachabilityChecking = Instant.now();
+
requestValidator.checkWants(this, notAdvertisedWants);
+ accumulator.reachabilityCheckDuration = Duration
+ .between(startReachabilityChecking, Instant.now())
+ .toMillis();
+ }
+
AsyncRevObjectQueue q = walk.parseAny(wantIds, true);
try {
RevObject obj;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java
index 5b63635e5a..604eb3a66c 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/UserAgent.java
@@ -46,7 +46,7 @@ public class UserAgent {
return "unknown"; //$NON-NLS-1$
}
- private static String clean(String s) {
+ static String clean(String s) {
s = s.trim();
StringBuilder b = new StringBuilder(s.length());
for (int i = 0; i < s.length(); i++) {
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 4c26dd0c40..72278dc9c3 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/WorkingTreeIterator.java
@@ -25,6 +25,7 @@ import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
+import java.nio.file.Path;
import java.text.MessageFormat;
import java.time.Instant;
import java.util.Arrays;
@@ -48,8 +49,8 @@ import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.ignore.FastIgnoreRule;
import org.eclipse.jgit.ignore.IgnoreNode;
import org.eclipse.jgit.internal.JGitText;
+import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.CoreConfig;
import org.eclipse.jgit.lib.CoreConfig.CheckStat;
import org.eclipse.jgit.lib.CoreConfig.EolStreamType;
import org.eclipse.jgit.lib.CoreConfig.SymLinks;
@@ -1308,15 +1309,11 @@ public abstract class WorkingTreeIterator extends AbstractTreeIterator {
}
FS fs = repository.getFS();
- String path = repository.getConfig().get(CoreConfig.KEY)
- .getExcludesFile();
+ Path path = repository.getConfig().getPath(
+ ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_EXCLUDESFILE, fs, null, null);
if (path != null) {
- File excludesfile;
- if (path.startsWith("~/")) //$NON-NLS-1$
- excludesfile = fs.resolve(fs.userHome(), path.substring(2));
- else
- excludesfile = fs.resolve(null, path);
- loadRulesFromFile(r, excludesfile);
+ loadRulesFromFile(r, path.toFile());
}
File exclude = fs.resolve(repository.getDirectory(),
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java
index 19cda42485..4731f345bc 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/treewalk/filter/IndexDiffFilter.java
@@ -217,14 +217,15 @@ public class IndexDiffFilter extends TreeFilter {
*/
private void copyUntrackedFolders(String currentPath) {
String pathToBeSaved = null;
- while (!untrackedParentFolders.isEmpty()
- && !currentPath.startsWith(untrackedParentFolders.getFirst()
- + "/")) //$NON-NLS-1$
+ while (!untrackedParentFolders.isEmpty() && !currentPath
+ .startsWith(untrackedParentFolders.getFirst() + '/')) {
pathToBeSaved = untrackedParentFolders.removeFirst();
+ }
if (pathToBeSaved != null) {
- while (!untrackedFolders.isEmpty()
- && untrackedFolders.getLast().startsWith(pathToBeSaved))
+ while (!untrackedFolders.isEmpty() && untrackedFolders.getLast()
+ .startsWith(pathToBeSaved + '/')) {
untrackedFolders.removeLast();
+ }
untrackedFolders.addLast(pathToBeSaved);
}
}
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 bf7b753693..d8cab358e7 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FS.java
@@ -1080,8 +1080,9 @@ public abstract class FS {
}
/**
- * Set the last modified time of a file system object. If the OS/JRE support
- * symbolic links, the link is modified, not the target,
+ * Set the last modified time of a file system object.
+ * <p>
+ * For symlinks it sets the modified time of the link target.
*
* @param f
* a {@link java.io.File} object.
@@ -1097,8 +1098,9 @@ public abstract class FS {
}
/**
- * Set the last modified time of a file system object. If the OS/JRE support
- * symbolic links, the link is modified, not the target,
+ * Set the last modified time of a file system object.
+ * <p>
+ * For symlinks it sets the modified time of the link target.
*
* @param p
* a {@link Path} object.
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 c43956e53d..aa39a44642 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/FileUtils.java
@@ -710,6 +710,8 @@ public class FileUtils {
}
/**
+ * Set the last modified time of a file system object.
+ *
* @param file
* @param time
* @throws IOException
@@ -720,6 +722,8 @@ public class FileUtils {
}
/**
+ * Set the last modified time of a file system object.
+ *
* @param path
* @param time
* @throws IOException
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 8ff649bccc..04b3eab504 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/HttpSupport.java
@@ -424,6 +424,69 @@ public class HttpSupport {
}
}
+ /**
+ * Scan a RFC 7230 token as it appears in HTTP headers.
+ *
+ * @param header
+ * to scan in
+ * @param from
+ * index in {@code header} to start scanning at
+ * @return the index after the token, that is, on the first non-token
+ * character or {@code header.length}
+ * @throws IndexOutOfBoundsException
+ * if {@code from < 0} or {@code from > header.length()}
+ *
+ * @see <a href="https://tools.ietf.org/html/rfc7230#appendix-B">RFC 7230,
+ * Appendix B: Collected Grammar; "token" production</a>
+ * @since 5.10
+ */
+ public static int scanToken(String header, int from) {
+ int length = header.length();
+ int i = from;
+ if (i < 0 || i > length) {
+ throw new IndexOutOfBoundsException();
+ }
+ while (i < length) {
+ char c = header.charAt(i);
+ switch (c) {
+ case '!':
+ case '#':
+ case '$':
+ case '%':
+ case '&':
+ case '\'':
+ case '*':
+ case '+':
+ case '-':
+ case '.':
+ case '^':
+ case '_':
+ case '`':
+ case '|':
+ case '~':
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ i++;
+ break;
+ default:
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+ i++;
+ break;
+ }
+ return i;
+ }
+ }
+ return i;
+ }
+
private HttpSupport() {
// Utility class only.
}