Append self links to parsed diff results

This commit is contained in:
Rene Pfeuffer
2020-01-24 16:31:31 +01:00
parent 9fcaf5e69d
commit 02a9dafee4
8 changed files with 171 additions and 51 deletions

View File

@@ -3,6 +3,7 @@ package sonia.scm.api.v2.resources;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import de.otto.edison.hal.HalRepresentation; import de.otto.edison.hal.HalRepresentation;
import de.otto.edison.hal.Links;
import lombok.Data; import lombok.Data;
import java.util.List; import java.util.List;
@@ -10,6 +11,10 @@ import java.util.List;
@Data @Data
public class DiffResultDto extends HalRepresentation { public class DiffResultDto extends HalRepresentation {
public DiffResultDto(Links links) {
super(links);
}
private List<FileDto> files; private List<FileDto> files;
@Data @Data

View File

@@ -3,6 +3,8 @@ package sonia.scm.api.v2.resources;
import com.github.sdorra.spotter.ContentTypes; import com.github.sdorra.spotter.ContentTypes;
import com.github.sdorra.spotter.Language; import com.github.sdorra.spotter.Language;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.inject.Inject;
import sonia.scm.repository.Repository;
import sonia.scm.repository.api.DiffFile; import sonia.scm.repository.api.DiffFile;
import sonia.scm.repository.api.DiffLine; import sonia.scm.repository.api.DiffLine;
import sonia.scm.repository.api.DiffResult; import sonia.scm.repository.api.DiffResult;
@@ -13,24 +15,38 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt; import java.util.OptionalInt;
import static de.otto.edison.hal.Links.linkingTo;
/** /**
* TODO conflicts, copy and rename * TODO conflicts, copy and rename
*/ */
final class DiffResultToDiffResultDtoMapper { class DiffResultToDiffResultDtoMapper {
static final DiffResultToDiffResultDtoMapper INSTANCE = new DiffResultToDiffResultDtoMapper(); private final ResourceLinks resourceLinks;
private DiffResultToDiffResultDtoMapper() { @Inject
DiffResultToDiffResultDtoMapper(ResourceLinks resourceLinks) {
this.resourceLinks = resourceLinks;
} }
public DiffResultDto map(DiffResult result) { public DiffResultDto mapForIncoming(Repository repository, DiffResult result, String source, String target) {
DiffResultDto dto = new DiffResultDto(linkingTo().self(resourceLinks.incoming().diffParsed(repository.getNamespace(), repository.getName(), source, target)).build());
setFiles(result, dto);
return dto;
}
public DiffResultDto mapForRevision(Repository repository, DiffResult result, String revision) {
DiffResultDto dto = new DiffResultDto(linkingTo().self(resourceLinks.diff().parsed(repository.getNamespace(), repository.getName(), revision)).build());
setFiles(result, dto);
return dto;
}
private void setFiles(DiffResult result, DiffResultDto dto) {
List<DiffResultDto.FileDto> files = new ArrayList<>(); List<DiffResultDto.FileDto> files = new ArrayList<>();
for (DiffFile file : result) { for (DiffFile file : result) {
files.add(mapFile(file)); files.add(mapFile(file));
} }
DiffResultDto dto = new DiffResultDto();
dto.setFiles(files); dto.setFiles(files);
return dto;
} }
private DiffResultDto.FileDto mapFile(DiffFile file) { private DiffResultDto.FileDto mapFile(DiffFile file) {

View File

@@ -31,10 +31,12 @@ public class DiffRootResource {
static final String DIFF_FORMAT_VALUES_REGEX = "NATIVE|GIT|UNIFIED"; static final String DIFF_FORMAT_VALUES_REGEX = "NATIVE|GIT|UNIFIED";
private final RepositoryServiceFactory serviceFactory; private final RepositoryServiceFactory serviceFactory;
private final DiffResultToDiffResultDtoMapper parsedDiffMapper;
@Inject @Inject
public DiffRootResource(RepositoryServiceFactory serviceFactory) { public DiffRootResource(RepositoryServiceFactory serviceFactory, DiffResultToDiffResultDtoMapper parsedDiffMapper) {
this.serviceFactory = serviceFactory; this.serviceFactory = serviceFactory;
this.parsedDiffMapper = parsedDiffMapper;
} }
@@ -83,11 +85,11 @@ public class DiffRootResource {
@ResponseCode(code = 404, condition = "not found, no revision with the specified param for the repository available or repository not found"), @ResponseCode(code = 404, condition = "not found, no revision with the specified param for the repository available or repository not found"),
@ResponseCode(code = 500, condition = "internal server error") @ResponseCode(code = 500, condition = "internal server error")
}) })
public Response getParsed(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision) throws IOException { public DiffResultDto getParsed(@PathParam("namespace") String namespace, @PathParam("name") String name, @PathParam("revision") String revision) throws IOException {
HttpUtil.checkForCRLFInjection(revision); HttpUtil.checkForCRLFInjection(revision);
try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) { try (RepositoryService repositoryService = serviceFactory.create(new NamespaceAndName(namespace, name))) {
DiffResult diffResult = repositoryService.getDiffResultCommand().setRevision(revision).getDiffResult(); DiffResult diffResult = repositoryService.getDiffResultCommand().setRevision(revision).getDiffResult();
return Response.ok(DiffResultToDiffResultDtoMapper.INSTANCE.map(diffResult)).build(); return parsedDiffMapper.mapForRevision(repositoryService.getRepository(), diffResult, revision);
} }
} }
} }

View File

@@ -34,16 +34,16 @@ import static sonia.scm.api.v2.resources.DiffRootResource.HEADER_CONTENT_DISPOSI
public class IncomingRootResource { public class IncomingRootResource {
private final RepositoryServiceFactory serviceFactory; private final RepositoryServiceFactory serviceFactory;
private final IncomingChangesetCollectionToDtoMapper mapper; private final IncomingChangesetCollectionToDtoMapper changesetMapper;
private final DiffResultToDiffResultDtoMapper parsedDiffMapper;
@Inject @Inject
public IncomingRootResource(RepositoryServiceFactory serviceFactory, IncomingChangesetCollectionToDtoMapper incomingChangesetCollectionToDtoMapper) { public IncomingRootResource(RepositoryServiceFactory serviceFactory, IncomingChangesetCollectionToDtoMapper incomingChangesetCollectionToDtoMapper, DiffResultToDiffResultDtoMapper parsedDiffMapper) {
this.serviceFactory = serviceFactory; this.serviceFactory = serviceFactory;
this.mapper = incomingChangesetCollectionToDtoMapper; this.changesetMapper = incomingChangesetCollectionToDtoMapper;
this.parsedDiffMapper = parsedDiffMapper;
} }
/** /**
@@ -110,7 +110,7 @@ public class IncomingRootResource {
.getChangesets(); .getChangesets();
if (changesets != null && changesets.getChangesets() != null) { if (changesets != null && changesets.getChangesets() != null) {
PageResult<Changeset> pageResult = new PageResult<>(changesets.getChangesets(), changesets.getTotal()); PageResult<Changeset> pageResult = new PageResult<>(changesets.getChangesets(), changesets.getTotal());
return Response.ok(mapper.map(page, pageSize, pageResult, repository, source, target)).build(); return Response.ok(changesetMapper.map(page, pageSize, pageResult, repository, source, target)).build();
} else { } else {
return Response.ok().build(); return Response.ok().build();
} }
@@ -160,7 +160,7 @@ public class IncomingRootResource {
@ResponseCode(code = 400, condition = "Bad Request"), @ResponseCode(code = 400, condition = "Bad Request"),
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"), @ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
@ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the diff"), @ResponseCode(code = 403, condition = "not authorized, the current user has no privileges to read the diff"),
@ResponseCode(code = 404, condition = "not found, no revision with the specified param for the repository available or repository not found"), @ResponseCode(code = 404, condition = "not found, source or target branch for the repository not available or repository not found"),
@ResponseCode(code = 500, condition = "internal server error") @ResponseCode(code = 500, condition = "internal server error")
}) })
public Response incomingDiffParsed(@PathParam("namespace") String namespace, public Response incomingDiffParsed(@PathParam("namespace") String namespace,
@@ -174,7 +174,7 @@ public class IncomingRootResource {
.setRevision(source) .setRevision(source)
.setAncestorChangeset(target) .setAncestorChangeset(target)
.getDiffResult(); .getDiffResult();
return Response.ok(DiffResultToDiffResultDtoMapper.INSTANCE.map(diffResult)).build(); return Response.ok(parsedDiffMapper.mapForIncoming(repositoryService.getRepository(), diffResult, source, target)).build();
} }
} }
} }

View File

@@ -419,7 +419,18 @@ class ResourceLinks {
} }
public String diffParsed(String namespace, String name) { public String diffParsed(String namespace, String name) {
return toTemplateParams(incomingLinkBuilder.method("getRepositoryResource").parameters(namespace, name).method("incoming").parameters().method("incomingDiffParsed").parameters("source", "target").href()); return toTemplateParams(diffParsed(namespace, name, "source", "target"));
}
public String diffParsed(String namespace, String name, String source, String target) {
return incomingLinkBuilder
.method("getRepositoryResource")
.parameters(namespace, name)
.method("incoming")
.parameters()
.method("incomingDiffParsed")
.parameters(source, target)
.href();
} }
public String toTemplateParams(String href) { public String toTemplateParams(String href) {

View File

@@ -2,6 +2,7 @@ package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers; import com.google.inject.util.Providers;
import de.otto.edison.hal.Links;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.subject.support.SubjectThreadState;
@@ -13,6 +14,7 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoJUnitRunner;
import sonia.scm.NotFoundException; import sonia.scm.NotFoundException;
@@ -20,6 +22,8 @@ import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.DiffCommandBuilder;
import sonia.scm.repository.api.DiffFormat; import sonia.scm.repository.api.DiffFormat;
import sonia.scm.repository.api.DiffResult;
import sonia.scm.repository.api.DiffResultCommandBuilder;
import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.util.CRLFInjectionException; import sonia.scm.util.CRLFInjectionException;
@@ -34,7 +38,6 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -45,6 +48,7 @@ public class DiffResourceTest extends RepositoryTestBase {
public static final String DIFF_PATH = "space/repo/diff/"; public static final String DIFF_PATH = "space/repo/diff/";
public static final String DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + DIFF_PATH; public static final String DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + DIFF_PATH;
public static final Repository REPOSITORY = new Repository("repoId", "git", "space", "repo");
private RestDispatcher dispatcher = new RestDispatcher(); private RestDispatcher dispatcher = new RestDispatcher();
@@ -54,8 +58,13 @@ public class DiffResourceTest extends RepositoryTestBase {
@Mock @Mock
private RepositoryService service; private RepositoryService service;
@Mock @Mock(answer = Answers.RETURNS_SELF)
private DiffCommandBuilder diffCommandBuilder; private DiffCommandBuilder diffCommandBuilder;
@Mock(answer = Answers.RETURNS_SELF)
private DiffResultCommandBuilder diffResultCommandBuilder;
@Mock
private DiffResultToDiffResultDtoMapper diffResultToDiffResultDtoMapper;
private DiffRootResource diffRootResource; private DiffRootResource diffRootResource;
@@ -66,15 +75,16 @@ public class DiffResourceTest extends RepositoryTestBase {
@Before @Before
public void prepareEnvironment() { public void prepareEnvironment() {
diffRootResource = new DiffRootResource(serviceFactory); diffRootResource = new DiffRootResource(serviceFactory, diffResultToDiffResultDtoMapper);
super.diffRootResource = Providers.of(diffRootResource); super.diffRootResource = Providers.of(diffRootResource);
dispatcher.addSingletonResource(getRepositoryRootResource()); dispatcher.addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(service);
when(serviceFactory.create(any(Repository.class))).thenReturn(service); when(serviceFactory.create(any(Repository.class))).thenReturn(service);
when(service.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); when(service.getRepository()).thenReturn(REPOSITORY);
ExceptionWithContextToErrorDtoMapperImpl mapper = new ExceptionWithContextToErrorDtoMapperImpl(); ExceptionWithContextToErrorDtoMapperImpl mapper = new ExceptionWithContextToErrorDtoMapperImpl();
dispatcher.registerException(CRLFInjectionException.class, Response.Status.BAD_REQUEST); dispatcher.registerException(CRLFInjectionException.class, Response.Status.BAD_REQUEST);
when(service.getDiffCommand()).thenReturn(diffCommandBuilder); when(service.getDiffCommand()).thenReturn(diffCommandBuilder);
when(service.getDiffResultCommand()).thenReturn(diffResultCommandBuilder);
subjectThreadState.bind(); subjectThreadState.bind();
ThreadContext.bind(subject); ThreadContext.bind(subject);
when(subject.isPermitted(any(String.class))).thenReturn(true); when(subject.isPermitted(any(String.class))).thenReturn(true);
@@ -87,8 +97,6 @@ public class DiffResourceTest extends RepositoryTestBase {
@Test @Test
public void shouldGetDiffs() throws Exception { public void shouldGetDiffs() throws Exception {
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {}); when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {});
MockHttpRequest request = MockHttpRequest MockHttpRequest request = MockHttpRequest
.get(DIFF_URL + "revision") .get(DIFF_URL + "revision")
@@ -106,6 +114,25 @@ public class DiffResourceTest extends RepositoryTestBase {
.contains(expectedValue); .contains(expectedValue);
} }
@Test
public void shouldGetParsedDiffs() throws Exception {
DiffResult diffResult = mock(DiffResult.class);
when(diffResultCommandBuilder.getDiffResult()).thenReturn(diffResult);
when(diffResultToDiffResultDtoMapper.mapForRevision(REPOSITORY, diffResult, "revision"))
.thenReturn(new DiffResultDto(Links.linkingTo().self("http://self").build()));
MockHttpRequest request = MockHttpRequest
.get(DIFF_URL + "revision/parsed")
.accept(VndMediaType.DIFF_PARSED);
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertThat(response.getStatus())
.isEqualTo(200);
assertThat(response.getContentAsString())
.contains("\"self\":{\"href\":\"http://self\"}");
}
@Test @Test
public void shouldGet404OnMissingRepository() throws URISyntaxException { public void shouldGet404OnMissingRepository() throws URISyntaxException {
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(new NotFoundException("Text", "x")); when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(new NotFoundException("Text", "x"));
@@ -119,8 +146,6 @@ public class DiffResourceTest extends RepositoryTestBase {
@Test @Test
public void shouldGet404OnMissingRevision() throws Exception { public void shouldGet404OnMissingRevision() throws Exception {
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x")); when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x"));
MockHttpRequest request = MockHttpRequest MockHttpRequest request = MockHttpRequest
@@ -135,8 +160,6 @@ public class DiffResourceTest extends RepositoryTestBase {
@Test @Test
public void shouldGet400OnCrlfInjection() throws Exception { public void shouldGet400OnCrlfInjection() throws Exception {
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x")); when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Text", "x"));
MockHttpRequest request = MockHttpRequest MockHttpRequest request = MockHttpRequest
@@ -149,8 +172,6 @@ public class DiffResourceTest extends RepositoryTestBase {
@Test @Test
public void shouldGet400OnUnknownFormat() throws Exception { public void shouldGet400OnUnknownFormat() throws Exception {
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Test", "test")); when(diffCommandBuilder.retrieveContent()).thenThrow(new NotFoundException("Test", "test"));
MockHttpRequest request = MockHttpRequest MockHttpRequest request = MockHttpRequest
@@ -163,8 +184,6 @@ public class DiffResourceTest extends RepositoryTestBase {
@Test @Test
public void shouldAcceptDiffFormats() throws Exception { public void shouldAcceptDiffFormats() throws Exception {
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {}); when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {});
Arrays.stream(DiffFormat.values()).map(DiffFormat::name).forEach( Arrays.stream(DiffFormat.values()).map(DiffFormat::name).forEach(

View File

@@ -1,8 +1,10 @@
package sonia.scm.api.v2.resources; package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Link;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension; import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.repository.Repository;
import sonia.scm.repository.api.DiffFile; import sonia.scm.repository.api.DiffFile;
import sonia.scm.repository.api.DiffLine; import sonia.scm.repository.api.DiffLine;
import sonia.scm.repository.api.DiffResult; import sonia.scm.repository.api.DiffResult;
@@ -10,8 +12,10 @@ import sonia.scm.repository.api.Hunk;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.OptionalInt; import java.util.OptionalInt;
import static java.net.URI.create;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -19,21 +23,14 @@ import static org.mockito.Mockito.when;
@ExtendWith(MockitoExtension.class) @ExtendWith(MockitoExtension.class)
class DiffResultToDiffResultDtoMapperTest { class DiffResultToDiffResultDtoMapperTest {
private static final Repository REPOSITORY = new Repository("1", "git", "space", "X");
ResourceLinks resourceLinks = ResourceLinksMock.createMock(create("/scm/api/v2"));
DiffResultToDiffResultDtoMapper mapper = new DiffResultToDiffResultDtoMapper(resourceLinks);
@Test @Test
void shouldMapDiffResult() { void shouldMapDiffResult() {
DiffResult result = result( DiffResultDto dto = mapper.mapForRevision(REPOSITORY, createResult(), "123");
addedFile("A.java", "abc"),
modifiedFile("B.ts", "def", "abc",
hunk("@@ -3,4 1,2 @@", 1, 2, 3, 4,
insertedLine("a", 1),
modifiedLine("b", 2),
deletedLine("c", 3)
)
),
deletedFile("C.go", "ghi")
);
DiffResultDto dto = DiffResultToDiffResultDtoMapper.INSTANCE.map(result);
List<DiffResultDto.FileDto> files = dto.getFiles(); List<DiffResultDto.FileDto> files = dto.getFiles();
assertAddedFile(files.get(0), "A.java", "abc", "java"); assertAddedFile(files.get(0), "A.java", "abc", "java");
@@ -49,6 +46,44 @@ class DiffResultToDiffResultDtoMapperTest {
assertDeletedLine(changes.get(2), "c", 3); assertDeletedLine(changes.get(2), "c", 3);
} }
@Test
void shouldCreateSelfLinkForRevision() {
DiffResultDto dto = mapper.mapForRevision(REPOSITORY, createResult(), "123");
Optional<Link> selfLink = dto.getLinks().getLinkBy("self");
assertThat(selfLink)
.isPresent()
.get()
.extracting("href")
.contains("/scm/api/v2/repositories/space/X/diff/123/parsed");
}
@Test
void shouldCreateSelfLinkForIncoming() {
DiffResultDto dto = mapper.mapForIncoming(REPOSITORY, createResult(), "feature/some", "master");
Optional<Link> selfLink = dto.getLinks().getLinkBy("self");
assertThat(selfLink)
.isPresent()
.get()
.extracting("href")
.contains("/scm/api/v2/repositories/space/X/incoming/feature%2Fsome/master/diff/parsed");
}
private DiffResult createResult() {
return result(
addedFile("A.java", "abc"),
modifiedFile("B.ts", "def", "abc",
hunk("@@ -3,4 1,2 @@", 1, 2, 3, 4,
insertedLine("a", 1),
modifiedLine("b", 2),
deletedLine("c", 3)
)
),
deletedFile("C.go", "ghi")
);
}
public void assertInsertedLine(DiffResultDto.ChangeDto change, String content, int lineNumber) { public void assertInsertedLine(DiffResultDto.ChangeDto change, String content, int lineNumber) {
assertThat(change.getContent()).isEqualTo(content); assertThat(change.getContent()).isEqualTo(content);
assertThat(change.getLineNumber()).isEqualTo(lineNumber); assertThat(change.getLineNumber()).isEqualTo(lineNumber);

View File

@@ -2,6 +2,7 @@ package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers; import com.google.inject.util.Providers;
import de.otto.edison.hal.Links;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState; import org.apache.shiro.subject.support.SubjectThreadState;
@@ -24,6 +25,8 @@ import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Person; import sonia.scm.repository.Person;
import sonia.scm.repository.Repository; import sonia.scm.repository.Repository;
import sonia.scm.repository.api.DiffCommandBuilder; import sonia.scm.repository.api.DiffCommandBuilder;
import sonia.scm.repository.api.DiffResult;
import sonia.scm.repository.api.DiffResultCommandBuilder;
import sonia.scm.repository.api.LogCommandBuilder; import sonia.scm.repository.api.LogCommandBuilder;
import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.api.RepositoryServiceFactory;
@@ -45,6 +48,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static sonia.scm.repository.api.DiffFormat.NATIVE;
@RunWith(MockitoJUnitRunner.Silent.class) @RunWith(MockitoJUnitRunner.Silent.class)
@Slf4j @Slf4j
@@ -54,6 +58,7 @@ public class IncomingRootResourceTest extends RepositoryTestBase {
public static final String INCOMING_PATH = "space/repo/incoming/"; public static final String INCOMING_PATH = "space/repo/incoming/";
public static final String INCOMING_CHANGESETS_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH; public static final String INCOMING_CHANGESETS_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH;
public static final String INCOMING_DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH; public static final String INCOMING_DIFF_URL = "/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + INCOMING_PATH;
public static final Repository REPOSITORY = new Repository("repoId", "git", "space", "repo");
private RestDispatcher dispatcher = new RestDispatcher(); private RestDispatcher dispatcher = new RestDispatcher();
@@ -71,7 +76,11 @@ public class IncomingRootResourceTest extends RepositoryTestBase {
@Mock @Mock
private DiffCommandBuilder diffCommandBuilder; private DiffCommandBuilder diffCommandBuilder;
@Mock
private DiffResultCommandBuilder diffResultCommandBuilder;
@Mock
private DiffResultToDiffResultDtoMapper diffResultToDiffResultDtoMapper;
private IncomingChangesetCollectionToDtoMapper incomingChangesetCollectionToDtoMapper; private IncomingChangesetCollectionToDtoMapper incomingChangesetCollectionToDtoMapper;
@@ -88,14 +97,15 @@ public class IncomingRootResourceTest extends RepositoryTestBase {
@Before @Before
public void prepareEnvironment() { public void prepareEnvironment() {
incomingChangesetCollectionToDtoMapper = new IncomingChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks); incomingChangesetCollectionToDtoMapper = new IncomingChangesetCollectionToDtoMapper(changesetToChangesetDtoMapper, resourceLinks);
incomingRootResource = new IncomingRootResource(serviceFactory, incomingChangesetCollectionToDtoMapper); incomingRootResource = new IncomingRootResource(serviceFactory, incomingChangesetCollectionToDtoMapper, diffResultToDiffResultDtoMapper);
super.incomingRootResource = Providers.of(incomingRootResource); super.incomingRootResource = Providers.of(incomingRootResource);
dispatcher.addSingletonResource(getRepositoryRootResource()); dispatcher.addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService); when(serviceFactory.create(new NamespaceAndName("space", "repo"))).thenReturn(repositoryService);
when(serviceFactory.create(any(Repository.class))).thenReturn(repositoryService); when(serviceFactory.create(REPOSITORY)).thenReturn(repositoryService);
when(repositoryService.getRepository()).thenReturn(new Repository("repoId", "git", "space", "repo")); when(repositoryService.getRepository()).thenReturn(REPOSITORY);
when(repositoryService.getLogCommand()).thenReturn(logCommandBuilder); when(repositoryService.getLogCommand()).thenReturn(logCommandBuilder);
when(repositoryService.getDiffCommand()).thenReturn(diffCommandBuilder); when(repositoryService.getDiffCommand()).thenReturn(diffCommandBuilder);
when(repositoryService.getDiffResultCommand()).thenReturn(diffResultCommandBuilder);
dispatcher.registerException(CRLFInjectionException.class, Response.Status.BAD_REQUEST); dispatcher.registerException(CRLFInjectionException.class, Response.Status.BAD_REQUEST);
subjectThreadState.bind(); subjectThreadState.bind();
ThreadContext.bind(subject); ThreadContext.bind(subject);
@@ -170,9 +180,9 @@ public class IncomingRootResourceTest extends RepositoryTestBase {
@Test @Test
public void shouldGetDiffs() throws Exception { public void shouldGetDiffs() throws Exception {
when(diffCommandBuilder.setRevision(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setRevision("src_changeset_id")).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.setAncestorChangeset(anyString())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setAncestorChangeset("target_changeset_id")).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.setFormat(any())).thenReturn(diffCommandBuilder); when(diffCommandBuilder.setFormat(NATIVE)).thenReturn(diffCommandBuilder);
when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {}); when(diffCommandBuilder.retrieveContent()).thenReturn(output -> {});
MockHttpRequest request = MockHttpRequest MockHttpRequest request = MockHttpRequest
.get(INCOMING_DIFF_URL + "src_changeset_id/target_changeset_id/diff") .get(INCOMING_DIFF_URL + "src_changeset_id/target_changeset_id/diff")
@@ -190,6 +200,28 @@ public class IncomingRootResourceTest extends RepositoryTestBase {
.contains(expectedValue); .contains(expectedValue);
} }
@Test
public void shouldGetParsedDiffs() throws Exception {
when(diffResultCommandBuilder.setRevision("src_changeset_id")).thenReturn(diffResultCommandBuilder);
when(diffResultCommandBuilder.setAncestorChangeset("target_changeset_id")).thenReturn(diffResultCommandBuilder);
DiffResult diffResult = mock(DiffResult.class);
when(diffResultCommandBuilder.getDiffResult()).thenReturn(diffResult);
when(diffResultToDiffResultDtoMapper.mapForIncoming(REPOSITORY, diffResult, "src_changeset_id", "target_changeset_id"))
.thenReturn(new DiffResultDto(Links.linkingTo().self("http://self").build()));
MockHttpRequest request = MockHttpRequest
.get(INCOMING_DIFF_URL + "src_changeset_id/target_changeset_id/diff/parsed")
.accept(VndMediaType.DIFF_PARSED);
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertThat(response.getStatus())
.isEqualTo(200);
assertThat(response.getContentAsString())
.contains("\"self\":{\"href\":\"http://self\"}");
}
@Test @Test
public void shouldGet404OnMissingRepository() throws URISyntaxException { public void shouldGet404OnMissingRepository() throws URISyntaxException {
when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(new NotFoundException("Text", "x")); when(serviceFactory.create(any(NamespaceAndName.class))).thenThrow(new NotFoundException("Text", "x"));