Skip to content

Add the Tuleap Git SCM Browser #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.jenkinsci.plugins.tuleap_git_branch_source;

import edu.umd.cs.findbugs.annotations.NonNull;
import hudson.Extension;
import hudson.model.Descriptor;
import hudson.plugins.git.GitChangeSet;
import hudson.plugins.git.browser.GitRepositoryBrowser;
import hudson.scm.EditType;
import hudson.scm.RepositoryBrowser;
import net.sf.json.JSONObject;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.StaplerRequest;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

public class TuleapBrowser extends GitRepositoryBrowser {

@DataBoundConstructor
public TuleapBrowser(String repositoryUrl) {
super(repositoryUrl);
}

public String getRepositoryUrl() {
return super.getRepoUrl();
}

@Override
public URL getDiffLink(GitChangeSet.Path path) throws IOException {
if (path.getEditType() != EditType.EDIT || path.getSrc() == null || path.getDst() == null
|| path.getChangeSet().getParentCommit() == null) {
return null;
}
return encodeURL(new URL(this.getRepositoryUrl() + "?a=commitdiff&h=" + path.getChangeSet().getId()));
}

@Override
public URL getFileLink(GitChangeSet.Path path) throws IOException, URISyntaxException {
if (path.getEditType().equals(EditType.DELETE)) {
return null;
}
URL fileUrl = new URL(this.getRepositoryUrl() + "?a=blob&hb=" + path.getChangeSet().getId() + "&f=" + path.getPath());
return encodeURL(fileUrl);
}

@Override
public URL getChangeSetLink(GitChangeSet changeSet) throws IOException {
return encodeURL(new URL(this.getRepositoryUrl() + "?a=commit&h=" + changeSet.getId()));
}

@Extension
public static class DescriptorImpl extends Descriptor<RepositoryBrowser<?>> {

@NonNull
public String getDisplayName() {
return "Tuleap";
}

@Override
public TuleapBrowser newInstance(StaplerRequest req, @NonNull JSONObject jsonObject)
throws FormException {
return req.bindJSON(TuleapBrowser.class, jsonObject);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
import org.jetbrains.annotations.NotNull;

public class TuleapSCMBuilder extends GitSCMBuilder<TuleapSCMBuilder> {
public TuleapSCMBuilder(@NotNull SCMHead head, SCMRevision revision, @NotNull String remote, String credentialsId) {

private String repositoryBaseUrl;

public TuleapSCMBuilder(@NotNull SCMHead head, SCMRevision revision, @NotNull String remote, String credentialsId, String repositoryBaseUrl) {
super(head, revision, remote, credentialsId);
withoutRefSpecs();
if (head instanceof TuleapPullRequestSCMHead) {
Expand All @@ -17,6 +20,8 @@ public TuleapSCMBuilder(@NotNull SCMHead head, SCMRevision revision, @NotNull St
} else {
withRefSpec("+refs/heads/" + head.getName() + ":refs/remotes/@{remote}/" + head.getName());
}
this.repositoryBaseUrl = repositoryBaseUrl;
withBrowser(new TuleapBrowser(repositoryBaseUrl));
}

@NonNull
Expand All @@ -32,6 +37,7 @@ public GitSCM build() {
} finally {
withHead(head);
withRevision(revision);
withBrowser(new TuleapBrowser(this.repositoryBaseUrl));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,8 @@ public void setCredentials(TuleapAccessToken credentials) {
@NotNull
@Override
public SCM build(@NonNull SCMHead scmHead, @CheckForNull SCMRevision scmRevision) {
return new TuleapSCMBuilder(scmHead, scmRevision, remoteUrl, credentialsId).withTraits(traits).build();
String repositoryUri = this.getGitBaseUri() + this.project.getShortname() + "/" +this.repository.getName();
return new TuleapSCMBuilder(scmHead, scmRevision, remoteUrl, credentialsId, repositoryUri).withTraits(traits).build();
}

public List<SCMSourceTrait> getTraits() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core"
xmlns:f="/lib/form">
<f:entry field="repositoryUrl" title="${%Repository URL}">
<f:textbox/>
</f:entry>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
The URL is the web URL of the Tuleap Git repository.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
Specify the HTTPS URL for the Tuleap Git repository so that links to changes can be automatically generated by Jenkins.
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package org.jenkinsci.plugins.tuleap_git_branch_source;

import hudson.plugins.git.GitChangeSet;
import hudson.scm.EditType;
import org.junit.Test;

import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.List;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class TuleapBrowserTest {

@Test
public void testItReturnsNoDiffLinkIfTheFileIsNotEditedInTheLastCommit() throws IOException {
String parentLine = "parent h4sh_s0m3";
List<String> lines = Collections.singletonList(parentLine);
GitChangeSet changeSet = new GitChangeSet(lines, false);

GitChangeSet.Path path = mock(GitChangeSet.Path.class);
when(path.getEditType()).thenReturn(EditType.ADD);
when(path.getSrc()).thenReturn("source/file");
when(path.getDst()).thenReturn("dest/file");
when(path.getChangeSet()).thenReturn(changeSet);

TuleapBrowser browser = new TuleapBrowser("https://tuleap.example.com/plugins/git/naha/repo01");

assertNull(browser.getDiffLink(path));
}

@Test
public void testItReturnsNoDiffLinkIfTheFileDoesNotHaveSourcePath() throws IOException {
String parentLine = "parent h4sh_s0m3";
List<String> lines = Collections.singletonList(parentLine);
GitChangeSet changeSet = new GitChangeSet(lines, false);

GitChangeSet.Path path = mock(GitChangeSet.Path.class);
when(path.getEditType()).thenReturn(EditType.EDIT);
when(path.getSrc()).thenReturn(null);
when(path.getDst()).thenReturn("dest/file");
when(path.getChangeSet()).thenReturn(changeSet);

TuleapBrowser browser = new TuleapBrowser("https://tuleap.example.com/plugins/git/naha/repo01");

assertNull(browser.getDiffLink(path));
}

@Test
public void testItReturnsNoDiffLinkIfTheFileDoesNotHaveDestinationPath() throws IOException {
String parentLine = "parent h4sh_s0m3";
List<String> lines = Collections.singletonList(parentLine);
GitChangeSet changeSet = new GitChangeSet(lines, false);

GitChangeSet.Path path = mock(GitChangeSet.Path.class);
when(path.getEditType()).thenReturn(EditType.EDIT);
when(path.getSrc()).thenReturn("source/file");
when(path.getDst()).thenReturn(null);
when(path.getChangeSet()).thenReturn(changeSet);

TuleapBrowser browser = new TuleapBrowser("https://tuleap.example.com/plugins/git/naha/repo01");

assertNull(browser.getDiffLink(path));
}

@Test
public void testItReturnsNoDiffLinkIfTheFileDoesNotHaveParentCommit() throws IOException {
String treeLine = "tree h4sh_s0m3";
List<String> lines = Collections.singletonList(treeLine);
GitChangeSet changeSet = new GitChangeSet(lines, false);

GitChangeSet.Path path = mock(GitChangeSet.Path.class);
when(path.getEditType()).thenReturn(EditType.EDIT);
when(path.getSrc()).thenReturn("source/file");
when(path.getDst()).thenReturn("dest/file");
when(path.getChangeSet()).thenReturn(changeSet);

TuleapBrowser browser = new TuleapBrowser("https://tuleap.example.com/plugins/git/naha/repo01");

assertNull(browser.getDiffLink(path));
}

@Test
public void testItReturnsTheDiffLink() throws IOException {
String treeLine = "parent h4sh_s0m3";
List<String> lines = Collections.singletonList(treeLine);
GitChangeSet changeSet = new GitChangeSet(lines, false);

GitChangeSet.Path path = mock(GitChangeSet.Path.class);
when(path.getEditType()).thenReturn(EditType.EDIT);
when(path.getSrc()).thenReturn("source/file");
when(path.getDst()).thenReturn("dest/file");
when(path.getChangeSet()).thenReturn(changeSet);

TuleapBrowser browser = new TuleapBrowser("https://tuleap.example.com/plugins/git/naha/repo01");

assertEquals(new URL("https://tuleap.example.com/plugins/git/naha/repo01?a=commitdiff&h=null"), browser.getDiffLink(path));
}

@Test
public void testItDoesNotReturnTheFileLinkContentIfTheFileIsInDeleteMode() throws IOException, URISyntaxException {
GitChangeSet.Path path = mock(GitChangeSet.Path.class);
when(path.getEditType()).thenReturn(EditType.DELETE);

TuleapBrowser browser = new TuleapBrowser("https://tuleap.example.com/plugins/git/naha/repo01");

assertNull(browser.getFileLink(path));
}

@Test
public void testItReturnsTheFileLinkContentIfTheFileIsNotInDeleteMode() throws IOException, URISyntaxException {
String commitIdLine = "commit h4sh_s0m3";
List<String> lines = Collections.singletonList(commitIdLine);
GitChangeSet changeSet = new GitChangeSet(lines, false);

GitChangeSet.Path path = mock(GitChangeSet.Path.class);
when(path.getEditType()).thenReturn(EditType.EDIT).thenReturn(EditType.ADD);
when(path.getChangeSet()).thenReturn(changeSet);

TuleapBrowser browser = new TuleapBrowser("https://tuleap.example.com/plugins/git/naha/repo01");

assertEquals(new URL("https://tuleap.example.com/plugins/git/naha/repo01?a=blob&hb=h4sh_s0m3&f=null"), browser.getFileLink(path));
assertEquals(new URL("https://tuleap.example.com/plugins/git/naha/repo01?a=blob&hb=h4sh_s0m3&f=null"), browser.getFileLink(path));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public void testItCleansAndAddTheBranchRefSpecByDefault() {
String remote = "https://tuleap.example.com/repo.git";
String credentialsId = "1581";

TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpScmHead, tlpRevision, remote, credentialsId);
TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpScmHead, tlpRevision, remote, credentialsId,"https://tuleap.example.com/plugins/git/somerepo");
assertEquals(1, tuleapSCMBuilder.refSpecs().size());
assertEquals("+refs/heads/jcomprendspas-branch:refs/remotes/@{remote}/jcomprendspas-branch", tuleapSCMBuilder.refSpecs().get(0));
assertEquals("https://tuleap.example.com/repo.git", tuleapSCMBuilder.remote());
Expand All @@ -39,7 +39,7 @@ public void testItCleansAndAddThePullRequestBranchRefSpecWhenThereIsAPullRequest
String remote = "https://tuleap.example.com/repo.git";
String credentialsId = "1581";

TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpPrScmHead, tlpPrRevision, remote, credentialsId);
TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpPrScmHead, tlpPrRevision, remote, credentialsId, "https://tuleap.example.com/plugins/git/somerepo");
assertEquals(1, tuleapSCMBuilder.refSpecs().size());
assertEquals("+refs/tlpr/3/head:refs/remotes/@{remote}/TLP-PR-3", tuleapSCMBuilder.refSpecs().get(0));
assertEquals("https://tuleap.example.com/repo.git", tuleapSCMBuilder.remote());
Expand All @@ -54,7 +54,7 @@ public void testItReturnsAGitSCMWithTheOriginRevisionWhenThereIsATuleapPullReque
String remote = "https://tuleap.example.com/repo.git";
String credentialsId = "1581";

TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpPrScmHead, tlpPrRevision, remote, credentialsId);
TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpPrScmHead, tlpPrRevision, remote, credentialsId, "https://tuleap.example.com/plugins/git/somerepo");

tuleapSCMBuilder.build();
verify(tlpPrRevision, atLeastOnce()).getOrigin();
Expand All @@ -72,7 +72,7 @@ public void testItReturnsAGitSCMWithTheBaseRevisionWhenThereIsNoTuleapPullReques
String remote = "https://tuleap.example.com/repo.git";
String credentialsId = "1581";

TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpScmHead, tlpRevision, remote, credentialsId);
TuleapSCMBuilder tuleapSCMBuilder = new TuleapSCMBuilder(tlpScmHead, tlpRevision, remote, credentialsId, "https://tuleap.example.com/plugins/git/somerepo");

tuleapSCMBuilder.build();
assertEquals(tlpRevision, tuleapSCMBuilder.revision());
Expand Down