-
Notifications
You must be signed in to change notification settings - Fork 354
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support cloning from Bitbucket mirror
A mirrored Git repository can be configured for fetching references. The mirror is not used in the following cases: - If the source branch in a pull request resides in a different repository, the source branch is fetched from the primary repository while the target branch is fetched from the mirror. - During initial pull request scanning, the mirror isn't used because PullRequestSCMHead doesn't contain the hash needed for the build and SCMRevision is null. This is the current design limitation and can be refactored later. Cloning from the mirror can only be used with native web-hooks since plugin web-hooks don't provide a mirror identifier. For branches and tags, the mirror sync event is used. Thus, at cloning time, the mirror is already synchronized. However, in the case of a pull request event, there is no such guarantee. The plugin optimistically assumes that the mirror is synced and the required commit hashes exist in the mirrored repository at cloning time. If the plugin can't find the required hashes, it falls back to the primary repository. Fixes #592 Co-authors: - Andrey Fomin https://github.com/andrey-fomin - Andrei Kouznetchik https://github.com/akouznetchik - Eugene Mercuriev https://github.com/zamonier
- Loading branch information
1 parent
ef13e0c
commit d5750f4
Showing
48 changed files
with
2,133 additions
and
1,138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
93 changes: 93 additions & 0 deletions
93
src/main/java/com/cloudbees/jenkins/plugins/bitbucket/BitbucketApiUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package com.cloudbees.jenkins.plugins.bitbucket; | ||
|
||
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketApi; | ||
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketApiFactory; | ||
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketAuthenticator; | ||
import com.cloudbees.jenkins.plugins.bitbucket.api.BitbucketRequestException; | ||
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketCloudEndpoint; | ||
import com.cloudbees.jenkins.plugins.bitbucket.endpoints.BitbucketEndpointConfiguration; | ||
import com.cloudbees.plugins.credentials.CredentialsProvider; | ||
import com.cloudbees.plugins.credentials.common.StandardCredentials; | ||
import hudson.Util; | ||
import hudson.model.Item; | ||
import hudson.util.FormFillFailure; | ||
import hudson.util.ListBoxModel; | ||
import java.io.IOException; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
import jenkins.authentication.tokens.api.AuthenticationTokens; | ||
import jenkins.model.Jenkins; | ||
import jenkins.scm.api.SCMSourceOwner; | ||
import org.apache.commons.lang.StringUtils; | ||
|
||
public class BitbucketApiUtils { | ||
|
||
private static final Logger LOGGER = Logger.getLogger(BitbucketApiUtils.class.getName()); | ||
|
||
public static ListBoxModel getFromBitbucket(SCMSourceOwner context, | ||
String serverUrl, | ||
String credentialsId, | ||
String repoOwner, | ||
String repository, | ||
BitbucketSupplier<ListBoxModel> listBoxModelSupplier) | ||
throws FormFillFailure { | ||
repoOwner = Util.fixEmptyAndTrim(repoOwner); | ||
if (repoOwner == null) { | ||
return new ListBoxModel(); | ||
} | ||
if (context == null && !Jenkins.get().hasPermission(Jenkins.ADMINISTER) || | ||
context != null && !context.hasPermission(Item.EXTENDED_READ)) { | ||
return new ListBoxModel(); // not supposed to be seeing this form | ||
} | ||
if (context != null && !context.hasPermission(CredentialsProvider.USE_ITEM)) { | ||
return new ListBoxModel(); // not permitted to try connecting with these credentials | ||
} | ||
|
||
String serverUrlFallback = BitbucketCloudEndpoint.SERVER_URL; | ||
// if at least one bitbucket server is configured use it instead of bitbucket cloud | ||
if(BitbucketEndpointConfiguration.get().getEndpointItems().size() > 0){ | ||
serverUrlFallback = BitbucketEndpointConfiguration.get().getEndpointItems().get(0).value; | ||
} | ||
|
||
serverUrl = StringUtils.defaultIfBlank(serverUrl, serverUrlFallback); | ||
StandardCredentials credentials = BitbucketCredentials.lookupCredentials( | ||
serverUrl, | ||
context, | ||
credentialsId, | ||
StandardCredentials.class | ||
); | ||
|
||
BitbucketAuthenticator authenticator = AuthenticationTokens.convert(BitbucketAuthenticator.authenticationContext(serverUrl), credentials); | ||
|
||
try { | ||
BitbucketApi bitbucket = BitbucketApiFactory.newInstance(serverUrl, authenticator, repoOwner, null, repository); | ||
return listBoxModelSupplier.get(bitbucket); | ||
} catch (FormFillFailure | OutOfMemoryError e) { | ||
throw e; | ||
} catch (IOException e) { | ||
if (e instanceof BitbucketRequestException) { | ||
if (((BitbucketRequestException) e).getHttpCode() == 401) { | ||
throw FormFillFailure.error(credentials == null | ||
? Messages.BitbucketSCMSource_UnauthorizedAnonymous(repoOwner) | ||
: Messages.BitbucketSCMSource_UnauthorizedOwner(repoOwner)).withSelectionCleared(); | ||
} | ||
} else if (e.getCause() instanceof BitbucketRequestException) { | ||
if (((BitbucketRequestException) e.getCause()).getHttpCode() == 401) { | ||
throw FormFillFailure.error(credentials == null | ||
? Messages.BitbucketSCMSource_UnauthorizedAnonymous(repoOwner) | ||
: Messages.BitbucketSCMSource_UnauthorizedOwner(repoOwner)).withSelectionCleared(); | ||
} | ||
} | ||
LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||
throw FormFillFailure.error(e.getMessage()); | ||
} catch (Throwable e) { | ||
LOGGER.log(Level.SEVERE, e.getMessage(), e); | ||
throw FormFillFailure.error(e.getMessage()); | ||
} | ||
} | ||
|
||
public interface BitbucketSupplier<T> { | ||
T get(BitbucketApi bitbucketApi) throws IOException, InterruptedException; | ||
} | ||
|
||
} |
Oops, something went wrong.