changeset 959:9e67a769bcc1

fixing TW-48788 for the case of http/https URLs: for HTTP URL we can try to ask for Mercurial repository capabilities to check if it's in fact mercurial
author Pavel.Sher
date Tue, 21 Feb 2017 18:14:54 +0100
parents 6a16b17fcada
children 1aaf8dba4072
files .idea/libraries/TeamCityAPI_common.xml mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialUrlSupport.java
diffstat 2 files changed, 65 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/.idea/libraries/TeamCityAPI_common.xml	Fri Jul 22 12:41:21 2016 +0200
+++ b/.idea/libraries/TeamCityAPI_common.xml	Tue Feb 21 18:14:54 2017 +0100
@@ -3,6 +3,8 @@
     <CLASSES>
       <root url="jar://$TeamCityDistribution$/devPackage/common-api.jar!/" />
       <root url="jar://$TeamCityDistribution$/devPackage/serviceMessages.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/commons-httpclient-3.1.jar!/" />
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/commons-logging.jar!/" />
     </CLASSES>
     <JAVADOC />
     <SOURCES>
--- a/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialUrlSupport.java	Fri Jul 22 12:41:21 2016 +0200
+++ b/mercurial-server/src/jetbrains/buildServer/buildTriggers/vcs/mercurial/MercurialUrlSupport.java	Tue Feb 21 18:14:54 2017 +0100
@@ -16,11 +16,20 @@
 
 package jetbrains.buildServer.buildTriggers.vcs.mercurial;
 
+import jetbrains.buildServer.http.HttpUtil;
+import jetbrains.buildServer.log.Loggers;
 import jetbrains.buildServer.vcs.*;
 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
+import org.apache.commons.httpclient.Header;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpState;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.GetMethod;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.net.URL;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -47,6 +56,13 @@
       testRequired = false;
     }
 
+    if (fetchUrl.startsWith("http")) {
+      // check URL by sending HTTP request
+      if (isMercurialRepository(fetchUrl, url.getCredentials())) {
+        testRequired = false;
+      }
+    }
+
     Map<String, String> res = new HashMap<String, String>(myVcsSupport.getDefaultVcsProperties());
     res.put(Constants.REPOSITORY_PROP, fetchUrl);
     Credentials credentials = url.getCredentials();
@@ -58,7 +74,6 @@
     if (testRequired) {
       try {
         TestConnectionSupport testConnectionSupport = myVcsSupport.getTestConnectionSupport();
-        assert testConnectionSupport != null;
         testConnectionSupport.testConnection(new VcsRootImpl(-1, res));
       } catch (VcsException e) {
         return null;
@@ -67,4 +82,51 @@
 
     return res;
   }
+
+  private boolean isMercurialRepository(@NotNull String fetchUrl, @Nullable Credentials credentials) {
+    String capabilitiesUrl = fetchUrl;
+    if (capabilitiesUrl.endsWith("/")) {
+      capabilitiesUrl += "?cmd=capabilities";
+    } else {
+      capabilitiesUrl += "/?cmd=capabilities";
+    }
+
+    HttpClient client = HttpUtil.createHttpClient(30);
+    GetMethod get = new GetMethod(capabilitiesUrl);
+
+    try {
+      if (credentials != null) {
+        URL url = new URL(fetchUrl);
+        HttpState state = new HttpState();
+        state.setCredentials(new AuthScope(url.getHost(), url.getPort()), new UsernamePasswordCredentials(credentials.getUsername(), credentials.getPassword()));
+        client.setState(state);
+      }
+
+      // emulate HG command request
+      get.addRequestHeader("Accept-Encoding", "identity");
+      get.addRequestHeader("accept", "application/mercurial-0.1");
+      get.addRequestHeader("user-agent", "mercurial/proto-1.0");
+
+      int status = client.executeMethod(get);
+      if (status == 200) {
+        Header header = get.getResponseHeader("Content-Type");
+        if (header == null || !"application/mercurial-0.1".equals(header.getValue())) {
+          return false;
+        }
+
+        String text = get.getResponseBodyAsString();
+        if (text.contains("unbundle=HG10GZ,HG10BZ")) {
+          // looks like mercurial repo
+          return true;
+        }
+      }
+
+    } catch (Exception e) {
+      Loggers.VCS.debug("Got error while sending HTTP request to " + capabilitiesUrl, e);
+    } finally {
+      get.releaseConnection();
+    }
+
+    return false;
+  }
 }