Merge branch 'Indore-2017.1.x'
authorDmitry Neverov <dmitry.neverov@gmail.com>
Mon, 17 Jul 2017 13:59:01 +0000 (15:59 +0200)
committerDmitry Neverov <dmitry.neverov@gmail.com>
Mon, 17 Jul 2017 13:59:01 +0000 (15:59 +0200)
13 files changed:
.idea/.name
.idea/libraries/TeamCity_server.xml
git-dsl/Git.xml
git-server-tc/src/META-INF/build-server-plugin-git-tc.xml
git-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/git/GitExternalChangeViewerExtension.java [new file with mode: 0644]
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/GitFileContentDispatcher.java
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/GitUrlSupport.java
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/ListFilesDispatcher.java
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/VcsHostingRepo.java [moved from git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/github/GitHubRepo.java with 54% similarity]
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/WellKnownHostingsUtil.java [new file with mode: 0644]
git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/github/GitHubUtil.java [deleted file]
git-tests/src/jetbrains/buildServer/buildTriggers/vcs/git/tests/WellKnownHostingsTest.java [new file with mode: 0644]
git-tests/src/testng.xml

index 2fdf873b57bebb91098ee76c4433c9c8482e6eff..5b3e4cb849477a35433b405c247ac69246a60180 100644 (file)
@@ -1 +1 @@
-git-plugin 2017.1.x
\ No newline at end of file
+git-plugin master
\ No newline at end of file
index 7936add9a55cd947229af2cd94a7e31a9f5f6aa1..71fcebff29ef93716ae36ee22e7a886e28ddd221 100644 (file)
@@ -2,6 +2,7 @@
   <library name="TeamCity server">\r
     <CLASSES>\r
       <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/server.jar!/" />\r
+      <root url="jar://$TeamCityDistribution$/webapps/ROOT/WEB-INF/lib/external-change-viewers.jar!/" />\r
     </CLASSES>\r
     <JAVADOC />\r
     <SOURCES />\r
index 69c5c1b38fa36e97c3cad7c868e9bc74b180bb25..1d42e6b2ff778e2b375c36b1cbd52ea6736c9895 100644 (file)
@@ -4,7 +4,7 @@
     <description>Git [VCS root](https://confluence.jetbrains.com/display/TCDL/Git)</description>
   </class>
   <params>
-    <param name="url">
+    <param name="url" mandatory="true">
       <description>Repository url</description>
     </param>
     <param name="push_url" dslName="pushUrl">
@@ -90,7 +90,7 @@
         <param name="username" dslName="userName">
           <description>Username to use, overwrites the username in the url</description>
         </param>
-        <param name="secure:password" dslName="password">
+        <param name="secure:password" dslName="password" mandatory="true">
           <description>Password to use</description>
         </param>
       </option>
         <param name="username" dslName="userName">
           <description>Username to use, overwrites the username in the url</description>
         </param>
-        <param name="teamcitySshKey" dslName="uploadedKey">
+        <param name="teamcitySshKey" dslName="uploadedKey" mandatory="true">
           <description>Name of the uploaded [SSH key](https://confluence.jetbrains.com/display/TCDL/SSH+Keys+Management) to use</description>
         </param>
         <param name="secure:passphrase" dslName="passphrase">
         <param name="username" dslName="userName">
           <description>Username to use, overwrites the username in the url</description>
         </param>
-        <param name="privateKeyPath" dslName="customKeyPath">
+        <param name="privateKeyPath" dslName="customKeyPath" mandatory="true">
           <description>Path to the SSH key on TeamCity server machine</description>
         </param>
         <param name="secure:passphrase" dslName="passphrase">
index 27bdc67948ad46c359326a166ac7df69cf8b87b5..7ad8f8f9fdfb8e2d394835dd924dd4f95bb8e6ad 100644 (file)
@@ -12,4 +12,5 @@
   <bean class="jetbrains.buildServer.buildTriggers.vcs.git.health.GitNotFoundHealthPage"/>
   <bean class="jetbrains.buildServer.buildTriggers.vcs.git.health.GitGcErrorsHealthReport"/>
   <bean class="jetbrains.buildServer.buildTriggers.vcs.git.health.GitGcErrorsHealthPage"/>
+  <bean class="jetbrains.buildServer.buildTriggers.vcs.git.GitExternalChangeViewerExtension"/>
 </beans>
\ No newline at end of file
diff --git a/git-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/git/GitExternalChangeViewerExtension.java b/git-server-tc/src/jetbrains/buildServer/buildTriggers/vcs/git/GitExternalChangeViewerExtension.java
new file mode 100644 (file)
index 0000000..1ca2f03
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package jetbrains.buildServer.buildTriggers.vcs.git;
+
+import jetbrains.buildServer.ExtensionHolder;
+import jetbrains.buildServer.serverSide.changeViewers.ExternalChangeViewerExtension;
+import jetbrains.buildServer.serverSide.changeViewers.PropertyType;
+import jetbrains.buildServer.vcs.VcsRoot;
+import org.eclipse.jgit.transport.URIish;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GitExternalChangeViewerExtension implements ExternalChangeViewerExtension {
+  public GitExternalChangeViewerExtension(@NotNull ExtensionHolder extensionHolder) {
+    extensionHolder.registerExtension(ExternalChangeViewerExtension.class, getClass().getName(), this);
+  }
+
+  @Nullable
+  @Override
+  public Map<String, String> getAvailableProperties(@NotNull final VcsRoot vcsRoot) {
+    if (!Constants.VCS_NAME.equals(vcsRoot.getVcsName())) return null;
+    String url = vcsRoot.getProperty(Constants.FETCH_URL);
+    if (url == null) return null;
+
+    URIish urIish;
+    try {
+      urIish = new URIish(url);
+    } catch (URISyntaxException e) {
+      return null;
+    }
+
+    VcsHostingRepo vcsHostingRepo = WellKnownHostingsUtil.getGitHubRepo(urIish);
+    if (vcsHostingRepo != null) {
+      final VcsHostingRepo finalVcsHostingRepo = vcsHostingRepo;
+      return new HashMap<String, String>() {{
+        put(PropertyType.CHANGE_SET_TYPE, finalVcsHostingRepo.repositoryUrl() + "/commit/${changeSetId}");
+        put(PropertyType.LINK_TEXT, "Open in GitHub");
+        put(PropertyType.LINK_ICON_CLASS, "icon-github");
+      }};
+    }
+
+    vcsHostingRepo = WellKnownHostingsUtil.getBitbucketRepo(urIish);
+    if (vcsHostingRepo != null) {
+      final VcsHostingRepo finalVcsHostingRepo = vcsHostingRepo;
+      return new HashMap<String, String>() {{
+        put(PropertyType.CHANGE_SET_TYPE, finalVcsHostingRepo.repositoryUrl() + "/commits/${changeSetId}");
+        put(PropertyType.LINK_TEXT, "Open in Bitbucket Cloud");
+        put(PropertyType.LINK_ICON_CLASS, "icon-bitbucket");
+      }};
+    }
+
+    vcsHostingRepo = WellKnownHostingsUtil.getGitlabRepo(urIish);
+    if (vcsHostingRepo != null) {
+      final VcsHostingRepo finalVcsHostingRepo = vcsHostingRepo;
+      return new HashMap<String, String>() {{
+        put(PropertyType.CHANGE_SET_TYPE, finalVcsHostingRepo.repositoryUrl() + "/commit/${changeSetId}");
+        put(PropertyType.LINK_TEXT, "Open in Gitlab.com");
+      }};
+    }
+
+    vcsHostingRepo = WellKnownHostingsUtil.getVSTSRepo(urIish);
+    if (vcsHostingRepo != null) {
+      final VcsHostingRepo finalVcsHostingRepo = vcsHostingRepo;
+      return new HashMap<String, String>() {{
+        put(PropertyType.CHANGE_SET_TYPE, finalVcsHostingRepo.repositoryUrl() + "/commit/${changeSetId}");
+        put(PropertyType.LINK_TEXT, "Open in Visual Studio Team Services");
+      }};
+    }
+
+    vcsHostingRepo = WellKnownHostingsUtil.getBitbucketServerRepo(urIish);
+    if (vcsHostingRepo != null) {
+      final VcsHostingRepo finalVcsHostingRepo = vcsHostingRepo;
+      return new HashMap<String, String>() {{
+        put(PropertyType.CHANGE_SET_TYPE, finalVcsHostingRepo.repositoryUrl() + "/commits/${changeSetId}");
+        put(PropertyType.LINK_TEXT, "Open in Bitbucket Server");
+        put(PropertyType.LINK_ICON_CLASS, "icon-bitbucket");
+      }};
+    }
+
+    return null;
+  }
+}
index 0714b52e086435c22fddb2182cf59ee787ecc64a..aa84f7a121b27a97d6b61d7749ec05fb90faa8ea 100644 (file)
@@ -17,8 +17,6 @@
 package jetbrains.buildServer.buildTriggers.vcs.git;
 
 import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubRawFileContentProvider;
-import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubRepo;
-import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubUtil;
 import jetbrains.buildServer.vcs.*;
 import org.jetbrains.annotations.NotNull;
 
@@ -63,10 +61,10 @@ public class GitFileContentDispatcher implements VcsFileContentProvider {
     try {
       if (GitServerUtil.isCloned(ctx.getRepository()))
         return genericProvider;
-      GitHubRepo ghRepo = GitHubUtil.getGitHubRepo(ctx.getGitRoot().getRepositoryFetchURL());
+      VcsHostingRepo ghRepo = WellKnownHostingsUtil.getGitHubRepo(ctx.getGitRoot().getRepositoryFetchURL());
       if (ghRepo == null)
         return genericProvider;
-      return new GitHubRawFileContentProvider(myVcs, genericProvider, ghRepo.owner(), ghRepo.repo());
+      return new GitHubRawFileContentProvider(myVcs, genericProvider, ghRepo.owner(), ghRepo.repoName());
     } catch (Exception e) {
       //LOG
       return genericProvider;
index 86c8b8990d0659237405d31c479d56b2b675148c..fb8f367af4091613ba144fa789e12dc9c996fc08 100644 (file)
@@ -16,8 +16,6 @@
 
 package jetbrains.buildServer.buildTriggers.vcs.git;
 
-import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubRepo;
-import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubUtil;
 import jetbrains.buildServer.util.positioning.PositionAware;
 import jetbrains.buildServer.util.positioning.PositionConstraint;
 import jetbrains.buildServer.vcs.*;
@@ -60,16 +58,19 @@ public class GitUrlSupport implements UrlSupport, PositionAware {
       throw new VcsException(e.getMessage(), e);
     }
 
-    if (fetchUrl.startsWith("https://") && !fetchUrl.endsWith(".git") && uri.getHost().contains("gitlab.com")) {
-      // for GitLab we need to add .git suffix to the fetch URL, otherwise, for some reason JGit can't work with this repository (although regular git command works)
-      fetchUrl = fetchUrl + ".git";
+    if (fetchUrl.startsWith("https://") && !fetchUrl.endsWith(".git")) {
+      VcsHostingRepo gitlabRepo = WellKnownHostingsUtil.getGitlabRepo(uri);
+      if (gitlabRepo != null) {
+        // for GitLab we need to add .git suffix to the fetch URL, otherwise, for some reason JGit can't work with this repository (although regular git command works)
+        fetchUrl = fetchUrl + ".git";
+      }
     }
 
     Map<String, String> props = new HashMap<>(myGitSupport.getDefaultVcsProperties());
     props.put(Constants.FETCH_URL, fetchUrl);
     props.putAll(getAuthSettings(url, uri));
 
-    GitHubRepo ghRepo = GitHubUtil.getGitHubRepo(uri);
+    VcsHostingRepo ghRepo = WellKnownHostingsUtil.getGitHubRepo(uri);
     if (ghRepo != null)
       refineGithubSettings(ghRepo, props);
 
@@ -86,14 +87,14 @@ public class GitUrlSupport implements UrlSupport, PositionAware {
     }
   }
 
-  private void refineGithubSettings(@NotNull GitHubRepo ghRepo, @NotNull Map<String, String> props) {
+  private void refineGithubSettings(@NotNull VcsHostingRepo ghRepo, @NotNull Map<String, String> props) {
     GitHubClient client = new GitHubClient();
     AuthSettings auth = new AuthSettings(props);
     if (auth.getAuthMethod() == AuthenticationMethod.PASSWORD && auth.getUserName() != null && auth.getPassword() != null) {
       client.setCredentials(auth.getUserName(), auth.getPassword());
     }
     try {
-      Repository r = new RepositoryService(client).getRepository(ghRepo.owner(), ghRepo.repo());
+      Repository r = new RepositoryService(client).getRepository(ghRepo.owner(), ghRepo.repoName());
       props.put(Constants.BRANCH_NAME, GitUtils.expandRef(r.getMasterBranch()));
     } catch (IOException e) {
       //ignore, cannot refine settings
index f8aeec3d7be063c27b90a2816fd195d1e860910a..2275b87c1bd79795d6c7d5c8d928195ce0957586 100644 (file)
@@ -17,8 +17,6 @@
 package jetbrains.buildServer.buildTriggers.vcs.git;
 
 import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubListFilesSupport;
-import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubRepo;
-import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubUtil;
 import jetbrains.buildServer.vcs.ListDirectChildrenPolicy;
 import jetbrains.buildServer.vcs.VcsException;
 import jetbrains.buildServer.vcs.VcsFileData;
@@ -57,10 +55,10 @@ public class ListFilesDispatcher implements ListDirectChildrenPolicy {
     try {
       if (GitServerUtil.isCloned(ctx.getRepository()))
         return genericListFiles;
-      GitHubRepo ghRepo = GitHubUtil.getGitHubRepo(ctx.getGitRoot().getRepositoryFetchURL());
+      VcsHostingRepo ghRepo = WellKnownHostingsUtil.getGitHubRepo(ctx.getGitRoot().getRepositoryFetchURL());
       if (ghRepo == null)
         return genericListFiles;
-      return new GitHubListFilesSupport(myVcs, genericListFiles, ghRepo.owner(), ghRepo.repo());
+      return new GitHubListFilesSupport(myVcs, genericListFiles, ghRepo.owner(), ghRepo.repoName());
     } catch (Exception e) {
       //LOG
       return genericListFiles;
similarity index 54%
rename from git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/github/GitHubRepo.java
rename to git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/VcsHostingRepo.java
index b5804f013189f9f8d851bc08c1203b73c5c634e6..2b9db511fd52395dddf2584c469092f82773357b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2017 JetBrains s.r.o.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * limitations under the License.
  */
 
-package jetbrains.buildServer.buildTriggers.vcs.git.github;
+package jetbrains.buildServer.buildTriggers.vcs.git;
 
-import com.intellij.openapi.util.Pair;
 import org.jetbrains.annotations.NotNull;
 
-public class GitHubRepo extends Pair<String, String> {
-  public GitHubRepo(@NotNull String owner, @NotNull String repo) {
-    super(owner, repo);
+public class VcsHostingRepo {
+  private final String myOwner;
+  private final String myRepoName;
+  private final String myRepositoryUrl;
+
+  public VcsHostingRepo(@NotNull String repositoryUrl, @NotNull String owner, @NotNull String repoName) {
+    myOwner = owner;
+    myRepoName = repoName;
+    myRepositoryUrl = repositoryUrl;
+  }
+
+  public String repositoryUrl() {
+    return myRepositoryUrl;
   }
 
   @NotNull
   public String owner() {
-    return first;
+    return myOwner;
   }
   @NotNull
-  public String repo() {
-    return second;
+  public String repoName() {
+    return myRepoName;
   }
 }
diff --git a/git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/WellKnownHostingsUtil.java b/git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/WellKnownHostingsUtil.java
new file mode 100644 (file)
index 0000000..99978c2
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package jetbrains.buildServer.buildTriggers.vcs.git;
+
+import org.eclipse.jgit.transport.URIish;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public final class WellKnownHostingsUtil {
+  private WellKnownHostingsUtil() {}
+
+  @Nullable
+  public static VcsHostingRepo getGitHubRepo(@NotNull URIish uri) {
+    if (!"github.com".equals(uri.getHost()))
+      return null;
+
+    return ownerProjectStyleRepo("https://github.com/", uri);
+  }
+
+  @Nullable
+  public static VcsHostingRepo getGitlabRepo(@NotNull URIish uri) {
+    if (!"gitlab.com".equals(uri.getHost()))
+      return null;
+
+    return ownerProjectStyleRepo("https://gitlab.com/", uri);
+  }
+
+  @Nullable
+  public static VcsHostingRepo getBitbucketRepo(@NotNull URIish uri) {
+    if (!"bitbucket.org".equals(uri.getHost()))
+      return null;
+
+    return ownerProjectStyleRepo("https://bitbucket.org/", uri);
+  }
+
+  @Nullable
+  public static VcsHostingRepo getBitbucketServerRepo(@NotNull URIish uri) {
+    String host = uri.getHost();
+    if (host == null)
+      return null;
+
+    String path = uri.getPath();
+    if (uri.getScheme() != null && uri.getScheme().startsWith("http") && path.endsWith(".git") && (path.startsWith("/scm/") || path.startsWith("/git/"))) {
+      // probably Bitbucket server
+      String ownerAndRepo = path.substring(5); // length of /scm/ or /git/
+      int slashIdx = ownerAndRepo.indexOf('/');
+      if (slashIdx == -1) return null;
+      String owner = ownerAndRepo.substring(0, slashIdx);
+      String repo = ownerAndRepo.substring(slashIdx+1, ownerAndRepo.length() - ".git".length());
+      if (repo.contains("/")) return null;
+
+      boolean personalRepo = '~' == owner.charAt(0);
+      if (personalRepo) {
+        owner = owner.substring(1);
+      }
+
+      String hostAndPort = host;
+      if (uri.getPort() > 0 && uri.getPort() != 80 && uri.getPort() != 443) {
+        hostAndPort += ":" + uri.getPort();
+      }
+
+      if (personalRepo) {
+        return new VcsHostingRepo(uri.getScheme() + "://" + hostAndPort + "/users/" + owner + "/repos/" + repo, owner, repo);
+      } else {
+        return new VcsHostingRepo(uri.getScheme() + "://" + hostAndPort + "/projects/" + owner + "/repos/" + repo, owner, repo);
+      }
+    }
+
+    return null;
+  }
+
+  @Nullable
+  public static VcsHostingRepo getVSTSRepo(@NotNull URIish uri) {
+    String host = uri.getHost();
+    if (host == null)
+      return null;
+
+    final int idx = host.indexOf(".visualstudio.com");
+    if (idx <= 0)
+      return null;
+
+    String owner = host.substring(0, idx);
+
+    String path = uri.getPath();
+    if (path == null)
+      return null;
+
+    int gitPrefixIdx = path.indexOf("_git/");
+    if (gitPrefixIdx == -1) return null;
+
+    String repoName = path.substring(gitPrefixIdx + "_git/".length());
+
+    return new VcsHostingRepo("https://" + host + "/_git/" + repoName, owner, repoName);
+  }
+
+  private static VcsHostingRepo ownerProjectStyleRepo(@NotNull String hostingUrl, @NotNull URIish uri) {
+    String path = uri.getPath();
+    if (path == null)
+      return null;
+    if (path.startsWith("/"))
+      path = path.substring(1);
+    int idx = path.indexOf("/");
+    if (idx <= 0)
+      return null;
+    String owner = path.substring(0, idx);
+    String repo = path.substring(idx + 1, path.length());
+    if (repo.endsWith(".git"))
+      repo = repo.substring(0, repo.length() - 4);
+    return new VcsHostingRepo(hostingUrl + owner + "/" + repo, owner, repo);
+  }
+
+}
diff --git a/git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/github/GitHubUtil.java b/git-server/src/jetbrains/buildServer/buildTriggers/vcs/git/github/GitHubUtil.java
deleted file mode 100644 (file)
index be62670..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2000-2014 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package jetbrains.buildServer.buildTriggers.vcs.git.github;
-
-import jetbrains.buildServer.vcs.VcsException;
-import org.eclipse.jgit.transport.URIish;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public final class GitHubUtil {
-  private GitHubUtil() {}
-
-  @Nullable
-  public static GitHubRepo getGitHubRepo(@NotNull URIish uri) throws VcsException {
-    if (!"github.com".equals(uri.getHost()))
-      return null;
-    String path = uri.getPath();
-    if (path == null)
-      return null;
-    if (path.startsWith("/"))
-      path = path.substring(1);
-    int idx = path.indexOf("/");
-    if (idx <= 0)
-      return null;
-    String owner = path.substring(0, idx);
-    String repo = path.substring(idx + 1, path.length());
-    if (repo.endsWith(".git"))
-      repo = repo.substring(0, repo.length() - 4);
-    return new GitHubRepo(owner, repo);
-  }
-
-}
diff --git a/git-tests/src/jetbrains/buildServer/buildTriggers/vcs/git/tests/WellKnownHostingsTest.java b/git-tests/src/jetbrains/buildServer/buildTriggers/vcs/git/tests/WellKnownHostingsTest.java
new file mode 100644 (file)
index 0000000..6c5cf2f
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package jetbrains.buildServer.buildTriggers.vcs.git.tests;
+
+import jetbrains.buildServer.BaseTestCase;
+import jetbrains.buildServer.buildTriggers.vcs.git.VcsHostingRepo;
+import jetbrains.buildServer.buildTriggers.vcs.git.WellKnownHostingsUtil;
+import org.eclipse.jgit.transport.URIish;
+import org.testng.annotations.Test;
+
+import java.net.URISyntaxException;
+
+@Test
+public class WellKnownHostingsTest extends BaseTestCase {
+  public void test_github_https() throws URISyntaxException {
+    String url = "https://github.com/JetBrains/teamcity-commit-hooks.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getGitHubRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://github.com/JetBrains/teamcity-commit-hooks", repo.repositoryUrl());
+    assertEquals("JetBrains", repo.owner());
+    assertEquals("teamcity-commit-hooks", repo.repoName());
+  }
+
+  public void test_github_ssh() throws URISyntaxException {
+    String url = "git@github.com:JetBrains/teamcity-commit-hooks.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getGitHubRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://github.com/JetBrains/teamcity-commit-hooks", repo.repositoryUrl());
+    assertEquals("JetBrains", repo.owner());
+    assertEquals("teamcity-commit-hooks", repo.repoName());
+  }
+
+  public void test_gitlab_https() throws URISyntaxException {
+    String url = "https://pavelsher@gitlab.com/pavelsher/testgitrepo.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getGitlabRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://gitlab.com/pavelsher/testgitrepo", repo.repositoryUrl());
+    assertEquals("pavelsher", repo.owner());
+    assertEquals("testgitrepo", repo.repoName());
+  }
+
+  public void test_gitlab_ssh() throws URISyntaxException {
+    String url = "git@gitlab.com:pavelsher/testgitrepo.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getGitlabRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://gitlab.com/pavelsher/testgitrepo", repo.repositoryUrl());
+    assertEquals("pavelsher", repo.owner());
+    assertEquals("testgitrepo", repo.repoName());
+  }
+
+  public void test_bitbucket_https() throws URISyntaxException {
+    String url = "https://owner@bitbucket.org/owner/testgitrepo.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getBitbucketRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://bitbucket.org/owner/testgitrepo", repo.repositoryUrl());
+    assertEquals("owner", repo.owner());
+    assertEquals("testgitrepo", repo.repoName());
+  }
+
+  public void test_bitbucket_ssh() throws URISyntaxException {
+    String url = "git@bitbucket.org:owner/testgitrepo.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getBitbucketRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://bitbucket.org/owner/testgitrepo", repo.repositoryUrl());
+    assertEquals("owner", repo.owner());
+    assertEquals("testgitrepo", repo.repoName());
+  }
+
+  public void test_bitbucket_server_http_personal_repo() throws URISyntaxException {
+    String url = "http://admin@localhost:7990/scm/~admin/personalrepo.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getBitbucketServerRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("http://localhost:7990/users/admin/repos/personalrepo", repo.repositoryUrl());
+    assertEquals("admin", repo.owner());
+    assertEquals("personalrepo", repo.repoName());
+  }
+
+  public void test_bitbucket_server_http_project_repo() throws URISyntaxException {
+    String url = "https://admin@localhost/scm/TP/projectrepo.git";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getBitbucketServerRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://localhost/projects/TP/repos/projectrepo", repo.repositoryUrl());
+    assertEquals("TP", repo.owner());
+    assertEquals("projectrepo", repo.repoName());
+  }
+
+  public void test_vsts_https() throws URISyntaxException {
+    String url = "https://spav5.visualstudio.com/_git/MyFirstProject";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getVSTSRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://spav5.visualstudio.com/_git/MyFirstProject", repo.repositoryUrl());
+    assertEquals("spav5", repo.owner());
+    assertEquals("MyFirstProject", repo.repoName());
+  }
+
+  public void test_vsts_ssh() throws URISyntaxException {
+    String url = "ssh://spav5@spav5.visualstudio.com:22/_git/MyFirstProject";
+    VcsHostingRepo repo = WellKnownHostingsUtil.getVSTSRepo(new URIish(url));
+    assertNotNull(repo);
+    assertEquals("https://spav5.visualstudio.com/_git/MyFirstProject", repo.repositoryUrl());
+    assertEquals("spav5", repo.owner());
+    assertEquals("MyFirstProject", repo.repoName());
+  }
+}
index d09d4765144c3670a74194aa251523b6fcf83a9c..576689fcf071cf1aef69a26245669d943d9f02fb 100755 (executable)
@@ -47,6 +47,7 @@
       <class name="jetbrains.buildServer.buildTriggers.vcs.git.tests.ContentProviderTest"/>
       <class name="jetbrains.buildServer.buildTriggers.vcs.git.tests.CollectChangesTest"/>
       <class name="jetbrains.buildServer.buildTriggers.vcs.git.tests.RevisionsCacheTest"/>
+      <class name="jetbrains.buildServer.buildTriggers.vcs.git.tests.WellKnownHostingsTest"/>
     </classes>
   </test>
 </suite>