in git-server/src/main/java/jetbrains/buildServer/buildTriggers/vcs/git/GitUrlSupport.java [81:206]
public Map<String, String> convertToVcsRootProperties(@NotNull VcsUrl url, @NotNull VcsOperationContext operationContext) throws VcsException {
String scmName = getMavenScmName(url);
if (scmName != null && !"git".equalsIgnoreCase(scmName) && !"ssh".equalsIgnoreCase(scmName)) //some other scm provider
return null;
String fetchUrl = getFetchUrl(url);
String lowerCaseFetchUrl = StringUtil.toLowerCase(fetchUrl);
if (!myConfig.isAllowFileUrl() && GitRemoteUrlInspector.isLocalFileAccess(fetchUrl)) {
throw new VcsException("The git fetch URL most not be a local file URL");
}
URIish uri = parseURIish(fetchUrl);
if (lowerCaseFetchUrl.startsWith("https://") && !lowerCaseFetchUrl.endsWith(".git") && !lowerCaseFetchUrl.endsWith(".git/")) {
VcsHostingRepo gitlabRepo = WellKnownHostingsUtil.getGitlabRepo(uri);
if (gitlabRepo != null) {
// if repo ends with a backslash, but does not have ".git" suffix, we have to remove the backslash for JGit to work
fetchUrl = StringUtil.removeTailingSlash(fetchUrl);
// 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";
uri = parseURIish(fetchUrl);
}
}
final SProject curProject = myProjectManager == null ? null : myProjectManager.findProjectById(operationContext.getCurrentProjectId());
Map<String, String> props = new HashMap<>(myGitSupport.getDefaultVcsProperties());
props.put(Constants.FETCH_URL, fetchUrl);
props.putAll(getAuthSettings(url, uri));
// GitHub api does not seem to work with uri ending with trailing slash, but git works with it.
// no need to remove "/" from actual uri stored in properties
uri = uri.setPath(StringUtil.removeTailingSlash(uri.getPath()));
VcsHostingRepo ghRepo = WellKnownHostingsUtil.getGitHubRepo(uri);
if (ghRepo != null && curProject != null)
refineGithubSettings(ghRepo, props, curProject);
if (AuthenticationMethod.PRIVATE_KEY_DEFAULT.toString().equals(props.get(Constants.AUTH_METHOD))
&& curProject != null
&& isSsh(uri)) {
ServerSshKeyManager serverSshKeyManager = getSshKeyManager();
int numSshKeysTried = 0;
if (serverSshKeyManager != null) {
Credentials credentials = url.getCredentials();
// if credentials are provided, trying to find matching key
if (credentials != null) {
TeamCitySshKey key = serverSshKeyManager.getKey(curProject, credentials.getUsername());
if (key != null) {
Map<String, String> propsCopy = new HashMap<>(props);
propsCopy.put(Constants.AUTH_METHOD, AuthenticationMethod.TEAMCITY_SSH_KEY.toString());
propsCopy.put(VcsRootSshKeyManager.VCS_ROOT_TEAMCITY_SSH_KEY_NAME, key.getName());
if (key.isEncrypted()) {
String passphrase = credentials.getPassword();
if (StringUtil.isNotEmpty(passphrase)) {
propsCopy.put(Constants.PASSPHRASE, passphrase);
}
}
try {
return testConnection(propsCopy, curProject);
} catch (VcsException e) {
// here we try to use the exact key, so if it does not fit - we fail the check
if (isBranchRelatedError(e) || GitServerUtil.isAuthError(e) || fetchUrl.toLowerCase().contains("git")) throw e;
}
}
}
// SSH access, before using the default private key which may not be accessible on the agent,
// let's iterate over all SSH keys of the current project, maybe we'll find a working one
for (TeamCitySshKey key: serverSshKeyManager.getKeys(curProject)) {
if (key.isEncrypted()) continue; // don't know password, so can't use it
Map<String, String> propsCopy = new HashMap<>(props);
propsCopy.put(Constants.AUTH_METHOD, AuthenticationMethod.TEAMCITY_SSH_KEY.toString());
propsCopy.put(VcsRootSshKeyManager.VCS_ROOT_TEAMCITY_SSH_KEY_NAME, key.getName());
try {
numSshKeysTried++;
return testConnection(propsCopy, curProject);
} catch (VcsException e) {
if (isBranchRelatedError(e)) throw e;
}
}
}
// could not find any valid keys, proceed with default SSH key
try {
return testConnection(props, curProject);
} catch (VcsException e) {
if (isBranchRelatedError(e)) throw e;
String message = "Could not connect to the Git repository by SSH protocol.";
if (numSshKeysTried > 0) {
message += " Tried " + numSshKeysTried + " SSH " + StringUtil.pluralize("key", numSshKeysTried) +
" accessible from the current project.";
} else {
message += " Could not find an SSH key in the current project which would work with this Git repository.";
}
throw new VcsException(message + " Error message: " + e.getMessage(), e);
}
}
final boolean defaultBranchKnown = props.get(Constants.BRANCH_NAME) != null;
if (defaultBranchKnown) {
//git protocol, or git scm provider
if ("git".equalsIgnoreCase(scmName) || "git".equalsIgnoreCase(uri.getScheme()) || fetchUrl.endsWith(".git") || lowerCaseFetchUrl.endsWith(".git")) return props;
}
// need to guess default branch or
// not SSH or URL does not end with .git, still try to connect just for the case
try {
return testConnection(props, curProject);
} catch (VcsException e) {
if (isBranchRelatedError(e) || GitServerUtil.isAuthError(e) || fetchUrl.toLowerCase().contains("git")) throw e;
// probably not git
Loggers.VCS.infoAndDebugDetails("Failed to recognize " + url.getUrl() + " as a git repository", e);
return null;
}
}