summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Sohn <matthias.sohn@sap.com>2018-06-14 00:00:30 +0200
committerMatthias Sohn <matthias.sohn@sap.com>2018-06-14 00:00:30 +0200
commit331f1a8e49dbd619d501f925210df31b0d9db2ea (patch)
tree186c632429b7688dd67dd1a7f0f4f86ca22adca8
parent44137491dc5e0fb428cacd6df1d7a958c7eba070 (diff)
parent0dbaf9d951e78a6b0aec0c2aac3153570c4b9a9f (diff)
downloadjgit-331f1a8e49dbd619d501f925210df31b0d9db2ea.tar.gz
jgit-331f1a8e49dbd619d501f925210df31b0d9db2ea.zip
Merge branch 'stable-5.0'
* stable-5.0: Prepare 5.0.1-SNAPSHOT builds JGit v5.0.0.201806131550-r JGit v5.0.0.201806131210-r Downgrade Apache httpclient to 4.5.2.v20170210-0925 RefUpdateTest: Refactor to not use deprecated Repository#getAllRefs Propagate failure of ssh command to caller of SshSupport Make JGit describe behaves same as c-git for lightweight tags Fix issues with LFS on GitHub (SSH) Change-Id: I0471440919adfdbfc72996711d9e0bbd1f3cf477 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com>
-rw-r--r--org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsConfigInvalidException.java13
-rw-r--r--org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java57
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target9
-rw-r--r--org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd8
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java181
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java44
-rw-r--r--org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java44
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/util/SshSupport.java58
10 files changed, 325 insertions, 91 deletions
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsConfigInvalidException.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsConfigInvalidException.java
index 5320af0b78..f90a003b4b 100644
--- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsConfigInvalidException.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/errors/LfsConfigInvalidException.java
@@ -63,4 +63,17 @@ public class LfsConfigInvalidException extends IOException {
super(msg);
}
+ /**
+ * Constructor for LfsConfigInvalidException.
+ *
+ * @param msg
+ * the error description
+ * @param e
+ * cause of this exception
+ * @since 5.0
+ */
+ public LfsConfigInvalidException(String msg, Exception e) {
+ super(msg, e);
+ }
+
}
diff --git a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java
index 3ac69923f2..955eca0c3f 100644
--- a/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java
+++ b/org.eclipse.jgit.lfs/src/org/eclipse/jgit/lfs/internal/LfsConnectionFactory.java
@@ -49,6 +49,7 @@ import static org.eclipse.jgit.util.HttpSupport.HDR_CONTENT_TYPE;
import java.io.IOException;
import java.net.ProxySelector;
+import java.net.URISyntaxException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
@@ -56,6 +57,7 @@ import java.util.Map;
import java.util.TreeMap;
import org.eclipse.jgit.annotations.NonNull;
+import org.eclipse.jgit.errors.CommandFailedException;
import org.eclipse.jgit.lfs.LfsPointer;
import org.eclipse.jgit.lfs.Protocol;
import org.eclipse.jgit.lfs.errors.LfsConfigInvalidException;
@@ -74,7 +76,7 @@ import org.eclipse.jgit.util.SshSupport;
*/
public class LfsConnectionFactory {
- private static final int SSH_AUTH_TIMEOUT_SECONDS = 5;
+ private static final int SSH_AUTH_TIMEOUT_SECONDS = 30;
private static final String SCHEME_HTTPS = "https"; //$NON-NLS-1$
private static final String SCHEME_SSH = "ssh"; //$NON-NLS-1$
private static final Map<String, AuthCache> sshAuthCache = new TreeMap<>();
@@ -128,6 +130,7 @@ public class LfsConnectionFactory {
String lfsUrl = config.getString(ConfigConstants.CONFIG_SECTION_LFS,
null,
ConfigConstants.CONFIG_KEY_URL);
+ Exception ex = null;
if (lfsUrl == null) {
String remoteUrl = null;
for (String remote : db.getRemoteNames()) {
@@ -146,38 +149,44 @@ public class LfsConnectionFactory {
break;
}
if (lfsUrl == null && remoteUrl != null) {
- lfsUrl = discoverLfsUrl(db, purpose, additionalHeaders,
- remoteUrl);
+ try {
+ lfsUrl = discoverLfsUrl(db, purpose, additionalHeaders,
+ remoteUrl);
+ } catch (URISyntaxException | IOException
+ | CommandFailedException e) {
+ ex = e;
+ }
} else {
lfsUrl = lfsUrl + Protocol.INFO_LFS_ENDPOINT;
}
}
if (lfsUrl == null) {
+ if (ex != null) {
+ throw new LfsConfigInvalidException(
+ LfsText.get().lfsNoDownloadUrl, ex);
+ }
throw new LfsConfigInvalidException(LfsText.get().lfsNoDownloadUrl);
}
return lfsUrl;
}
private static String discoverLfsUrl(Repository db, String purpose,
- Map<String, String> additionalHeaders, String remoteUrl) {
- try {
- URIish u = new URIish(remoteUrl);
- if (SCHEME_SSH.equals(u.getScheme())) {
- Protocol.ExpiringAction action = getSshAuthentication(
- db, purpose, remoteUrl, u);
- additionalHeaders.putAll(action.header);
- return action.href;
- } else {
- return remoteUrl + Protocol.INFO_LFS_ENDPOINT;
- }
- } catch (Exception e) {
- return null; // could not discover
+ Map<String, String> additionalHeaders, String remoteUrl)
+ throws URISyntaxException, IOException, CommandFailedException {
+ URIish u = new URIish(remoteUrl);
+ if (u.getScheme() == null || SCHEME_SSH.equals(u.getScheme())) {
+ Protocol.ExpiringAction action = getSshAuthentication(db, purpose,
+ remoteUrl, u);
+ additionalHeaders.putAll(action.header);
+ return action.href;
+ } else {
+ return remoteUrl + Protocol.INFO_LFS_ENDPOINT;
}
}
private static Protocol.ExpiringAction getSshAuthentication(
Repository db, String purpose, String remoteUrl, URIish u)
- throws IOException {
+ throws IOException, CommandFailedException {
AuthCache cached = sshAuthCache.get(remoteUrl);
Protocol.ExpiringAction action = null;
if (cached != null && cached.validUntil > System.currentTimeMillis()) {
@@ -226,8 +235,10 @@ public class LfsConnectionFactory {
.create(contentUrl, HttpSupport
.proxyFor(ProxySelector.getDefault(), contentUrl));
contentServerConn.setRequestMethod(method);
- action.header
- .forEach((k, v) -> contentServerConn.setRequestProperty(k, v));
+ if (action.header != null) {
+ action.header.forEach(
+ (k, v) -> contentServerConn.setRequestProperty(k, v));
+ }
if (contentUrl.getProtocol().equals(SCHEME_HTTPS)
&& !repo.getConfig().getBoolean(HttpConfig.HTTP,
HttpConfig.SSL_VERIFY_KEY, true)) {
@@ -241,7 +252,13 @@ public class LfsConnectionFactory {
}
private static String extractProjectName(URIish u) {
- String path = u.getPath().substring(1);
+ String path = u.getPath();
+
+ // begins with a slash if the url contains a port (gerrit vs. github).
+ if (path.startsWith("/")) { //$NON-NLS-1$
+ path = path.substring(1);
+ }
+
if (path.endsWith(org.eclipse.jgit.lib.Constants.DOT_GIT)) {
return path.substring(0, path.length() - 4);
} else {
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
index 564b49326a..6f57c9d6a1 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/jgit-4.8.target
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde?>
<!-- generated with https://github.com/mbarbero/fr.obeo.releng.targetplatform -->
-<target name="jgit-4.8" sequenceNumber="1528373976">
+<target name="jgit-4.8" sequenceNumber="1528872727">
<locations>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.jetty.client" version="9.4.8.v20171121"/>
@@ -33,8 +33,6 @@
<unit id="org.apache.commons.logging.source" version="1.1.1.v201101211721"/>
<unit id="org.apache.httpcomponents.httpcore" version="4.4.6.v20170210-0925"/>
<unit id="org.apache.httpcomponents.httpcore.source" version="4.4.6.v20170210-0925"/>
- <unit id="org.apache.httpcomponents.httpclient" version="4.5.2.v20180410-1551"/>
- <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.2.v20180410-1551"/>
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
<unit id="org.apache.log4j.source" version="1.2.15.v201012070815"/>
<unit id="org.kohsuke.args4j" version="2.33.0.v20160323-2218"/>
@@ -69,6 +67,11 @@
<repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20180606145124/repository"/>
</location>
<location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
+ <unit id="org.apache.httpcomponents.httpclient" version="4.5.2.v20170210-0925"/>
+ <unit id="org.apache.httpcomponents.httpclient.source" version="4.5.2.v20170210-0925"/>
+ <repository location="http://download.eclipse.org/tools/orbit/downloads/drops/R20170919201930/repository/"/>
+ </location>
+ <location includeMode="slicer" includeAllPlatforms="false" includeSource="true" includeConfigurePhase="true" type="InstallableUnit">
<unit id="org.eclipse.osgi" version="0.0.0"/>
<repository location="http://download.eclipse.org/releases/oxygen/"/>
</location>
diff --git a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd
index 8497c2c871..808b9d6944 100644
--- a/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd
+++ b/org.eclipse.jgit.packaging/org.eclipse.jgit.target/orbit/R20180606145124-Photon.tpd
@@ -12,8 +12,6 @@ location "http://download.eclipse.org/tools/orbit/downloads/drops/R2018060614512
org.apache.commons.logging.source [1.1.1.v201101211721,1.1.1.v201101211721]
org.apache.httpcomponents.httpcore [4.4.6.v20170210-0925,4.4.6.v20170210-0925]
org.apache.httpcomponents.httpcore.source [4.4.6.v20170210-0925,4.4.6.v20170210-0925]
- org.apache.httpcomponents.httpclient [4.5.2.v20180410-1551,4.5.2.v20180410-1551]
- org.apache.httpcomponents.httpclient.source [4.5.2.v20180410-1551,4.5.2.v20180410-1551]
org.apache.log4j [1.2.15.v201012070815,1.2.15.v201012070815]
org.apache.log4j.source [1.2.15.v201012070815,1.2.15.v201012070815]
org.kohsuke.args4j [2.33.0.v20160323-2218,2.33.0.v20160323-2218]
@@ -45,4 +43,10 @@ location "http://download.eclipse.org/tools/orbit/downloads/drops/R2018060614512
org.slf4j.impl.log4j12.source [1.7.2.v20131105-2200,1.7.2.v20131105-2200]
com.jcraft.jzlib [1.1.1.v201205102305,1.1.1.v201205102305]
com.jcraft.jzlib.source [1.1.1.v201205102305,1.1.1.v201205102305]
+}
+
+location "http://download.eclipse.org/tools/orbit/downloads/drops/R20170919201930/repository/" {
+ // platform uses this outdated version of httpclient in Photon
+ org.apache.httpcomponents.httpclient [4.5.2.v20170210-0925,4.5.2.v20170210-0925]
+ org.apache.httpcomponents.httpclient.source [4.5.2.v20170210-0925,4.5.2.v20170210-0925]
} \ No newline at end of file
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
index 79da2da7ea..a422ef91cb 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/DescribeCommandTest.java
@@ -54,7 +54,6 @@ import java.util.Collection;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.RefNotFoundException;
-import org.eclipse.jgit.errors.InvalidPatternException;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Test;
@@ -68,13 +67,18 @@ public class DescribeCommandTest extends RepositoryTestCase {
private Git git;
- @Parameter
+ @Parameter(0)
public boolean useAnnotatedTags;
- @Parameters
+ @Parameter(1)
+ public boolean describeUseAllTags;
+
+ @Parameters(name = "git tag -a {0}?-a: with git describe {1}?--tags:")
public static Collection<Boolean[]> getUseAnnotatedTagsValues() {
- return Arrays.asList(new Boolean[][] { { Boolean.TRUE },
- { Boolean.FALSE } });
+ return Arrays.asList(new Boolean[][] { { Boolean.TRUE, Boolean.FALSE },
+ { Boolean.FALSE, Boolean.FALSE },
+ { Boolean.TRUE, Boolean.TRUE },
+ { Boolean.FALSE, Boolean.TRUE } });
}
@Override
@@ -99,35 +103,52 @@ public class DescribeCommandTest extends RepositoryTestCase {
tag("bob-t2");
ObjectId c4 = modify("ddd");
+ assertNameStartsWith(c4, "3e563c5");
assertNull(describe(c1));
assertNull(describe(c1, true));
assertNull(describe(c1, "a*", "b*", "c*"));
-
- assertEquals("alice-t1", describe(c2));
- assertEquals("alice-t1", describe(c2, "alice*"));
assertNull(describe(c2, "bob*"));
assertNull(describe(c2, "?ob*"));
- assertEquals("alice-t1", describe(c2, "a*", "b*", "c*"));
- assertEquals("bob-t2", describe(c3));
- assertEquals("bob-t2-0-g44579eb", describe(c3, true));
- assertEquals("alice-t1-1-g44579eb", describe(c3, "alice*"));
- assertEquals("alice-t1-1-g44579eb", describe(c3, "a??c?-t*"));
- assertEquals("bob-t2", describe(c3, "bob*"));
- assertEquals("bob-t2", describe(c3, "?ob*"));
- assertEquals("bob-t2", describe(c3, "a*", "b*", "c*"));
-
- assertNameStartsWith(c4, "3e563c5");
- // the value verified with git-describe(1)
- assertEquals("bob-t2-1-g3e563c5", describe(c4));
- assertEquals("bob-t2-1-g3e563c5", describe(c4, true));
- assertEquals("alice-t1-2-g3e563c5", describe(c4, "alice*"));
- assertEquals("bob-t2-1-g3e563c5", describe(c4, "bob*"));
- assertEquals("bob-t2-1-g3e563c5", describe(c4, "a*", "b*", "c*"));
+ if (useAnnotatedTags || describeUseAllTags) {
+ assertEquals("alice-t1", describe(c2));
+ assertEquals("alice-t1", describe(c2, "alice*"));
+ assertEquals("alice-t1", describe(c2, "a*", "b*", "c*"));
+
+ assertEquals("bob-t2", describe(c3));
+ assertEquals("bob-t2-0-g44579eb", describe(c3, true));
+ assertEquals("alice-t1-1-g44579eb", describe(c3, "alice*"));
+ assertEquals("alice-t1-1-g44579eb", describe(c3, "a??c?-t*"));
+ assertEquals("bob-t2", describe(c3, "bob*"));
+ assertEquals("bob-t2", describe(c3, "?ob*"));
+ assertEquals("bob-t2", describe(c3, "a*", "b*", "c*"));
+
+ // the value verified with git-describe(1)
+ assertEquals("bob-t2-1-g3e563c5", describe(c4));
+ assertEquals("bob-t2-1-g3e563c5", describe(c4, true));
+ assertEquals("alice-t1-2-g3e563c5", describe(c4, "alice*"));
+ assertEquals("bob-t2-1-g3e563c5", describe(c4, "bob*"));
+ assertEquals("bob-t2-1-g3e563c5", describe(c4, "a*", "b*", "c*"));
+ } else {
+ assertEquals(null, describe(c2));
+ assertEquals(null, describe(c3));
+ assertEquals(null, describe(c4));
+ }
// test default target
- assertEquals("bob-t2-1-g3e563c5", git.describe().call());
+ if (useAnnotatedTags) {
+ assertEquals("bob-t2-1-g3e563c5", git.describe().call());
+ assertEquals("bob-t2-1-g3e563c5",
+ git.describe().setTags(false).call());
+ assertEquals("bob-t2-1-g3e563c5",
+ git.describe().setTags(true).call());
+ } else {
+ assertEquals(null, git.describe().call());
+ assertEquals(null, git.describe().setTags(false).call());
+ assertEquals("bob-t2-1-g3e563c5",
+ git.describe().setTags(true).call());
+ }
}
@Test
@@ -137,7 +158,14 @@ public class DescribeCommandTest extends RepositoryTestCase {
tag("v1.1.1");
ObjectId c2 = modify("bbb");
- // Ensure that if we're interested in any tags, we get the first match as per Git behaviour
+ if (!useAnnotatedTags && !describeUseAllTags) {
+ assertEquals(null, describe(c1));
+ assertEquals(null, describe(c2));
+ return;
+ }
+
+ // Ensure that if we're interested in any tags, we get the first match
+ // as per Git behaviour
assertEquals("v1.0.0", describe(c1));
assertEquals("v1.0.0-1-g3747db3", describe(c2));
@@ -179,7 +207,11 @@ public class DescribeCommandTest extends RepositoryTestCase {
ObjectId c4 = merge(c2);
assertNameStartsWith(c4, "119892b");
- assertEquals("t-2-g119892b", describe(c4)); // 2 commits: c4 and c3
+ if (useAnnotatedTags || describeUseAllTags) {
+ assertEquals("2 commits: c4 and c3", "t-2-g119892b", describe(c4));
+ } else {
+ assertEquals(null, describe(c4));
+ }
assertNull(describe(c3));
assertNull(describe(c3, true));
}
@@ -211,14 +243,76 @@ public class DescribeCommandTest extends RepositoryTestCase {
branch("b", c1);
ObjectId c3 = modify("ccc");
+ assertNameStartsWith(c3, "0244e7f");
ObjectId c4 = merge(c2);
assertNameStartsWith(c4, "119892b");
- assertEquals("t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3
+
+ if (useAnnotatedTags || describeUseAllTags) {
+ assertEquals("t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3
+ assertEquals("t1-1-g0244e7f", describe(c3));
+ } else {
+ assertEquals(null, describe(c4));
+ assertEquals(null, describe(c3));
+ }
+ }
+
+ /**
+ * When t1 annotated dominates t2 lightweight tag
+ *
+ * <pre>
+ * t1 -+-> t2 -
+ * | |
+ * +-> c3 -+-> c4
+ * </pre>
+ *
+ * @throws Exception
+ */
+ @Test
+ public void t1AnnotatedDominatesT2lightweight() throws Exception {
+ ObjectId c1 = modify("aaa");
+ tag("t1", useAnnotatedTags);
+
+ ObjectId c2 = modify("bbb");
+ tag("t2", false);
+
+ assertNameStartsWith(c2, "3747db3");
+ if (useAnnotatedTags && !describeUseAllTags) {
+ assertEquals(
+ "only annotated tag t1 expected to be used for describe",
+ "t1-1-g3747db3", describe(c2)); // 1 commits: t2 overridden
+ // by t1
+ } else if (!useAnnotatedTags && !describeUseAllTags) {
+ assertEquals("no commits to describe expected", null, describe(c2));
+ } else {
+ assertEquals("lightweight tag t2 expected in describe", "t2",
+ describe(c2));
+ }
+
+ branch("b", c1);
+
+ ObjectId c3 = modify("ccc");
assertNameStartsWith(c3, "0244e7f");
- assertEquals("t1-1-g0244e7f", describe(c3));
+ if (useAnnotatedTags || describeUseAllTags) {
+ assertEquals("t1-1-g0244e7f", describe(c3));
+ }
+
+ ObjectId c4 = merge(c2);
+
+ assertNameStartsWith(c4, "119892b");
+ if (describeUseAllTags) {
+ assertEquals(
+ "2 commits for describe commit increment expected since lightweight tag: c4 and c3",
+ "t2-2-g119892b", describe(c4)); // 2 commits: c4 and c3
+ } else if (!useAnnotatedTags && !describeUseAllTags) {
+ assertEquals("no matching commits expected", null, describe(c4));
+ } else {
+ assertEquals(
+ "3 commits for describe commit increment expected since annotated tag: c4 and c3 and c2",
+ "t1-3-g119892b", describe(c4)); //
+ }
}
/**
@@ -246,7 +340,11 @@ public class DescribeCommandTest extends RepositoryTestCase {
ObjectId c4 = merge(t1);
assertNameStartsWith(c4, "bb389a4");
- assertEquals("t1-3-gbb389a4", describe(c4));
+ if (useAnnotatedTags || describeUseAllTags) {
+ assertEquals("t1-3-gbb389a4", describe(c4));
+ } else {
+ assertEquals(null, describe(c4));
+ }
}
/**
@@ -275,7 +373,11 @@ public class DescribeCommandTest extends RepositoryTestCase {
ObjectId c4 = merge(c2);
assertNameStartsWith(c4, "bb389a4");
- assertEquals("t2-4-gbb389a4", describe(c4));
+ if (useAnnotatedTags || describeUseAllTags) {
+ assertEquals("t2-4-gbb389a4", describe(c4));
+ } else {
+ assertEquals(null, describe(c4));
+ }
}
private ObjectId merge(ObjectId c2) throws GitAPIException {
@@ -289,10 +391,15 @@ public class DescribeCommandTest extends RepositoryTestCase {
}
private void tag(String tag) throws GitAPIException {
+ tag(tag, this.useAnnotatedTags);
+ }
+
+ private void tag(String tag, boolean annotatedTag) throws GitAPIException {
TagCommand tagCommand = git.tag().setName(tag)
- .setAnnotated(useAnnotatedTags);
- if (useAnnotatedTags)
+ .setAnnotated(annotatedTag);
+ if (annotatedTag) {
tagCommand.setMessage(tag);
+ }
tagCommand.call();
}
@@ -304,15 +411,17 @@ public class DescribeCommandTest extends RepositoryTestCase {
private String describe(ObjectId c1, boolean longDesc)
throws GitAPIException, IOException {
- return git.describe().setTarget(c1).setLong(longDesc).call();
+ return git.describe().setTarget(c1).setTags(describeUseAllTags)
+ .setLong(longDesc).call();
}
private String describe(ObjectId c1) throws GitAPIException, IOException {
return describe(c1, false);
}
- private String describe(ObjectId c1, String... patterns) throws GitAPIException, IOException, InvalidPatternException {
- return git.describe().setTarget(c1).setMatch(patterns).call();
+ private String describe(ObjectId c1, String... patterns) throws Exception {
+ return git.describe().setTarget(c1).setTags(describeUseAllTags)
+ .setMatch(patterns).call();
}
private static void assertNameStartsWith(ObjectId c4, String prefix) {
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java
index b2fae316c3..e1adeedc54 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/RefUpdateTest.java
@@ -62,6 +62,7 @@ import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Optional;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
@@ -110,11 +111,21 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
delete(db, ref, expected, exists, removed);
}
- private void delete(Repository repo, final RefUpdate ref, final Result expected,
- final boolean exists, final boolean removed) throws IOException {
- assertEquals(exists, repo.getAllRefs().containsKey(ref.getName()));
+ private void delete(Repository repo, final RefUpdate ref,
+ final Result expected, final boolean exists, final boolean removed)
+ throws IOException {
+ assertEquals(exists, getRef(repo, ref.getName()).isPresent());
assertEquals(expected, ref.delete());
- assertEquals(!removed, repo.getAllRefs().containsKey(ref.getName()));
+ assertEquals(!removed, getRef(repo, ref.getName()).isPresent());
+ }
+
+ private Optional<Ref> getRef(Repository repo, String name)
+ throws IOException {
+ return getRef(repo.getRefDatabase().getRefs(), name);
+ }
+
+ private Optional<Ref> getRef(List<Ref> refs, String name) {
+ return refs.stream().filter(r -> r.getName().equals(name)).findAny();
}
@Test
@@ -125,8 +136,7 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
ru.setNewObjectId(newid);
Result update = ru.update();
assertEquals(Result.NEW, update);
- final Ref r = db.getAllRefs().get(newRef);
- assertNotNull(r);
+ final Ref r = getRef(db, newRef).get();
assertEquals(newRef, r.getName());
assertNotNull(r.getObjectId());
assertNotSame(newid, r.getObjectId());
@@ -378,10 +388,10 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
@Test
public void testRefKeySameAsName() {
+ @SuppressWarnings("deprecation")
Map<String, Ref> allRefs = db.getAllRefs();
for (Entry<String, Ref> e : allRefs.entrySet()) {
assertEquals(e.getKey(), e.getValue().getName());
-
}
}
@@ -520,8 +530,8 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
*/
@Test
public void testRefsCacheAfterUpdate() throws Exception {
- // Do not use the defalt repo for this case.
- Map<String, Ref> allRefs = db.getAllRefs();
+ // Do not use the default repo for this case.
+ List<Ref> allRefs = db.getRefDatabase().getRefs();
ObjectId oldValue = db.resolve("HEAD");
ObjectId newValue = db.resolve("HEAD^");
// first make HEAD refer to loose ref
@@ -537,9 +547,9 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
update = updateRef.update();
assertEquals(Result.FAST_FORWARD, update);
- allRefs = db.getAllRefs();
- Ref master = allRefs.get("refs/heads/master");
- Ref head = allRefs.get("HEAD");
+ allRefs = db.getRefDatabase().getRefs();
+ Ref master = getRef(allRefs, "refs/heads/master").get();
+ Ref head = getRef(allRefs, "HEAD").get();
assertEquals("refs/heads/master", master.getName());
assertEquals("HEAD", head.getName());
assertTrue("is symbolic reference", head.isSymbolic());
@@ -557,8 +567,8 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
*/
@Test
public void testRefsCacheAfterUpdateLooseOnly() throws Exception {
- // Do not use the defalt repo for this case.
- Map<String, Ref> allRefs = db.getAllRefs();
+ // Do not use the default repo for this case.
+ List<Ref> allRefs = db.getRefDatabase().getRefs();
ObjectId oldValue = db.resolve("HEAD");
writeSymref(Constants.HEAD, "refs/heads/newref");
RefUpdate updateRef = db.updateRef(Constants.HEAD);
@@ -567,9 +577,9 @@ public class RefUpdateTest extends SampleDataRepositoryTestCase {
Result update = updateRef.update();
assertEquals(Result.NEW, update);
- allRefs = db.getAllRefs();
- Ref head = allRefs.get("HEAD");
- Ref newref = allRefs.get("refs/heads/newref");
+ allRefs = db.getRefDatabase().getRefs();
+ Ref head = getRef(allRefs, "HEAD").get();
+ Ref newref = getRef(allRefs, "refs/heads/newref").get();
assertEquals("refs/heads/newref", newref.getName());
assertEquals("HEAD", head.getName());
assertTrue("is symbolic reference", head.isSymbolic());
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 b608ca8533..809bdf2865 100644
--- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
+++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/JGitText.properties
@@ -629,6 +629,7 @@ sourceIsNotAWildcard=Source is not a wildcard.
sourceRefDoesntResolveToAnyObject=Source ref {0} doesn''t resolve to any object.
sourceRefNotSpecifiedForRefspec=Source ref not specified for refspec: {0}
squashCommitNotUpdatingHEAD=Squash commit -- not updating HEAD
+sshCommandFailed=Execution of ssh command ''{0}'' failed with error ''{1}''
sshUserNameError=Jsch error: failed to set SSH user name correctly to ''{0}''; using ''{1}'' picked up from SSH config file.
sslFailureExceptionMessage=Secure connection to {0} could not be stablished because of SSL problems
sslFailureInfo=A secure connection to {0}\ncould not be established because the server''s certificate could not be validated.
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 dc605a91e5..4d5e499571 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/DescribeCommand.java
@@ -104,6 +104,11 @@ public class DescribeCommand extends GitCommand<String> {
private List<IMatcher> matchers = new ArrayList<>();
/**
+ * Whether to use all tags (incl. lightweight) or not
+ */
+ private boolean useTags = false;
+
+ /**
* Constructor for DescribeCommand.
*
* @param repo
@@ -173,6 +178,22 @@ public class DescribeCommand extends GitCommand<String> {
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.
+ *
+ * @param tags
+ * <code>true</code> enables matching lightweight (non-annotated)
+ * tags like setting option --tags in c git
+ * @return {@code this}
+ * @since 5.0
+ */
+ public DescribeCommand setTags(boolean tags) {
+ this.useTags = tags;
+ return this;
+ }
+
private String longDescription(Ref tag, int depth, ObjectId tip)
throws IOException {
return String.format(
@@ -246,13 +267,14 @@ public class DescribeCommand extends GitCommand<String> {
public String call() throws GitAPIException {
try {
checkCallable();
-
- if (target == null)
+ if (target == null) {
setTarget(Constants.HEAD);
+ }
Collection<Ref> tagList = repo.getRefDatabase()
.getRefsByPrefix(R_TAGS);
Map<ObjectId, List<Ref>> tags = tagList.stream()
+ .filter(this::filterLightweightTags)
.collect(Collectors.groupingBy(this::getObjectIdFromRef));
// combined flags of all the candidate instances
@@ -376,4 +398,22 @@ public class DescribeCommand extends GitCommand<String> {
w.close();
}
}
+
+ /**
+ * Whether we use lightweight tags or not for describe Candidates
+ *
+ * @param ref
+ * reference under inspection
+ * @return true if it should be used for describe or not regarding
+ * {@link org.eclipse.jgit.api.DescribeCommand#useTags}
+ */
+ @SuppressWarnings("null")
+ private boolean filterLightweightTags(Ref ref) {
+ ObjectId id = ref.getObjectId();
+ try {
+ return this.useTags || (id != null && (w.parseTag(id) != null));
+ } catch (IOException e) {
+ return false;
+ }
+ }
}
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 2ac75e1c2f..f3029bf3a1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/JGitText.java
@@ -690,6 +690,7 @@ public class JGitText extends TranslationBundle {
/***/ public String sourceRefDoesntResolveToAnyObject;
/***/ public String sourceRefNotSpecifiedForRefspec;
/***/ public String squashCommitNotUpdatingHEAD;
+ /***/ public String sshCommandFailed;
/***/ public String sshUserNameError;
/***/ public String sslFailureExceptionMessage;
/***/ public String sslFailureInfo;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/SshSupport.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/SshSupport.java
index 96123ea670..913aa72867 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/SshSupport.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/SshSupport.java
@@ -42,12 +42,12 @@
*/
package org.eclipse.jgit.util;
-import java.io.BufferedReader;
import java.io.IOException;
-import java.io.InputStreamReader;
+import java.text.MessageFormat;
import org.eclipse.jgit.annotations.Nullable;
-import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.errors.CommandFailedException;
+import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.RemoteSession;
import org.eclipse.jgit.transport.SshSessionFactory;
@@ -76,27 +76,44 @@ public class SshSupport {
* @param command
* the remote command to execute.
* @param timeout
- * a timeout in seconds.
- * @return The first line of output read from stdout. Stderr is discarded.
+ * a timeout in seconds. The timeout may be exceeded in corner
+ * cases.
+ * @return The entire output read from stdout.
* @throws IOException
+ * @throws CommandFailedException
+ * if the ssh command execution failed, error message contains
+ * the content of stderr.
*/
public static String runSshCommand(URIish sshUri,
@Nullable CredentialsProvider provider, FS fs, String command,
- int timeout) throws IOException {
+ int timeout) throws IOException, CommandFailedException {
RemoteSession session = null;
Process process = null;
StreamCopyThread errorThread = null;
- try (MessageWriter stderr = new MessageWriter()) {
+ StreamCopyThread outThread = null;
+ CommandFailedException failure = null;
+ @SuppressWarnings("resource")
+ MessageWriter stderr = new MessageWriter();
+ try (MessageWriter stdout = new MessageWriter()) {
session = SshSessionFactory.getInstance().getSession(sshUri,
provider, fs, 1000 * timeout);
process = session.exec(command, 0);
errorThread = new StreamCopyThread(process.getErrorStream(),
stderr.getRawStream());
errorThread.start();
- try (BufferedReader reader = new BufferedReader(
- new InputStreamReader(process.getInputStream(),
- Constants.CHARSET))) {
- return reader.readLine();
+ outThread = new StreamCopyThread(process.getInputStream(),
+ stdout.getRawStream());
+ outThread.start();
+ try {
+ // waitFor with timeout has a bug - JSch' exitValue() throws the
+ // wrong exception type :(
+ if (process.waitFor() == 0) {
+ return stdout.toString();
+ } else {
+ return null; // still running after timeout
+ }
+ } catch (InterruptedException e) {
+ return null; // error
}
} finally {
if (errorThread != null) {
@@ -108,12 +125,31 @@ public class SshSupport {
errorThread = null;
}
}
+ if (outThread != null) {
+ try {
+ outThread.halt();
+ } catch (InterruptedException e) {
+ // Stop waiting and return anyway.
+ } finally {
+ outThread = null;
+ }
+ }
if (process != null) {
+ if (process.exitValue() != 0) {
+ failure = new CommandFailedException(process.exitValue(),
+ MessageFormat.format(
+ JGitText.get().sshCommandFailed, command,
+ stderr.toString()));
+ }
process.destroy();
}
+ stderr.close();
if (session != null) {
SshSessionFactory.getInstance().releaseSession(session);
}
+ if (failure != null) {
+ throw failure;
+ }
}
}