From 9f80840c43a65318c45b362465c8efecd9b25b78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Wed, 26 Sep 2018 13:19:38 +0200 Subject: [PATCH 01/12] Add branch to changeset collections Branch information is added to a changeset collection and therefore removed from single changesets for git repositories. Mercurial repositories now also set the default branch in changesets. --- .../scm/repository/ChangesetPagingResult.java | 51 ++++++++++------ .../scm/repository/GitChangesetConverter.java | 27 +------- .../repository/spi/AbstractGitCommand.java | 22 ++++++- .../scm/repository/spi/GitLogCommand.java | 23 ++++--- .../scm/repository/spi/GitLogCommandTest.java | 5 ++ .../scm/repository/spi/HgLogCommand.java | 6 +- .../spi/javahg/AbstractChangesetCommand.java | 5 +- .../scm/repository/spi/HgLogCommandTest.java | 15 +++++ .../BranchChangesetCollectionToDtoMapper.java | 4 +- .../api/v2/resources/BranchReferenceDto.java | 19 ++++++ .../ChangesetCollectionToDtoMapper.java | 5 +- .../ChangesetCollectionToDtoMapperBase.java | 19 +++++- .../v2/resources/ChangesetRootResource.java | 6 +- .../scm/api/v2/resources/CollectionDto.java | 5 ++ .../FileHistoryCollectionToDtoMapper.java | 2 +- .../ChangesetCollectionToDtoMapperTest.java | 61 +++++++++++++++++++ 16 files changed, 209 insertions(+), 66 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchReferenceDto.java create mode 100644 scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperTest.java diff --git a/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java index 59a705e36a..ca1018b7aa 100644 --- a/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java +++ b/scm-core/src/main/java/sonia/scm/repository/ChangesetPagingResult.java @@ -82,6 +82,22 @@ public class ChangesetPagingResult implements Iterable, Serializable { this.total = total; this.changesets = changesets; + this.branchName = null; + } + + /** + * Constructs a new changeset paging result for a specific branch. + * + * + * @param total total number of changesets + * @param changesets current list of fetched changesets + * @param branchName branch name this result was created for + */ + public ChangesetPagingResult(int total, List changesets, String branchName) + { + this.total = total; + this.changesets = changesets; + this.branchName = branchName; } //~--- methods -------------------------------------------------------------- @@ -158,6 +174,7 @@ public class ChangesetPagingResult implements Iterable, Serializable return MoreObjects.toStringHelper(this) .add("changesets", changesets) .add("total", total) + .add("branch", branchName) .toString(); //J+ } @@ -186,37 +203,35 @@ public class ChangesetPagingResult implements Iterable, Serializable return total; } - //~--- set methods ---------------------------------------------------------- - - /** - * Sets the current list of changesets. - * - * - * @param changesets current list of changesets - */ - public void setChangesets(List changesets) + void setChangesets(List changesets) { this.changesets = changesets; } - /** - * Sets the total number of changesets - * - * - * @param total total number of changesets - */ - public void setTotal(int total) + void setTotal(int total) { this.total = total; } + void setBranchName(String branchName) { + this.branchName = branchName; + } + + /** + * Returns the branch name this result was created for. This can either be an explicit branch ("give me all + * changesets for branch xyz") or an implicit one ("give me the changesets for the default"). + */ + public String getBranchName() { + return branchName; + } + //~--- fields --------------------------------------------------------------- - /** current list of changesets */ @XmlElement(name = "changeset") @XmlElementWrapper(name = "changesets") private List changesets; - /** total number of changesets */ private int total; + + private String branchName; } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java index 6936c51269..2275fbcfd0 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitChangesetConverter.java @@ -39,7 +39,6 @@ import com.google.common.collect.Lists; import com.google.common.collect.Multimap; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.PersonIdent; -import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.TreeWalk; @@ -51,8 +50,8 @@ import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; -import java.util.Set; //~--- JDK imports ------------------------------------------------------------ @@ -130,27 +129,9 @@ public class GitChangesetConverter implements Closeable * * @throws IOException */ - public Changeset createChangeset(RevCommit commit) throws IOException + public Changeset createChangeset(RevCommit commit) { - List branches = Lists.newArrayList(); - Set refs = repository.getAllRefsByPeeledObjectId().get(commit.getId()); - - if (Util.isNotEmpty(refs)) - { - - for (Ref ref : refs) - { - String branch = GitUtil.getBranch(ref); - - if (branch != null) - { - branches.add(branch); - } - } - - } - - return createChangeset(commit, branches); + return createChangeset(commit, Collections.emptyList()); } /** @@ -165,7 +146,6 @@ public class GitChangesetConverter implements Closeable * @throws IOException */ public Changeset createChangeset(RevCommit commit, String branch) - throws IOException { return createChangeset(commit, Lists.newArrayList(branch)); } @@ -183,7 +163,6 @@ public class GitChangesetConverter implements Closeable * @throws IOException */ public Changeset createChangeset(RevCommit commit, List branches) - throws IOException { String id = commit.getId().name(); List parentList = null; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index d098c30b4e..ed2d06e209 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -34,7 +34,6 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import org.eclipse.jgit.lib.Repository; @@ -97,7 +96,15 @@ public class AbstractGitCommand } return commit; } - + + protected String getBranchNameOrDefault(String requestedBranch) { + if ( Strings.isNullOrEmpty(requestedBranch) ) { + return getDefaultBranchName(); + } else { + return requestedBranch; + } + } + protected ObjectId getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException { ObjectId head; if ( Strings.isNullOrEmpty(requestedBranch) ) { @@ -107,7 +114,16 @@ public class AbstractGitCommand } return head; } - + + protected String getDefaultBranchName() { + String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); + if (!Strings.isNullOrEmpty(defaultBranchName)) { + return defaultBranchName; + } else { + return null; + } + } + protected ObjectId getDefaultBranch(Repository gitRepository) throws IOException { ObjectId head; String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java index beb79cb921..9b106e95a2 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java @@ -170,8 +170,8 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand GitChangesetConverter converter = null; RevWalk revWalk = null; - try (org.eclipse.jgit.lib.Repository gr = open()) { - if (!gr.getAllRefs().isEmpty()) { + try (org.eclipse.jgit.lib.Repository repository = open()) { + if (!repository.getAllRefs().isEmpty()) { int counter = 0; int start = request.getPagingStart(); @@ -188,18 +188,18 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand ObjectId startId = null; if (!Strings.isNullOrEmpty(request.getStartChangeset())) { - startId = gr.resolve(request.getStartChangeset()); + startId = repository.resolve(request.getStartChangeset()); } ObjectId endId = null; if (!Strings.isNullOrEmpty(request.getEndChangeset())) { - endId = gr.resolve(request.getEndChangeset()); + endId = repository.resolve(request.getEndChangeset()); } - revWalk = new RevWalk(gr); + revWalk = new RevWalk(repository); - converter = new GitChangesetConverter(gr, revWalk); + converter = new GitChangesetConverter(repository, revWalk); if (!Strings.isNullOrEmpty(request.getPath())) { revWalk.setTreeFilter( @@ -207,7 +207,8 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF)); } - ObjectId head = getBranchOrDefault(gr, request.getBranch()); + ObjectId head = getBranchOrDefault(repository, request.getBranch()); + String branch = getBranchNameOrDefault(request.getBranch()); if (head != null) { if (startId != null) { @@ -234,10 +235,14 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand } } - changesets = new ChangesetPagingResult(counter, changesetList); + if (branch != null) { + changesets = new ChangesetPagingResult(counter, changesetList, branch); + } else { + changesets = new ChangesetPagingResult(counter, changesetList); + } } else if (logger.isWarnEnabled()) { logger.warn("the repository {} seems to be empty", - repository.getName()); + this.repository.getName()); changesets = new ChangesetPagingResult(0, Collections.EMPTY_LIST); } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java index d6e6ac98d8..b1420cb885 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java @@ -45,6 +45,7 @@ import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @@ -72,6 +73,8 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase assertEquals("86a6645eceefe8b9a247db5eb16e3d89a7e6e6d1", result.getChangesets().get(1).getId()); assertEquals("592d797cd36432e591416e8b2b98154f4f163411", result.getChangesets().get(2).getId()); assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", result.getChangesets().get(3).getId()); + assertNull(result.getBranchName()); + assertTrue(result.getChangesets().stream().allMatch(r -> r.getBranches().isEmpty())); // set default branch and fetch again repository.setProperty(GitConstants.PROPERTY_DEFAULT_BRANCH, "test-branch"); @@ -83,6 +86,8 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase assertEquals("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4", result.getChangesets().get(0).getId()); assertEquals("592d797cd36432e591416e8b2b98154f4f163411", result.getChangesets().get(1).getId()); assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", result.getChangesets().get(2).getId()); + assertEquals("test-branch", result.getBranchName()); + assertTrue(result.getChangesets().stream().allMatch(r -> r.getBranches().isEmpty())); } @Test diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgLogCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgLogCommand.java index 68d6913962..e9de7f7471 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgLogCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgLogCommand.java @@ -132,7 +132,11 @@ public class HgLogCommand extends AbstractCommand implements LogCommand List changesets = on(repository).rev(start + ":" + end).execute(); - result = new ChangesetPagingResult(total, changesets); + if (request.getBranch() == null) { + result = new ChangesetPagingResult(total, changesets); + } else { + result = new ChangesetPagingResult(total, changesets, request.getBranch()); + } } else { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java index 6466eb6d11..89164a8d80 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/javahg/AbstractChangesetCommand.java @@ -216,10 +216,7 @@ public abstract class AbstractChangesetCommand extends AbstractCommand String branch = in.textUpTo('\n'); - if (!BRANCH_DEFAULT.equals(branch)) - { - changeset.getBranches().add(branch); - } + changeset.getBranches().add(branch); String p1 = readId(in, changeset, PROPERTY_PARENT1_REVISION); diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgLogCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgLogCommandTest.java index 99e9fc191a..29fc46ed57 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgLogCommandTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgLogCommandTest.java @@ -88,6 +88,21 @@ public class HgLogCommandTest extends AbstractHgCommandTestBase result.getChangesets().get(2).getId()); } + @Test + public void testGetDefaultBranchInfo() { + LogCommandRequest request = new LogCommandRequest(); + + request.setPath("a.txt"); + + ChangesetPagingResult result = createComamnd().getChangesets(request); + + assertNotNull(result); + assertEquals(1, + result.getChangesets().get(0).getBranches().size()); + assertEquals("default", + result.getChangesets().get(0).getBranches().get(0)); + } + @Test public void testGetAllWithLimit() { LogCommandRequest request = new LogCommandRequest(); diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchChangesetCollectionToDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchChangesetCollectionToDtoMapper.java index afe8ad318b..8842d176fa 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchChangesetCollectionToDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchChangesetCollectionToDtoMapper.java @@ -12,12 +12,12 @@ public class BranchChangesetCollectionToDtoMapper extends ChangesetCollectionToD @Inject public BranchChangesetCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) { - super(changesetToChangesetDtoMapper); + super(changesetToChangesetDtoMapper, resourceLinks); this.resourceLinks = resourceLinks; } public CollectionDto map(int pageNumber, int pageSize, PageResult pageResult, Repository repository, String branch) { - return this.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository, branch)); + return this.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository, branch), branch); } private String createSelfLink(Repository repository, String branch) { diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchReferenceDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchReferenceDto.java new file mode 100644 index 0000000000..129d8d8bfa --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/BranchReferenceDto.java @@ -0,0 +1,19 @@ +package sonia.scm.api.v2.resources; + +import de.otto.edison.hal.HalRepresentation; +import de.otto.edison.hal.Links; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@NoArgsConstructor @AllArgsConstructor @Getter @Setter +public class BranchReferenceDto extends HalRepresentation { + private String name; + + @Override + @SuppressWarnings("squid:S1185") // We want to have this method available in this package + protected HalRepresentation add(Links links) { + return super.add(links); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapper.java index 24ee9b0ce1..87f3454e0f 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapper.java @@ -12,10 +12,13 @@ public class ChangesetCollectionToDtoMapper extends ChangesetCollectionToDtoMapp @Inject public ChangesetCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) { - super(changesetToChangesetDtoMapper); + super(changesetToChangesetDtoMapper, resourceLinks); this.resourceLinks = resourceLinks; } + public CollectionDto map(int pageNumber, int pageSize, PageResult pageResult, Repository repository, String branchName) { + return super.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository), branchName); + } public CollectionDto map(int pageNumber, int pageSize, PageResult pageResult, Repository repository) { return super.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository)); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperBase.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperBase.java index e29a0a92b2..a34b7d44d6 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperBase.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperBase.java @@ -1,5 +1,6 @@ package sonia.scm.api.v2.resources; +import de.otto.edison.hal.Links; import sonia.scm.PageResult; import sonia.scm.repository.Changeset; import sonia.scm.repository.Repository; @@ -10,14 +11,28 @@ import java.util.function.Supplier; class ChangesetCollectionToDtoMapperBase extends PagedCollectionToDtoMapper { private final ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper; + private final ResourceLinks resourceLinks; - ChangesetCollectionToDtoMapperBase(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper) { + ChangesetCollectionToDtoMapperBase(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) { super("changesets"); this.changesetToChangesetDtoMapper = changesetToChangesetDtoMapper; + this.resourceLinks = resourceLinks; } CollectionDto map(int pageNumber, int pageSize, PageResult pageResult, Repository repository, Supplier selfLinkSupplier) { return super.map(pageNumber, pageSize, pageResult, selfLinkSupplier.get(), Optional.empty(), changeset -> changesetToChangesetDtoMapper.map(changeset, repository)); } -} + CollectionDto map(int pageNumber, int pageSize, PageResult pageResult, Repository repository, Supplier selfLinkSupplier, String branchName) { + CollectionDto collectionDto = this.map(pageNumber, pageSize, pageResult, repository, selfLinkSupplier); + collectionDto.withEmbedded("branch", createBranchReferenceDto(repository, branchName)); + return collectionDto; + } + + private BranchReferenceDto createBranchReferenceDto(Repository repository, String branchName) { + BranchReferenceDto branchReferenceDto = new BranchReferenceDto(); + branchReferenceDto.setName(branchName); + branchReferenceDto.add(Links.linkingTo().self(resourceLinks.branch().self(repository.getNamespaceAndName(), branchName)).build()); + return branchReferenceDto; + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java index 717b8d7198..396d055963 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/ChangesetRootResource.java @@ -65,7 +65,11 @@ public class ChangesetRootResource { .getChangesets(); if (changesets != null && changesets.getChangesets() != null) { PageResult pageResult = new PageResult<>(changesets.getChangesets(), changesets.getTotal()); - return Response.ok(changesetCollectionToDtoMapper.map(page, pageSize, pageResult, repository)).build(); + if (changesets.getBranchName() != null) { + return Response.ok(changesetCollectionToDtoMapper.map(page, pageSize, pageResult, repository, changesets.getBranchName())).build(); + } else { + return Response.ok(changesetCollectionToDtoMapper.map(page, pageSize, pageResult, repository)).build(); + } } else { return Response.ok().build(); } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CollectionDto.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CollectionDto.java index c10e18267c..b59d697c2e 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CollectionDto.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/CollectionDto.java @@ -15,4 +15,9 @@ class CollectionDto extends HalRepresentation { CollectionDto(Links links, Embedded embedded) { super(links, embedded); } + + @Override + protected HalRepresentation withEmbedded(String rel, HalRepresentation embeddedItem) { + return super.withEmbedded(rel, embeddedItem); + } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryCollectionToDtoMapper.java b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryCollectionToDtoMapper.java index af7fb2ed83..57e5667c65 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryCollectionToDtoMapper.java +++ b/scm-webapp/src/main/java/sonia/scm/api/v2/resources/FileHistoryCollectionToDtoMapper.java @@ -13,7 +13,7 @@ public class FileHistoryCollectionToDtoMapper extends ChangesetCollectionToDtoMa @Inject public FileHistoryCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) { - super(changesetToChangesetDtoMapper); + super(changesetToChangesetDtoMapper, resourceLinks); this.resourceLinks = resourceLinks; } diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperTest.java new file mode 100644 index 0000000000..69695279e6 --- /dev/null +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/ChangesetCollectionToDtoMapperTest.java @@ -0,0 +1,61 @@ +package sonia.scm.api.v2.resources; + +import org.assertj.core.api.Assertions; +import org.junit.Test; +import sonia.scm.PageResult; +import sonia.scm.repository.Changeset; +import sonia.scm.repository.Repository; + +import java.net.URI; + +import static java.util.Arrays.asList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ChangesetCollectionToDtoMapperTest { + + public static final Repository REPOSITORY = new Repository("", "git", "space", "name"); + public static final Changeset CHANGESET = new Changeset(); + private final ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper = mock(ChangesetToChangesetDtoMapper.class); + + private final ChangesetCollectionToDtoMapper changesetCollectionToDtoMapper = new ChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, ResourceLinksMock.createMock(URI.create("/"))); + + @Test + public void shouldMapCollectionEntries() { + ChangesetDto expectedChangesetDto = new ChangesetDto(); + when(changesetToChangesetDtoMapper.map(CHANGESET, REPOSITORY)).thenReturn(expectedChangesetDto); + + CollectionDto collectionDto = changesetCollectionToDtoMapper.map(0, 1, new PageResult<>(asList(CHANGESET), 1), REPOSITORY); + + assertThat(collectionDto.getEmbedded().hasItem("changesets")).isTrue(); + assertThat(collectionDto.getEmbedded().getItemsBy("changesets")).containsExactly(expectedChangesetDto); + assertThat(collectionDto.getEmbedded().hasItem("branch")).isFalse(); + } + + @Test + public void shouldNotEmbedBranchIfNotSpecified() { + ChangesetDto expectedChangesetDto = new ChangesetDto(); + when(changesetToChangesetDtoMapper.map(CHANGESET, REPOSITORY)).thenReturn(expectedChangesetDto); + + CollectionDto collectionDto = changesetCollectionToDtoMapper.map(0, 1, new PageResult<>(asList(CHANGESET), 1), REPOSITORY); + + assertThat(collectionDto.getEmbedded().hasItem("branch")).isFalse(); + } + + @Test + public void shouldEmbedBranchIfSpecified() { + ChangesetDto expectedChangesetDto = new ChangesetDto(); + when(changesetToChangesetDtoMapper.map(CHANGESET, REPOSITORY)).thenReturn(expectedChangesetDto); + + CollectionDto collectionDto = changesetCollectionToDtoMapper.map(0, 1, new PageResult<>(asList(CHANGESET), 1), REPOSITORY, "someBranch"); + + assertThat(collectionDto.getEmbedded().hasItem("branch")).isTrue(); + assertThat(collectionDto.getEmbedded().getItemsBy("branch")) + .hasSize(1) + .first().matches(b -> b.getLinks().getLinkBy("self").isPresent()) + .extracting(b -> b.getLinks().getLinkBy("self").get().getHref()).first().isEqualTo("/v2/repositories/space/name/branches/someBranch"); + assertThat(collectionDto.getEmbedded().getItemsBy("branch")) + .first().extracting("name").first().isEqualTo("someBranch"); + } +} From e35ec519cbfafce1ee673c9d7e17856764f31f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 28 Sep 2018 10:14:04 +0200 Subject: [PATCH 02/12] Add method to retrieve branch name from repository --- .../java/sonia/scm/repository/GitUtil.java | 29 +++++++++++++- .../repository/spi/AbstractGitCommand.java | 8 ++-- .../scm/repository/spi/GitLogCommand.java | 2 +- .../scm/repository/spi/GitLogCommandTest.java | 39 ++++++++++++++++--- 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 7e145f2dd9..ed698ef00e 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -499,6 +499,33 @@ public final class GitUtil return ref; } + public static String getRepositoryHeadBranchName(org.eclipse.jgit.lib.Repository repo) { + Map refs = repo.getAllRefs(); + Ref lastHeadRef = null; + + for (Map.Entry e : refs.entrySet()) { + String key = e.getKey(); + + if (REF_HEAD.equals(key)) { + if (e.getValue().isSymbolic() && isBranch(e.getValue().getTarget().getName())) { + return getBranch(e.getValue().getTarget()); + } + } else if (key.startsWith(REF_HEAD_PREFIX)) { + if (REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { + return REF_MASTER; + } else { + lastHeadRef = e.getValue(); + } + } + } + + if (lastHeadRef == null) { + return null; + } else { + return getBranch(lastHeadRef); + } + } + /** * Method description * @@ -648,7 +675,7 @@ public final class GitUtil return tagName; } - + /** * Method description * diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index ed2d06e209..db7adce3f8 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -97,9 +97,9 @@ public class AbstractGitCommand return commit; } - protected String getBranchNameOrDefault(String requestedBranch) { + protected String getBranchNameOrDefault(Repository gitRepository, String requestedBranch) { if ( Strings.isNullOrEmpty(requestedBranch) ) { - return getDefaultBranchName(); + return getDefaultBranchName(gitRepository); } else { return requestedBranch; } @@ -115,12 +115,12 @@ public class AbstractGitCommand return head; } - protected String getDefaultBranchName() { + protected String getDefaultBranchName(Repository gitRepository) { String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); if (!Strings.isNullOrEmpty(defaultBranchName)) { return defaultBranchName; } else { - return null; + return GitUtil.getRepositoryHeadBranchName(gitRepository); } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java index 9b106e95a2..146962fa80 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java @@ -208,7 +208,7 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand } ObjectId head = getBranchOrDefault(repository, request.getBranch()); - String branch = getBranchNameOrDefault(request.getBranch()); + String branch = getBranchNameOrDefault(repository,request.getBranch()); if (head != null) { if (startId != null) { diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java index b1420cb885..2709646aba 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java @@ -1,3 +1,4 @@ + /** * Copyright (c) 2010, Sebastian Sdorra * All rights reserved. @@ -33,24 +34,24 @@ package sonia.scm.repository.spi; -//~--- non-JDK imports -------------------------------------------------------- - +import com.google.common.io.Files; import org.junit.Test; import sonia.scm.repository.Changeset; import sonia.scm.repository.ChangesetPagingResult; import sonia.scm.repository.GitConstants; import sonia.scm.repository.Modifications; +import java.io.File; +import java.io.IOException; + +import static java.nio.charset.Charset.defaultCharset; import static org.hamcrest.Matchers.contains; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; -//~--- JDK imports ------------------------------------------------------------ - /** * Unit tests for {@link GitLogCommand}. * @@ -73,7 +74,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase assertEquals("86a6645eceefe8b9a247db5eb16e3d89a7e6e6d1", result.getChangesets().get(1).getId()); assertEquals("592d797cd36432e591416e8b2b98154f4f163411", result.getChangesets().get(2).getId()); assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", result.getChangesets().get(3).getId()); - assertNull(result.getBranchName()); + assertEquals("master", result.getBranchName()); assertTrue(result.getChangesets().stream().allMatch(r -> r.getBranches().isEmpty())); // set default branch and fetch again @@ -215,6 +216,32 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", c2.getId()); } + @Test + public void shouldFindDefaultBranchFromHEAD() throws Exception { + setRepositoryHeadReference("ref: refs/heads/test-branch"); + + ChangesetPagingResult changesets = createCommand().getChangesets(new LogCommandRequest()); + + assertEquals("test-branch", changesets.getBranchName()); + } + + @Test + public void shouldFindMasterBranchWhenHEADisNoRef() throws Exception { + setRepositoryHeadReference("592d797cd36432e591416e8b2b98154f4f163411"); + + ChangesetPagingResult changesets = createCommand().getChangesets(new LogCommandRequest()); + + assertEquals("master", changesets.getBranchName()); + } + + private void setRepositoryHeadReference(String s) throws IOException { + Files.write(s, repositoryHeadReferenceFile(), defaultCharset()); + } + + private File repositoryHeadReferenceFile() { + return new File(repositoryDirectory, "HEAD"); + } + private GitLogCommand createCommand() { return new GitLogCommand(createContext(), repository); From 964f2eab2ed2f3cd3749e8114e80fa9e2ff10a91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 28 Sep 2018 11:18:36 +0200 Subject: [PATCH 03/12] Remove duplication --- .../java/sonia/scm/repository/GitUtil.java | 95 ++++++------------- 1 file changed, 31 insertions(+), 64 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index ed698ef00e..d317f07445 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -63,8 +63,12 @@ import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; +import static java.util.Optional.of; +import static java.util.Optional.ofNullable; + //~--- JDK imports ------------------------------------------------------------ /** @@ -500,76 +504,16 @@ public final class GitUtil } public static String getRepositoryHeadBranchName(org.eclipse.jgit.lib.Repository repo) { - Map refs = repo.getAllRefs(); - Ref lastHeadRef = null; - - for (Map.Entry e : refs.entrySet()) { - String key = e.getKey(); - - if (REF_HEAD.equals(key)) { - if (e.getValue().isSymbolic() && isBranch(e.getValue().getTarget().getName())) { - return getBranch(e.getValue().getTarget()); - } - } else if (key.startsWith(REF_HEAD_PREFIX)) { - if (REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { - return REF_MASTER; - } else { - lastHeadRef = e.getValue(); - } - } - } - - if (lastHeadRef == null) { - return null; - } else { - return getBranch(lastHeadRef); - } + return getRepositoryHeadRef(repo).map(GitUtil::getBranch).orElse(null); } - /** - * Method description - * - * - * @param repo - * - * @return - * - * @throws IOException - */ public static ObjectId getRepositoryHead(org.eclipse.jgit.lib.Repository repo) throws IOException { - ObjectId id = null; - String head = null; - Map refs = repo.getAllRefs(); + Optional headRef = getRepositoryHeadRef(repo); - for (Map.Entry e : refs.entrySet()) - { - String key = e.getKey(); - - if (REF_HEAD.equals(key)) - { - head = REF_HEAD; - id = e.getValue().getObjectId(); - - break; - } - else if (key.startsWith(REF_HEAD_PREFIX)) - { - id = e.getValue().getObjectId(); - head = key.substring(REF_HEAD_PREFIX.length()); - - if (REF_MASTER.equals(head)) - { - break; - } - } - } - - if (id == null) - { - id = repo.resolve(Constants.HEAD); - } + String head = headRef.map(GitUtil::getBranch).orElse(null); + ObjectId id = headRef.map(Ref::getObjectId).orElse(repo.resolve(Constants.HEAD)); if (logger.isDebugEnabled()) { @@ -590,6 +534,29 @@ public final class GitUtil return id; } + public static Optional getRepositoryHeadRef(org.eclipse.jgit.lib.Repository repo) { + Map refs = repo.getAllRefs(); + Ref lastHeadRef = null; + + for (Map.Entry e : refs.entrySet()) { + String key = e.getKey(); + + if (REF_HEAD.equals(key)) { + if (e.getValue().isSymbolic() && isBranch(e.getValue().getTarget().getName())) { + return of(e.getValue().getTarget()); + } + } else if (key.startsWith(REF_HEAD_PREFIX)) { + if (REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { + return of(e.getValue()); + } else { + lastHeadRef = e.getValue(); + } + } + } + + return ofNullable(lastHeadRef); + } + /** * Method description * From 6819d6a0fe85cc4d55e40484b77d1d391a365fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 28 Sep 2018 13:17:42 +0200 Subject: [PATCH 04/12] Remove unnecessary HEAD resolving --- .../java/sonia/scm/repository/GitUtil.java | 60 +++++++++---------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index d317f07445..64226fb912 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -66,6 +66,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; +import static java.util.Optional.empty; import static java.util.Optional.of; import static java.util.Optional.ofNullable; @@ -507,35 +508,13 @@ public final class GitUtil return getRepositoryHeadRef(repo).map(GitUtil::getBranch).orElse(null); } - public static ObjectId getRepositoryHead(org.eclipse.jgit.lib.Repository repo) - throws IOException - { - Optional headRef = getRepositoryHeadRef(repo); - - String head = headRef.map(GitUtil::getBranch).orElse(null); - ObjectId id = headRef.map(Ref::getObjectId).orElse(repo.resolve(Constants.HEAD)); - - if (logger.isDebugEnabled()) - { - if ((head != null) && (id != null)) - { - logger.debug("use {}:{} as repository head", head, id.name()); - } - else if (id != null) - { - logger.debug("use {} as repository head", id.name()); - } - else - { - logger.warn("could not find repository head"); - } - } - - return id; + public static ObjectId getRepositoryHead(org.eclipse.jgit.lib.Repository repo) { + return getRepositoryHeadRef(repo).map(Ref::getObjectId).orElse(null); } public static Optional getRepositoryHeadRef(org.eclipse.jgit.lib.Repository repo) { Map refs = repo.getAllRefs(); + Optional foundRef = empty(); Ref lastHeadRef = null; for (Map.Entry e : refs.entrySet()) { @@ -543,18 +522,33 @@ public final class GitUtil if (REF_HEAD.equals(key)) { if (e.getValue().isSymbolic() && isBranch(e.getValue().getTarget().getName())) { - return of(e.getValue().getTarget()); - } - } else if (key.startsWith(REF_HEAD_PREFIX)) { - if (REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { - return of(e.getValue()); - } else { - lastHeadRef = e.getValue(); + foundRef = of(e.getValue().getTarget()); + break; } + } else if (key.startsWith(REF_HEAD_PREFIX) && REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { + foundRef = of(e.getValue()); + break; + } else { + lastHeadRef = e.getValue(); } } - return ofNullable(lastHeadRef); + if (!foundRef.isPresent()) { + foundRef = ofNullable(lastHeadRef); + } + + if (foundRef.isPresent()) { + if (logger.isDebugEnabled()) { + logger.debug("use {}:{} as repository head for directory {}", + foundRef.map(GitUtil::getBranch).orElse(null), + foundRef.map(Ref::getObjectId).orElse(null).name(), + repo.getDirectory()); + } + } else { + logger.warn("could not find repository head in directory {}", repo.getDirectory()); + } + + return foundRef; } /** From 3dd632888b0bc0d3344a602bfd6276ff559ad79f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 28 Sep 2018 16:09:09 +0200 Subject: [PATCH 05/12] Fix optional mapping --- .../src/main/java/sonia/scm/repository/GitUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 64226fb912..0f6daff0e0 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -541,7 +541,7 @@ public final class GitUtil if (logger.isDebugEnabled()) { logger.debug("use {}:{} as repository head for directory {}", foundRef.map(GitUtil::getBranch).orElse(null), - foundRef.map(Ref::getObjectId).orElse(null).name(), + foundRef.map(Ref::getObjectId).map(ObjectId::name).orElse(null), repo.getDirectory()); } } else { From 0356af9ced8cf91d6c0d0203f4323f651041695d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 28 Sep 2018 16:19:41 +0200 Subject: [PATCH 06/12] Fix head ref computation --- .../src/main/java/sonia/scm/repository/GitUtil.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 0f6daff0e0..aac0557d7f 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -525,11 +525,13 @@ public final class GitUtil foundRef = of(e.getValue().getTarget()); break; } - } else if (key.startsWith(REF_HEAD_PREFIX) && REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { - foundRef = of(e.getValue()); - break; - } else { - lastHeadRef = e.getValue(); + } else if (key.startsWith(REF_HEAD_PREFIX)) { + if (REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { + foundRef = of(e.getValue()); + break; + } else { + lastHeadRef = e.getValue(); + } } } From 4b7940ac50b96309150826117431563247c9d30b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 2 Oct 2018 13:20:52 +0200 Subject: [PATCH 07/12] Cleanup computation of default branch --- .../java/sonia/scm/repository/GitUtil.java | 57 +++++++++---------- .../repository/spi/AbstractGitCommand.java | 37 +++++------- .../scm/repository/spi/GitLogCommand.java | 9 ++- 3 files changed, 45 insertions(+), 58 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index aac0557d7f..3590809795 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -39,6 +39,8 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; +import lombok.AllArgsConstructor; +import lombok.Getter; import org.eclipse.jgit.api.FetchCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; @@ -66,9 +68,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.TimeUnit; -import static java.util.Optional.empty; import static java.util.Optional.of; -import static java.util.Optional.ofNullable; //~--- JDK imports ------------------------------------------------------------ @@ -504,40 +504,12 @@ public final class GitUtil return ref; } - public static String getRepositoryHeadBranchName(org.eclipse.jgit.lib.Repository repo) { - return getRepositoryHeadRef(repo).map(GitUtil::getBranch).orElse(null); - } - public static ObjectId getRepositoryHead(org.eclipse.jgit.lib.Repository repo) { return getRepositoryHeadRef(repo).map(Ref::getObjectId).orElse(null); } public static Optional getRepositoryHeadRef(org.eclipse.jgit.lib.Repository repo) { - Map refs = repo.getAllRefs(); - Optional foundRef = empty(); - Ref lastHeadRef = null; - - for (Map.Entry e : refs.entrySet()) { - String key = e.getKey(); - - if (REF_HEAD.equals(key)) { - if (e.getValue().isSymbolic() && isBranch(e.getValue().getTarget().getName())) { - foundRef = of(e.getValue().getTarget()); - break; - } - } else if (key.startsWith(REF_HEAD_PREFIX)) { - if (REF_MASTER.equals(key.substring(REF_HEAD_PREFIX.length()))) { - foundRef = of(e.getValue()); - break; - } else { - lastHeadRef = e.getValue(); - } - } - } - - if (!foundRef.isPresent()) { - foundRef = ofNullable(lastHeadRef); - } + Optional foundRef = findMostAppropriateHead(repo.getAllRefs()); if (foundRef.isPresent()) { if (logger.isDebugEnabled()) { @@ -553,6 +525,29 @@ public final class GitUtil return foundRef; } + private static Optional findMostAppropriateHead(Map refs) { + Ref refHead = refs.get(REF_HEAD); + if (refHead != null && refHead.isSymbolic() && isBranch(refHead.getTarget().getName())) { + return of(refHead); + } + + Ref master = refs.get(REF_HEAD_PREFIX + REF_MASTER); + if (master != null) { + return of(master); + } + + Ref defaultBranch = refs.get(REF_HEAD_PREFIX + "default"); + if (defaultBranch != null) { + return of(defaultBranch); + } + + return refs.entrySet() + .stream() + .filter(e -> e.getKey().startsWith(REF_HEAD_PREFIX)) + .map(Map.Entry::getValue) + .findFirst(); + } + /** * Method description * diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index db7adce3f8..f12d1920c7 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -35,11 +35,16 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.base.Strings; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; //~--- JDK imports ------------------------------------------------------------ import java.io.IOException; +import java.util.Optional; + import org.eclipse.jgit.lib.ObjectId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -97,30 +102,12 @@ public class AbstractGitCommand return commit; } - protected String getBranchNameOrDefault(Repository gitRepository, String requestedBranch) { + protected BranchWithId getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException { if ( Strings.isNullOrEmpty(requestedBranch) ) { - return getDefaultBranchName(gitRepository); + Optional repositoryHeadRef = GitUtil.getRepositoryHeadRef(gitRepository); + return repositoryHeadRef.map(r -> new BranchWithId(GitUtil.getBranch(r), r.getObjectId())).orElse(null); } else { - return requestedBranch; - } - } - - protected ObjectId getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException { - ObjectId head; - if ( Strings.isNullOrEmpty(requestedBranch) ) { - head = getDefaultBranch(gitRepository); - } else { - head = GitUtil.getBranchId(gitRepository, requestedBranch); - } - return head; - } - - protected String getDefaultBranchName(Repository gitRepository) { - String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); - if (!Strings.isNullOrEmpty(defaultBranchName)) { - return defaultBranchName; - } else { - return GitUtil.getRepositoryHeadBranchName(gitRepository); + return new BranchWithId(requestedBranch, GitUtil.getBranchId(gitRepository, requestedBranch)); } } @@ -143,4 +130,10 @@ public class AbstractGitCommand /** Field description */ protected sonia.scm.repository.Repository repository; + + @Getter @AllArgsConstructor + static class BranchWithId { + private final String name; + private final ObjectId objectId; + } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java index 146962fa80..6d742012ae 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java @@ -207,14 +207,13 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF)); } - ObjectId head = getBranchOrDefault(repository, request.getBranch()); - String branch = getBranchNameOrDefault(repository,request.getBranch()); + BranchWithId branch = getBranchOrDefault(repository,request.getBranch()); - if (head != null) { + if (branch != null) { if (startId != null) { revWalk.markStart(revWalk.lookupCommit(startId)); } else { - revWalk.markStart(revWalk.lookupCommit(head)); + revWalk.markStart(revWalk.lookupCommit(branch.getObjectId())); } Iterator iterator = revWalk.iterator(); @@ -236,7 +235,7 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand } if (branch != null) { - changesets = new ChangesetPagingResult(counter, changesetList, branch); + changesets = new ChangesetPagingResult(counter, changesetList, branch.getName()); } else { changesets = new ChangesetPagingResult(counter, changesetList); } From 5a1f15b8c8ce4cbc0f1aead8b23d255a1fb4afb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 2 Oct 2018 13:41:20 +0200 Subject: [PATCH 08/12] Fix usage of default branch --- .../java/sonia/scm/repository/GitUtil.java | 18 +++++---------- .../repository/spi/AbstractGitCommand.java | 22 +++++++++---------- .../scm/repository/spi/GitLogCommand.java | 5 +++-- .../scm/repository/spi/GitLogCommandTest.java | 2 +- 4 files changed, 21 insertions(+), 26 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 3590809795..803348dc33 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -350,12 +350,11 @@ public final class GitUtil * * @throws IOException */ - public static ObjectId getBranchId(org.eclipse.jgit.lib.Repository repo, + public static Ref getBranchId(org.eclipse.jgit.lib.Repository repo, String branchName) throws IOException { - ObjectId branchId = null; - + Ref ref = null; if (!branchName.startsWith(REF_HEAD)) { branchName = PREFIX_HEADS.concat(branchName); @@ -365,24 +364,19 @@ public final class GitUtil try { - Ref ref = repo.findRef(branchName); + ref = repo.findRef(branchName); - if (ref != null) - { - branchId = ref.getObjectId(); - } - else if (logger.isWarnEnabled()) + if (ref == null) { logger.warn("could not find branch for {}", branchName); } - } catch (IOException ex) { logger.warn("error occured during resolve of branch id", ex); } - return branchId; + return ref; } /** @@ -528,7 +522,7 @@ public final class GitUtil private static Optional findMostAppropriateHead(Map refs) { Ref refHead = refs.get(REF_HEAD); if (refHead != null && refHead.isSymbolic() && isBranch(refHead.getTarget().getName())) { - return of(refHead); + return of(refHead.getTarget()); } Ref master = refs.get(REF_HEAD_PREFIX + REF_MASTER); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index f12d1920c7..8e1a48ed1d 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -102,12 +102,17 @@ public class AbstractGitCommand return commit; } - protected BranchWithId getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException { + protected Ref getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException { if ( Strings.isNullOrEmpty(requestedBranch) ) { - Optional repositoryHeadRef = GitUtil.getRepositoryHeadRef(gitRepository); - return repositoryHeadRef.map(r -> new BranchWithId(GitUtil.getBranch(r), r.getObjectId())).orElse(null); + String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); + if (!Strings.isNullOrEmpty(defaultBranchName)) { + return GitUtil.getBranchId(gitRepository, defaultBranchName); + } else { + Optional repositoryHeadRef = GitUtil.getRepositoryHeadRef(gitRepository); + return repositoryHeadRef.orElse(null); + } } else { - return new BranchWithId(requestedBranch, GitUtil.getBranchId(gitRepository, requestedBranch)); + return GitUtil.getBranchId(gitRepository, requestedBranch); } } @@ -115,7 +120,8 @@ public class AbstractGitCommand ObjectId head; String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); if (!Strings.isNullOrEmpty(defaultBranchName)) { - head = GitUtil.getBranchId(gitRepository, defaultBranchName); + Ref ref = GitUtil.getBranchId(gitRepository, defaultBranchName); + head = ref == null? null: ref.getObjectId(); } else { logger.trace("no default branch configured, use repository head as default"); head = GitUtil.getRepositoryHead(gitRepository); @@ -130,10 +136,4 @@ public class AbstractGitCommand /** Field description */ protected sonia.scm.repository.Repository repository; - - @Getter @AllArgsConstructor - static class BranchWithId { - private final String name; - private final ObjectId objectId; - } } diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java index 6d742012ae..4e9261f517 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitLogCommand.java @@ -39,6 +39,7 @@ import com.google.common.base.Strings; import com.google.common.collect.Lists; import org.eclipse.jgit.errors.MissingObjectException; import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; @@ -207,7 +208,7 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF)); } - BranchWithId branch = getBranchOrDefault(repository,request.getBranch()); + Ref branch = getBranchOrDefault(repository,request.getBranch()); if (branch != null) { if (startId != null) { @@ -235,7 +236,7 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand } if (branch != null) { - changesets = new ChangesetPagingResult(counter, changesetList, branch.getName()); + changesets = new ChangesetPagingResult(counter, changesetList, GitUtil.getBranch(branch.getName())); } else { changesets = new ChangesetPagingResult(counter, changesetList); } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java index 2709646aba..78db8ae686 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitLogCommandTest.java @@ -83,11 +83,11 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase result = createCommand().getChangesets(new LogCommandRequest()); assertNotNull(result); + assertEquals("test-branch", result.getBranchName()); assertEquals(3, result.getTotal()); assertEquals("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4", result.getChangesets().get(0).getId()); assertEquals("592d797cd36432e591416e8b2b98154f4f163411", result.getChangesets().get(1).getId()); assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", result.getChangesets().get(2).getId()); - assertEquals("test-branch", result.getBranchName()); assertTrue(result.getChangesets().stream().allMatch(r -> r.getBranches().isEmpty())); } From de6b94fa4c220b17e4ed74c74f113768c4f6067f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Tue, 2 Oct 2018 13:44:22 +0200 Subject: [PATCH 09/12] Remove code duplication --- .../repository/spi/AbstractGitCommand.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index 8e1a48ed1d..df21d61eef 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -102,12 +102,22 @@ public class AbstractGitCommand return commit; } + protected ObjectId getDefaultBranch(Repository gitRepository) throws IOException { + Ref ref = getBranchOrDefault(gitRepository, null); + if (ref == null) { + return null; + } else { + return ref.getObjectId(); + } + } + protected Ref getBranchOrDefault(Repository gitRepository, String requestedBranch) throws IOException { if ( Strings.isNullOrEmpty(requestedBranch) ) { String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); if (!Strings.isNullOrEmpty(defaultBranchName)) { return GitUtil.getBranchId(gitRepository, defaultBranchName); } else { + logger.trace("no default branch configured, use repository head as default"); Optional repositoryHeadRef = GitUtil.getRepositoryHeadRef(gitRepository); return repositoryHeadRef.orElse(null); } @@ -116,19 +126,6 @@ public class AbstractGitCommand } } - protected ObjectId getDefaultBranch(Repository gitRepository) throws IOException { - ObjectId head; - String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH); - if (!Strings.isNullOrEmpty(defaultBranchName)) { - Ref ref = GitUtil.getBranchId(gitRepository, defaultBranchName); - head = ref == null? null: ref.getObjectId(); - } else { - logger.trace("no default branch configured, use repository head as default"); - head = GitUtil.getRepositoryHead(gitRepository); - } - return head; - } - //~--- fields --------------------------------------------------------------- /** Field description */ From 8de89928b385c107dce0e3e6736fb358a0f86523 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 9 Oct 2018 08:50:20 +0200 Subject: [PATCH 10/12] remove unused imports --- .../main/java/sonia/scm/repository/GitUtil.java | 2 -- .../scm/repository/spi/AbstractGitCommand.java | 15 ++++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index 803348dc33..faa654307b 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -39,8 +39,6 @@ import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; -import lombok.AllArgsConstructor; -import lombok.Getter; import org.eclipse.jgit.api.FetchCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java index df21d61eef..2970bbd627 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/AbstractGitCommand.java @@ -35,22 +35,19 @@ package sonia.scm.repository.spi; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.base.Strings; -import lombok.AllArgsConstructor; -import lombok.Getter; +import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; - -//~--- JDK imports ------------------------------------------------------------ - -import java.io.IOException; -import java.util.Optional; - -import org.eclipse.jgit.lib.ObjectId; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.repository.GitConstants; import sonia.scm.repository.GitUtil; +import java.io.IOException; +import java.util.Optional; + +//~--- JDK imports ------------------------------------------------------------ + /** * * @author Sebastian Sdorra From 768309cea45a2efe9981539b618923e103ece25b Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 9 Oct 2018 08:52:33 +0200 Subject: [PATCH 11/12] use develop branch instead of default --- .../src/main/java/sonia/scm/repository/GitUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java index faa654307b..13340a20e7 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/GitUtil.java @@ -528,9 +528,9 @@ public final class GitUtil return of(master); } - Ref defaultBranch = refs.get(REF_HEAD_PREFIX + "default"); - if (defaultBranch != null) { - return of(defaultBranch); + Ref develop = refs.get(REF_HEAD_PREFIX + "develop"); + if (develop != null) { + return of(develop); } return refs.entrySet() From 2c476c34ef1f75883dc42c769fde970f5e060f47 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Tue, 9 Oct 2018 09:10:20 +0000 Subject: [PATCH 12/12] Close branch feature/harmonize_branches_in_changesets