TW-50733 specify full path to java in credential helper
[teamcity/git-plugin.git] / git-server / src / jetbrains / buildServer / buildTriggers / vcs / git / GitUrlSupport.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package jetbrains.buildServer.buildTriggers.vcs.git;
18
19 import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubRepo;
20 import jetbrains.buildServer.buildTriggers.vcs.git.github.GitHubUtil;
21 import jetbrains.buildServer.util.positioning.PositionAware;
22 import jetbrains.buildServer.util.positioning.PositionConstraint;
23 import jetbrains.buildServer.vcs.*;
24 import jetbrains.buildServer.vcs.impl.VcsRootImpl;
25 import org.eclipse.egit.github.core.Repository;
26 import org.eclipse.egit.github.core.client.GitHubClient;
27 import org.eclipse.egit.github.core.service.RepositoryService;
28 import org.eclipse.jgit.transport.URIish;
29 import org.jetbrains.annotations.NotNull;
30 import org.jetbrains.annotations.Nullable;
31
32 import java.io.IOException;
33 import java.net.URISyntaxException;
34 import java.util.HashMap;
35 import java.util.Map;
36
37 /**
38  * @author dmitry.neverov
39  */
40 public class GitUrlSupport implements UrlSupport, PositionAware {
41
42   private final GitVcsSupport myGitSupport;
43
44   public GitUrlSupport(@NotNull GitVcsSupport gitSupport) {
45     myGitSupport = gitSupport;
46   }
47
48   @Nullable
49   public Map<String, String> convertToVcsRootProperties(@NotNull VcsUrl url) throws VcsException {
50     String scmName = getMavenScmName(url);
51     if (scmName != null && !"git".equals(scmName) && !"ssh".equals(scmName)) //some other scm provider
52       return null;
53
54     String fetchUrl = getFetchUrl(url);
55
56     URIish uri;
57     try {
58       uri = new URIish(fetchUrl);
59     } catch (URISyntaxException e) {
60       throw new VcsException(e.getMessage(), e);
61     }
62
63     if (fetchUrl.startsWith("https://") && !fetchUrl.endsWith(".git") && uri.getHost().contains("gitlab.com")) {
64       // 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)
65       fetchUrl = fetchUrl + ".git";
66     }
67
68     Map<String, String> props = new HashMap<>(myGitSupport.getDefaultVcsProperties());
69     props.put(Constants.FETCH_URL, fetchUrl);
70     props.putAll(getAuthSettings(url, uri));
71
72     GitHubRepo ghRepo = GitHubUtil.getGitHubRepo(uri);
73     if (ghRepo != null)
74       refineGithubSettings(ghRepo, props);
75
76     if ("git".equals(scmName) || "git".equals(uri.getScheme()) || uri.getPath().endsWith(".git")) //git protocol, or git scm provider, or .git suffix
77       return props;
78
79     try {
80       myGitSupport.testConnection(new VcsRootImpl(-1, Constants.VCS_NAME, props));
81       return props;
82     } catch (VcsException e) {
83       if (GitServerUtil.isAuthError(e))
84         throw e;
85       return null; // probably not git
86     }
87   }
88
89   private void refineGithubSettings(@NotNull GitHubRepo ghRepo, @NotNull Map<String, String> props) {
90     GitHubClient client = new GitHubClient();
91     AuthSettings auth = new AuthSettings(props);
92     if (auth.getAuthMethod() == AuthenticationMethod.PASSWORD && auth.getUserName() != null && auth.getPassword() != null) {
93       client.setCredentials(auth.getUserName(), auth.getPassword());
94     }
95     try {
96       Repository r = new RepositoryService(client).getRepository(ghRepo.owner(), ghRepo.repo());
97       props.put(Constants.BRANCH_NAME, GitUtils.expandRef(r.getMasterBranch()));
98     } catch (IOException e) {
99       //ignore, cannot refine settings
100     }
101   }
102
103   @NotNull
104   private Map<String, String> getAuthSettings(@NotNull VcsUrl url, @NotNull URIish uri) {
105     Map<String, String> authSettings = new HashMap<String, String>();
106     authSettings.put(Constants.AUTH_METHOD, getAuthMethod(url, uri).toString());
107     Credentials credentials = url.getCredentials();
108     if (credentials != null) {
109       authSettings.put(Constants.USERNAME, credentials.getUsername());
110       authSettings.put(Constants.PASSWORD, credentials.getPassword());
111     } else {
112       authSettings.put(Constants.USERNAME, uri.getUser());
113     }
114     return authSettings;
115   }
116
117   private AuthenticationMethod getAuthMethod(@NotNull VcsUrl url, @NotNull URIish uri) {
118     if (isScpSyntax(uri) || "ssh".equals(uri.getScheme()))
119       return AuthenticationMethod.PRIVATE_KEY_DEFAULT;
120     if (url.getCredentials() != null)
121       return AuthenticationMethod.PASSWORD;
122     return AuthenticationMethod.ANONYMOUS;
123   }
124
125   @Nullable
126   private String getMavenScmName(@NotNull VcsUrl url) {
127     MavenVcsUrl mavenUrl = url.asMavenVcsUrl();
128     if (mavenUrl == null)
129       return null;
130     return mavenUrl.getProviderSchema();
131   }
132
133   @NotNull
134   private String getFetchUrl(@NotNull VcsUrl url) {
135     MavenVcsUrl mavenUrl = url.asMavenVcsUrl();
136     if (mavenUrl != null)
137       return mavenUrl.getProviderSpecificPart();
138     return url.getUrl();
139   }
140
141   private boolean isScpSyntax(URIish uriish) {
142     return uriish.getScheme() == null && uriish.isRemote();
143   }
144
145   @NotNull
146   public String getOrderId() {
147     return myGitSupport.getName();
148   }
149
150   @NotNull
151   public PositionConstraint getConstraint() {
152     return PositionConstraint.first(); // placed first to avoid problems with GitHub and SVN
153   }
154 }