Merged in feature/harmonize_branches_in_changesets (pull request #81)

Add branch to changeset collections
This commit is contained in:
Sebastian Sdorra
2018-10-09 09:10:20 +00:00
17 changed files with 292 additions and 158 deletions

View File

@@ -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<String> branches = Lists.newArrayList();
Set<Ref> 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<String> branches)
throws IOException
{
String id = commit.getId().name();
List<String> parentList = null;

View File

@@ -63,8 +63,11 @@ 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;
//~--- JDK imports ------------------------------------------------------------
/**
@@ -345,12 +348,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);
@@ -360,24 +362,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;
}
/**
@@ -499,68 +496,48 @@ public final class GitUtil
return ref;
}
/**
* 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<String, Ref> refs = repo.getAllRefs();
public static ObjectId getRepositoryHead(org.eclipse.jgit.lib.Repository repo) {
return getRepositoryHeadRef(repo).map(Ref::getObjectId).orElse(null);
}
for (Map.Entry<String, Ref> e : refs.entrySet())
{
String key = e.getKey();
public static Optional<Ref> getRepositoryHeadRef(org.eclipse.jgit.lib.Repository repo) {
Optional<Ref> foundRef = findMostAppropriateHead(repo.getAllRefs());
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 (foundRef.isPresent()) {
if (logger.isDebugEnabled()) {
logger.debug("use {}:{} as repository head for directory {}",
foundRef.map(GitUtil::getBranch).orElse(null),
foundRef.map(Ref::getObjectId).map(ObjectId::name).orElse(null),
repo.getDirectory());
}
} else {
logger.warn("could not find repository head in directory {}", repo.getDirectory());
}
if (id == null)
{
id = repo.resolve(Constants.HEAD);
return foundRef;
}
private static Optional<Ref> findMostAppropriateHead(Map<String, Ref> refs) {
Ref refHead = refs.get(REF_HEAD);
if (refHead != null && refHead.isSymbolic() && isBranch(refHead.getTarget().getName())) {
return of(refHead.getTarget());
}
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");
}
Ref master = refs.get(REF_HEAD_PREFIX + REF_MASTER);
if (master != null) {
return of(master);
}
return id;
Ref develop = refs.get(REF_HEAD_PREFIX + "develop");
if (develop != null) {
return of(develop);
}
return refs.entrySet()
.stream()
.filter(e -> e.getKey().startsWith(REF_HEAD_PREFIX))
.map(Map.Entry::getValue)
.findFirst();
}
/**
@@ -648,7 +625,7 @@ public final class GitUtil
return tagName;
}
/**
* Method description
*

View File

@@ -34,19 +34,20 @@ 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;
//~--- JDK imports ------------------------------------------------------------
import java.io.IOException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
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
@@ -97,27 +98,29 @@ public class AbstractGitCommand
}
return commit;
}
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 ObjectId getDefaultBranch(Repository gitRepository) throws IOException {
ObjectId head;
String defaultBranchName = repository.getProperty(GitConstants.PROPERTY_DEFAULT_BRANCH);
if (!Strings.isNullOrEmpty(defaultBranchName)) {
head = GitUtil.getBranchId(gitRepository, defaultBranchName);
Ref ref = getBranchOrDefault(gitRepository, null);
if (ref == null) {
return null;
} else {
logger.trace("no default branch configured, use repository head as default");
head = GitUtil.getRepositoryHead(gitRepository);
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<Ref> repositoryHeadRef = GitUtil.getRepositoryHeadRef(gitRepository);
return repositoryHeadRef.orElse(null);
}
} else {
return GitUtil.getBranchId(gitRepository, requestedBranch);
}
return head;
}
//~--- fields ---------------------------------------------------------------

View File

@@ -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;
@@ -170,8 +171,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 +189,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,13 +208,13 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF));
}
ObjectId head = getBranchOrDefault(gr, request.getBranch());
Ref 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<RevCommit> iterator = revWalk.iterator();
@@ -234,10 +235,14 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
}
}
changesets = new ChangesetPagingResult(counter, changesetList);
if (branch != null) {
changesets = new ChangesetPagingResult(counter, changesetList, GitUtil.getBranch(branch.getName()));
} 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);
}

View File

@@ -1,3 +1,4 @@
/**
* Copyright (c) 2010, Sebastian Sdorra
* All rights reserved.
@@ -33,14 +34,17 @@
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;
@@ -48,8 +52,6 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
//~--- JDK imports ------------------------------------------------------------
/**
* Unit tests for {@link GitLogCommand}.
*
@@ -72,6 +74,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());
assertEquals("master", 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");
@@ -79,10 +83,12 @@ 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());
assertTrue(result.getChangesets().stream().allMatch(r -> r.getBranches().isEmpty()));
}
@Test
@@ -210,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);