Merged in feature/log_two_revisions (pull request #104)

Feature log two revisions
This commit is contained in:
Sebastian Sdorra
2018-11-07 14:07:50 +00:00
7 changed files with 124 additions and 11 deletions

View File

@@ -398,6 +398,11 @@ public final class LogCommandBuilder
return this; return this;
} }
public LogCommandBuilder setAncestorChangeset(String ancestorChangeset) {
request.setAncestorChangeset(ancestorChangeset);
return this;
}
//~--- inner classes -------------------------------------------------------- //~--- inner classes --------------------------------------------------------
/** /**

View File

@@ -84,7 +84,8 @@ public final class LogCommandRequest implements Serializable, Resetable
&& Objects.equal(pagingStart, other.pagingStart) && Objects.equal(pagingStart, other.pagingStart)
&& Objects.equal(pagingLimit, other.pagingLimit) && Objects.equal(pagingLimit, other.pagingLimit)
&& Objects.equal(path, other.path) && Objects.equal(path, other.path)
&& Objects.equal(branch, other.branch); && Objects.equal(branch, other.branch)
&& Objects.equal(ancestorChangeset, other.ancestorChangeset);
//J+ //J+
} }
@@ -98,7 +99,7 @@ public final class LogCommandRequest implements Serializable, Resetable
public int hashCode() public int hashCode()
{ {
return Objects.hashCode(startChangeset, endChangeset, pagingStart, return Objects.hashCode(startChangeset, endChangeset, pagingStart,
pagingLimit, path, branch); pagingLimit, path, branch, ancestorChangeset);
} }
/** /**
@@ -114,6 +115,7 @@ public final class LogCommandRequest implements Serializable, Resetable
pagingLimit = 20; pagingLimit = 20;
path = null; path = null;
branch = null; branch = null;
ancestorChangeset = null;
} }
/** /**
@@ -133,6 +135,7 @@ public final class LogCommandRequest implements Serializable, Resetable
.add("pagingLimit", pagingLimit) .add("pagingLimit", pagingLimit)
.add("path", path) .add("path", path)
.add("branch", branch) .add("branch", branch)
.add("ancestorChangeset", ancestorChangeset)
.toString(); .toString();
//J+ //J+
} }
@@ -205,6 +208,10 @@ public final class LogCommandRequest implements Serializable, Resetable
this.startChangeset = startChangeset; this.startChangeset = startChangeset;
} }
public void setAncestorChangeset(String ancestorChangeset) {
this.ancestorChangeset = ancestorChangeset;
}
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/** /**
@@ -284,6 +291,10 @@ public final class LogCommandRequest implements Serializable, Resetable
return pagingLimit < 0; return pagingLimit < 0;
} }
public String getAncestorChangeset() {
return ancestorChangeset;
}
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */ /** Field description */
@@ -303,4 +314,6 @@ public final class LogCommandRequest implements Serializable, Resetable
/** Field description */ /** Field description */
private String startChangeset; private String startChangeset;
private String ancestorChangeset;
} }

View File

@@ -43,6 +43,7 @@ import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.revwalk.filter.RevFilter;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter; import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.treewalk.filter.TreeFilter; import org.eclipse.jgit.treewalk.filter.TreeFilter;
@@ -198,6 +199,14 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
endId = repository.resolve(request.getEndChangeset()); endId = repository.resolve(request.getEndChangeset());
} }
Ref branch = getBranchOrDefault(repository,request.getBranch());
ObjectId ancestorId = null;
if (!Strings.isNullOrEmpty(request.getAncestorChangeset())) {
ancestorId = computeCommonAncestor(request, repository, startId, branch);
}
revWalk = new RevWalk(repository); revWalk = new RevWalk(repository);
converter = new GitChangesetConverter(repository, revWalk); converter = new GitChangesetConverter(repository, revWalk);
@@ -208,8 +217,6 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF)); PathFilter.create(request.getPath()), TreeFilter.ANY_DIFF));
} }
Ref branch = getBranchOrDefault(repository,request.getBranch());
if (branch != null) { if (branch != null) {
if (startId != null) { if (startId != null) {
revWalk.markStart(revWalk.lookupCommit(startId)); revWalk.markStart(revWalk.lookupCommit(startId));
@@ -217,11 +224,16 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
revWalk.markStart(revWalk.lookupCommit(branch.getObjectId())); revWalk.markStart(revWalk.lookupCommit(branch.getObjectId()));
} }
Iterator<RevCommit> iterator = revWalk.iterator(); Iterator<RevCommit> iterator = revWalk.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
RevCommit commit = iterator.next(); RevCommit commit = iterator.next();
if (commit.getId().equals(ancestorId)) {
break;
}
if ((counter >= start) if ((counter >= start)
&& ((limit < 0) || (counter < start + limit))) { && ((limit < 0) || (counter < start + limit))) {
changesetList.add(converter.createChangeset(commit)); changesetList.add(converter.createChangeset(commit));
@@ -229,7 +241,7 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
counter++; counter++;
if ((endId != null) && commit.getId().equals(endId)) { if (commit.getId().equals(endId)) {
break; break;
} }
} }
@@ -263,4 +275,17 @@ public class GitLogCommand extends AbstractGitCommand implements LogCommand
return changesets; return changesets;
} }
private ObjectId computeCommonAncestor(LogCommandRequest request, Repository repository, ObjectId startId, Ref branch) throws IOException {
try (RevWalk mergeBaseWalk = new RevWalk(repository)) {
mergeBaseWalk.setRevFilter(RevFilter.MERGE_BASE);
if (startId != null) {
mergeBaseWalk.markStart(mergeBaseWalk.lookupCommit(startId));
} else {
mergeBaseWalk.markStart(mergeBaseWalk.lookupCommit(branch.getObjectId()));
}
mergeBaseWalk.markStart(mergeBaseWalk.parseCommit(repository.resolve(request.getAncestorChangeset())));
return mergeBaseWalk.next().getId();
}
}
} }

View File

@@ -64,7 +64,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
* Tests log command with the usage of a default branch. * Tests log command with the usage of a default branch.
*/ */
@Test @Test
public void testGetDefaultBranch() throws Exception { public void testGetDefaultBranch() {
// without default branch, the repository head should be used // without default branch, the repository head should be used
ChangesetPagingResult result = createCommand().getChangesets(new LogCommandRequest()); ChangesetPagingResult result = createCommand().getChangesets(new LogCommandRequest());
@@ -92,7 +92,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
} }
@Test @Test
public void testGetAll() throws Exception public void testGetAll()
{ {
ChangesetPagingResult result = ChangesetPagingResult result =
createCommand().getChangesets(new LogCommandRequest()); createCommand().getChangesets(new LogCommandRequest());
@@ -103,7 +103,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
} }
@Test @Test
public void testGetAllByPath() throws Exception public void testGetAllByPath()
{ {
LogCommandRequest request = new LogCommandRequest(); LogCommandRequest request = new LogCommandRequest();
@@ -119,7 +119,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
} }
@Test @Test
public void testGetAllWithLimit() throws Exception public void testGetAllWithLimit()
{ {
LogCommandRequest request = new LogCommandRequest(); LogCommandRequest request = new LogCommandRequest();
@@ -143,7 +143,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
} }
@Test @Test
public void testGetAllWithPaging() throws Exception public void testGetAllWithPaging()
{ {
LogCommandRequest request = new LogCommandRequest(); LogCommandRequest request = new LogCommandRequest();
@@ -194,7 +194,7 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
} }
@Test @Test
public void testGetRange() throws Exception public void testGetRange()
{ {
LogCommandRequest request = new LogCommandRequest(); LogCommandRequest request = new LogCommandRequest();
@@ -216,6 +216,26 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", c2.getId()); assertEquals("435df2f061add3589cb326cc64be9b9c3897ceca", c2.getId());
} }
@Test
public void testGetAncestor()
{
LogCommandRequest request = new LogCommandRequest();
request.setBranch("test-branch");
request.setAncestorChangeset("master");
ChangesetPagingResult result = createCommand().getChangesets(request);
assertNotNull(result);
assertEquals(1, result.getTotal());
assertEquals(1, result.getChangesets().size());
Changeset c = result.getChangesets().get(0);
assertNotNull(c);
assertEquals("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4", c.getId());
}
@Test @Test
public void shouldFindDefaultBranchFromHEAD() throws Exception { public void shouldFindDefaultBranchFromHEAD() throws Exception {
setRepositoryHeadReference("ref: refs/heads/test-branch"); setRepositoryHeadReference("ref: refs/heads/test-branch");

View File

@@ -5,6 +5,7 @@ import com.webcohesion.enunciate.metadata.rs.StatusCodes;
import com.webcohesion.enunciate.metadata.rs.TypeHint; import com.webcohesion.enunciate.metadata.rs.TypeHint;
import sonia.scm.NotFoundException; import sonia.scm.NotFoundException;
import sonia.scm.PageResult; import sonia.scm.PageResult;
import sonia.scm.repository.Branch;
import sonia.scm.repository.Branches; import sonia.scm.repository.Branches;
import sonia.scm.repository.Changeset; import sonia.scm.repository.Changeset;
import sonia.scm.repository.ChangesetPagingResult; import sonia.scm.repository.ChangesetPagingResult;
@@ -26,6 +27,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.IOException; import java.io.IOException;
import java.util.List;
public class BranchRootResource { public class BranchRootResource {
@@ -124,6 +126,49 @@ public class BranchRootResource {
} }
} }
@Path("{branch}/diffchangesets/{otherBranchName}")
@GET
@StatusCodes({
@ResponseCode(code = 200, condition = "success"),
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
@ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the changeset"),
@ResponseCode(code = 404, condition = "not found, no changesets available in the repository"),
@ResponseCode(code = 500, condition = "internal server error")
})
@Produces(VndMediaType.CHANGESET_COLLECTION)
@TypeHint(CollectionDto.class)
public Response changesetDiff(@PathParam("namespace") String namespace,
@PathParam("name") String name,
@PathParam("branch") String branchName,
@PathParam("otherBranchName") String otherBranchName,
@DefaultValue("0") @QueryParam("page") int page,
@DefaultValue("10") @QueryParam("pageSize") int pageSize) throws Exception {
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
List<Branch> allBranches = repositoryService.getBranchesCommand().getBranches().getBranches();
if (allBranches.stream().noneMatch(branch -> branchName.equals(branch.getName()))) {
throw new NotFoundException("branch", branchName);
}
if (allBranches.stream().noneMatch(branch -> otherBranchName.equals(branch.getName()))) {
throw new NotFoundException("branch", otherBranchName);
}
Repository repository = repositoryService.getRepository();
RepositoryPermissions.read(repository).check();
ChangesetPagingResult changesets = new PagedLogCommandBuilder(repositoryService)
.page(page)
.pageSize(pageSize)
.create()
.setBranch(branchName)
.setAncestorChangeset(otherBranchName)
.getChangesets();
if (changesets != null && changesets.getChangesets() != null) {
PageResult<Changeset> pageResult = new PageResult<>(changesets.getChangesets(), changesets.getTotal());
return Response.ok(branchChangesetCollectionToDtoMapper.map(page, pageSize, pageResult, repository, branchName)).build();
} else {
return Response.ok().build();
}
}
}
/** /**
* Returns the branches for a repository. * Returns the branches for a repository.
* *

View File

@@ -28,6 +28,7 @@ public abstract class BranchToBranchDtoMapper {
Links.Builder linksBuilder = linkingTo() Links.Builder linksBuilder = linkingTo()
.self(resourceLinks.branch().self(namespaceAndName, target.getName())) .self(resourceLinks.branch().self(namespaceAndName, target.getName()))
.single(linkBuilder("history", resourceLinks.branch().history(namespaceAndName, target.getName())).build()) .single(linkBuilder("history", resourceLinks.branch().history(namespaceAndName, target.getName())).build())
.single(linkBuilder("changesetDiff", resourceLinks.branch().changesetDiff(namespaceAndName, target.getName())).build())
.single(linkBuilder("changeset", resourceLinks.changeset().changeset(namespaceAndName.getNamespace(), namespaceAndName.getName(), target.getRevision())).build()) .single(linkBuilder("changeset", resourceLinks.changeset().changeset(namespaceAndName.getNamespace(), namespaceAndName.getName(), target.getRevision())).build())
.single(linkBuilder("source", resourceLinks.source().self(namespaceAndName.getNamespace(), namespaceAndName.getName(), target.getRevision())).build()); .single(linkBuilder("source", resourceLinks.source().self(namespaceAndName.getNamespace(), namespaceAndName.getName(), target.getRevision())).build());
target.add(linksBuilder.build()); target.add(linksBuilder.build());

View File

@@ -322,6 +322,10 @@ class ResourceLinks {
public String history(NamespaceAndName namespaceAndName, String branch) { public String history(NamespaceAndName namespaceAndName, String branch) {
return branchLinkBuilder.method("getRepositoryResource").parameters(namespaceAndName.getNamespace(), namespaceAndName.getName()).method("branches").parameters().method("history").parameters(branch).href(); return branchLinkBuilder.method("getRepositoryResource").parameters(namespaceAndName.getNamespace(), namespaceAndName.getName()).method("branches").parameters().method("history").parameters(branch).href();
} }
public String changesetDiff(NamespaceAndName namespaceAndName, String branch) {
return branchLinkBuilder.method("getRepositoryResource").parameters(namespaceAndName.getNamespace(), namespaceAndName.getName()).method("branches").parameters().method("changesetDiff").parameters(branch, "").href() + "{otherBranch}";
}
} }
public BranchCollectionLinks branchCollection() { public BranchCollectionLinks branchCollection() {