diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesService.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesService.java index 39d49c970..3f21f3944 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesService.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesService.java @@ -8,6 +8,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import org.gitlab.api.GitlabAPI; import org.gitlab.api.models.GitlabBranch; import org.gitlab.api.models.GitlabProject; @@ -60,7 +61,7 @@ protected GitLabProjectBranchesService(TimeUtility timeUtility) { this.timeUtility = timeUtility; } - public List getBranches(GitLab gitLab, String sourceRepositoryString) throws IOException { + public List getBranches(GitlabAPI client, String sourceRepositoryString) throws IOException { synchronized (projectBranchCache) { BranchListEntry branchListEntry = projectBranchCache.get(sourceRepositoryString); @@ -74,9 +75,9 @@ public List getBranches(GitLab gitLab, String sourceRepositoryString) th final List branchNames = new ArrayList(); try { - GitlabProject gitlabProject = findGitlabProjectForRepositoryUrl(gitLab, sourceRepositoryString); + GitlabProject gitlabProject = findGitlabProjectForRepositoryUrl(client, sourceRepositoryString); if (gitlabProject != null) { - final List branches = gitLab.instance().getBranches(gitlabProject); + final List branches = client.getBranches(gitlabProject); for (final GitlabBranch branch : branches) { branchNames.add(branch.getName()); } @@ -100,7 +101,7 @@ public List getBranches(GitLab gitLab, String sourceRepositoryString) th } } - public GitlabProject findGitlabProjectForRepositoryUrl(GitLab gitLab, String sourceRepositoryString) + public GitlabProject findGitlabProjectForRepositoryUrl(GitlabAPI client, String sourceRepositoryString) throws IOException { synchronized (projectMapCache) { String repositoryUrl = sourceRepositoryString.toLowerCase(); @@ -115,17 +116,17 @@ public GitlabProject findGitlabProjectForRepositoryUrl(GitLab gitLab, String sou (Boolean) projectMapCache.containsKey(repositoryUrl), projectCacheExpiry, timeUtility.getCurrentTimeInMillis() }); } - refreshGitLabProjectMap(gitLab); + refreshGitLabProjectMap(client); } return projectMapCache.get(repositoryUrl); } } - public Map refreshGitLabProjectMap(GitLab gitLab) throws IOException { + public Map refreshGitLabProjectMap(GitlabAPI client) throws IOException { synchronized (projectMapCache) { try { projectMapCache.clear(); - List projects = gitLab.instance().getProjects(); + List projects = client.getProjects(); for (GitlabProject gitlabProject : projects) { projectMapCache.put(gitlabProject.getSshUrl().toLowerCase(), gitlabProject); projectMapCache.put(gitlabProject.getHttpUrl().toLowerCase(), gitlabProject); diff --git a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java index c1deafde1..4e6e6aaea 100644 --- a/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java +++ b/src/main/java/com/dabsquared/gitlabjenkins/GitLabPushTrigger.java @@ -2,6 +2,7 @@ import com.dabsquared.gitlabjenkins.model.MergeRequestHook; import com.dabsquared.gitlabjenkins.model.PushHook; +import com.dabsquared.gitlabjenkins.trigger.branch.ProjectBranchesProvider; import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilter; import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterFactory; import com.dabsquared.gitlabjenkins.trigger.filter.BranchFilterType; @@ -263,37 +264,6 @@ public ListBoxModel doFillTriggerOpenMergeRequestOnPushItems(@QueryParameter Str new Option("On push to source or target branch", "both", triggerOpenMergeRequestOnPush.matches("both") )); } - private List getProjectBranches(final Job job) throws IOException, IllegalStateException { - if (!(job instanceof AbstractProject)) { - return Lists.newArrayList(); - } - - final URIish sourceRepository = getSourceRepoURLDefault(job); - - if (sourceRepository == null) { - throw new IllegalStateException(Messages.GitLabPushTrigger_NoSourceRepository()); - } - - if (!getGitlabHostUrl().isEmpty()) { - return GitLabProjectBranchesService.instance().getBranches(getGitlab(), sourceRepository.toString()); - } else { - LOGGER.log(Level.WARNING, "getProjectBranches: gitlabHostUrl hasn't been configured globally. Job {0}.", - job.getFullName()); - return Lists.newArrayList(); - } - } - - private GitSCM getGitSCM(SCMTriggerItem item) { - if(item != null) { - for(SCM scm : item.getSCMs()) { - if(scm instanceof GitSCM) { - return (GitSCM) scm; - } - } - } - return null; - } - private static List splitBranchSpec(final String spec) { return Lists.newArrayList(Splitter.on(',').omitEmptyStrings().trimResults().split(spec)); } @@ -305,7 +275,7 @@ private AutoCompletionCandidates doAutoCompleteBranchesSpec(final Job job, List values = ac.getValues(); try { - List branches = this.getProjectBranches(job); + List branches = ProjectBranchesProvider.instance().getProjectBranches(job); // show all suggestions for short strings if (query.length() < 2){ values.addAll(branches); @@ -345,7 +315,7 @@ private FormValidation doCheckBranchesSpec(@AncestorInPath final Job proje final List projectBranches; try { - projectBranches = this.getProjectBranches(project); + projectBranches = ProjectBranchesProvider.instance().getProjectBranches(project); } catch (final IllegalStateException ex) { return FormValidation.warning(Messages.GitLabPushTrigger_CannotConnectToGitLab(ex.getMessage())); } catch (final IOException ex) { @@ -381,39 +351,6 @@ public FormValidation doCheckExcludeBranchesSpec(@AncestorInPath final Job return this.doCheckBranchesSpec(project, value); } - /** - * Get the URL of the first declared repository in the project configuration. - * Use this as default source repository url. - * - * @return URIish the default value of the source repository url - * @throws IllegalStateException Project does not use git scm. - */ - protected URIish getSourceRepoURLDefault(Job job) { - URIish url = null; - SCMTriggerItem item = SCMTriggerItems.asSCMTriggerItem(job); - GitSCM gitSCM = getGitSCM(item); - if(gitSCM == null) { - LOGGER.log( - Level.WARNING, - "Could not find GitSCM for project. Project = {1}, next build = {2}", - new String[] { - job.getName(), - String.valueOf(job.getNextBuildNumber()) }); - throw new IllegalStateException("This project does not use git:" + job.getName()); - } - - List repositories = gitSCM.getRepositories(); - if (!repositories.isEmpty()) { - RemoteConfig defaultRepository = repositories.get(repositories.size() - 1); - List uris = defaultRepository.getURIs(); - if (!uris.isEmpty()) { - return uris.get(uris.size() - 1); - } - } - - return null; - } - public GitLab getGitlab() { if (gitlab == null) { gitlab = new GitLab(); diff --git a/src/main/java/com/dabsquared/gitlabjenkins/trigger/branch/ProjectBranchesProvider.java b/src/main/java/com/dabsquared/gitlabjenkins/trigger/branch/ProjectBranchesProvider.java new file mode 100644 index 000000000..219086fe4 --- /dev/null +++ b/src/main/java/com/dabsquared/gitlabjenkins/trigger/branch/ProjectBranchesProvider.java @@ -0,0 +1,86 @@ +package com.dabsquared.gitlabjenkins.trigger.branch; + +import com.dabsquared.gitlabjenkins.GitLabProjectBranchesService; +import com.dabsquared.gitlabjenkins.Messages; +import com.dabsquared.gitlabjenkins.connection.GitLabConnectionProperty; +import hudson.model.Job; +import hudson.plugins.git.GitSCM; +import hudson.scm.SCM; +import jenkins.triggers.SCMTriggerItem; +import org.eclipse.jgit.transport.RemoteConfig; +import org.eclipse.jgit.transport.URIish; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * @author Robin Müller + */ +public final class ProjectBranchesProvider { + + private static final Logger LOGGER = Logger.getLogger(ProjectBranchesProvider.class.getName()); + private static final ProjectBranchesProvider INSTANCE = new ProjectBranchesProvider(); + + private ProjectBranchesProvider() { } + + public static ProjectBranchesProvider instance() { + return INSTANCE; + } + + public List getProjectBranches(Job project) throws IOException { + final URIish sourceRepository = getSourceRepoURLDefault(project); + GitLabConnectionProperty connectionProperty = project.getProperty(GitLabConnectionProperty.class); + if (connectionProperty != null && connectionProperty.getClient() != null) { + return GitLabProjectBranchesService.instance().getBranches(connectionProperty.getClient(), sourceRepository.toString()); + } else { + LOGGER.log(Level.WARNING, "getProjectBranches: gitlabHostUrl hasn't been configured globally. Job {0}.", project.getFullName()); + return Collections.emptyList(); + } + } + + /** + * Get the URL of the first declared repository in the project configuration. + * Use this as default source repository url. + * + * @return URIish the default value of the source repository url + * @throws IllegalStateException Project does not use git scm. + */ + private URIish getSourceRepoURLDefault(Job job) { + SCMTriggerItem item = SCMTriggerItem.SCMTriggerItems.asSCMTriggerItem(job); + GitSCM gitSCM = getGitSCM(item); + if(gitSCM == null) { + LOGGER.log(Level.WARNING, "Could not find GitSCM for project. Project = {1}, next build = {2}", + array(job.getName(), String.valueOf(job.getNextBuildNumber()))); + throw new IllegalStateException("This project does not use git:" + job.getName()); + } + return getFirstRepoURL(gitSCM.getRepositories()); + } + + private URIish getFirstRepoURL(List repositories) { + if (!repositories.isEmpty()) { + List uris = repositories.get(repositories.size() - 1).getURIs(); + if (!uris.isEmpty()) { + return uris.get(uris.size() - 1); + } + } + throw new IllegalStateException(Messages.GitLabPushTrigger_NoSourceRepository()); + } + + private GitSCM getGitSCM(SCMTriggerItem item) { + if(item != null) { + for(SCM scm : item.getSCMs()) { + if(scm instanceof GitSCM) { + return (GitSCM) scm; + } + } + } + return null; + } + + private Object[] array(Object... objects) { + return objects; + } +} diff --git a/src/test/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesServiceTest.java b/src/test/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesServiceTest.java index 6650c5674..e88b52a8b 100644 --- a/src/test/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesServiceTest.java +++ b/src/test/java/com/dabsquared/gitlabjenkins/GitLabProjectBranchesServiceTest.java @@ -59,8 +59,8 @@ public void setUp() throws IOException { @Test public void shouldReturnProjectFromGitlabApi() throws Exception { // when - GitlabProject gitlabProject = branchesService.findGitlabProjectForRepositoryUrl(gitLab, - "git@git.example.com:groupOne/A.git"); + GitlabProject gitlabProject = branchesService.findGitlabProjectForRepositoryUrl( + gitLab.instance(), "git@git.example.com:groupOne/A.git"); // then assertThat(gitlabProject, is(gitlabProjectA)); @@ -69,7 +69,7 @@ public void shouldReturnProjectFromGitlabApi() throws Exception { @Test public void shouldReturnBranchNamesFromGitlabApi() throws Exception { // when - List actualBranchNames = branchesService.getBranches(gitLab, "git@git.example.com:groupOne/B.git"); + List actualBranchNames = branchesService.getBranches(gitLab.instance(), "git@git.example.com:groupOne/B.git"); // then assertThat(actualBranchNames, is(branchNamesProjectB)); @@ -78,9 +78,9 @@ public void shouldReturnBranchNamesFromGitlabApi() throws Exception { @Test public void shouldNotCallGitlabApiGetProjectsWhenElementIsCached() throws Exception { // when - branchesService.findGitlabProjectForRepositoryUrl(gitLab, "git@git.example.com:groupOne/A.git"); + branchesService.findGitlabProjectForRepositoryUrl(gitLab.instance(), "git@git.example.com:groupOne/A.git"); verify(gitlabApi, times(1)).getProjects(); - branchesService.findGitlabProjectForRepositoryUrl(gitLab, "git@git.example.com:groupOne/B.git"); + branchesService.findGitlabProjectForRepositoryUrl(gitLab.instance(), "git@git.example.com:groupOne/B.git"); // then verify(gitlabApi, times(1)).getProjects(); @@ -89,9 +89,9 @@ public void shouldNotCallGitlabApiGetProjectsWhenElementIsCached() throws Except @Test public void shouldCallGitlabApiGetProjectsWhenElementIsNotCached() throws Exception { // when - branchesService.findGitlabProjectForRepositoryUrl(gitLab, "git@git.example.com:groupOne/A.git"); + branchesService.findGitlabProjectForRepositoryUrl(gitLab.instance(), "git@git.example.com:groupOne/A.git"); verify(gitlabApi, times(1)).getProjects(); - branchesService.findGitlabProjectForRepositoryUrl(gitLab, "git@git.example.com:groupOne/DoesNotExist.git"); + branchesService.findGitlabProjectForRepositoryUrl(gitLab.instance(), "git@git.example.com:groupOne/DoesNotExist.git"); // then verify(gitlabApi, times(2)).getProjects(); @@ -100,9 +100,9 @@ public void shouldCallGitlabApiGetProjectsWhenElementIsNotCached() throws Except @Test public void shoulNotCallGitlabApiGetBranchesWhenElementIsCached() throws Exception { // when - branchesService.getBranches(gitLab, "git@git.example.com:groupOne/B.git"); + branchesService.getBranches(gitLab.instance(), "git@git.example.com:groupOne/B.git"); verify(gitlabApi, times(1)).getBranches(gitlabProjectB); - branchesService.getBranches(gitLab, "git@git.example.com:groupOne/B.git"); + branchesService.getBranches(gitLab.instance(), "git@git.example.com:groupOne/B.git"); // then verify(gitlabApi, times(1)).getProjects(); @@ -111,7 +111,7 @@ public void shoulNotCallGitlabApiGetBranchesWhenElementIsCached() throws Excepti @Test public void shoulNotMakeUnnecessaryCallsToGitlabApiGetBranches() throws Exception { // when - branchesService.getBranches(gitLab, "git@git.example.com:groupOne/A.git"); + branchesService.getBranches(gitLab.instance(), "git@git.example.com:groupOne/A.git"); // then verify(gitlabApi, times(1)).getBranches(gitlabProjectA); @@ -121,12 +121,12 @@ public void shoulNotMakeUnnecessaryCallsToGitlabApiGetBranches() throws Exceptio @Test public void shouldExpireBranchCacheAtSetTime() throws Exception { // first call should retrieve branches from gitlabApi - branchesService.getBranches(gitLab, "git@git.example.com:groupOne/A.git"); + branchesService.getBranches(gitLab.instance(), "git@git.example.com:groupOne/A.git"); verify(gitlabApi, times(1)).getBranches(gitlabProjectA); long timeAfterCacheExpiry = GitLabProjectBranchesService.BRANCH_CACHE_TIME_IN_MILLISECONDS + 2; when(timeUtility.getCurrentTimeInMillis()).thenReturn(timeAfterCacheExpiry); - branchesService.getBranches(gitLab, "git@git.example.com:groupOne/A.git"); + branchesService.getBranches(gitLab.instance(), "git@git.example.com:groupOne/A.git"); // then verify(gitlabApi, times(2)).getBranches(gitlabProjectA); @@ -135,12 +135,12 @@ public void shouldExpireBranchCacheAtSetTime() throws Exception { @Test public void shouldExpireProjectCacheAtSetTime() throws Exception { // first call should retrieve projects from gitlabApi - branchesService.findGitlabProjectForRepositoryUrl(gitLab, "git@git.example.com:groupOne/A.git"); + branchesService.findGitlabProjectForRepositoryUrl(gitLab.instance(), "git@git.example.com:groupOne/A.git"); verify(gitlabApi, times(1)).getProjects(); long timeAfterCacheExpiry = GitLabProjectBranchesService.PROJECT_MAP_CACHE_TIME_IN_MILLISECONDS + 2; when(timeUtility.getCurrentTimeInMillis()).thenReturn(timeAfterCacheExpiry); - branchesService.findGitlabProjectForRepositoryUrl(gitLab, "git@git.example.com:groupOne/A.git"); + branchesService.findGitlabProjectForRepositoryUrl(gitLab.instance(), "git@git.example.com:groupOne/A.git"); // then verify(gitlabApi, times(2)).getProjects(); @@ -203,4 +203,4 @@ private GitlabProject setupGitlabProject(String namespace, String name) { return project; } -} \ No newline at end of file +}