Add endpoint to set default branch

This commit is contained in:
René Pfeuffer
2018-12-12 15:04:56 +01:00
parent bc8c776821
commit b4081aaa99
5 changed files with 73 additions and 18 deletions

View File

@@ -17,15 +17,16 @@ import static de.otto.edison.hal.Links.linkingTo;
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection. // Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
@SuppressWarnings("squid:S3306") @SuppressWarnings("squid:S3306")
@Mapper @Mapper
public abstract class GitRepositoryConfigToGitRepositoryConfigDtoMapper { public abstract class GitRepositoryConfigMapper {
@Inject @Inject
private ScmPathInfoStore scmPathInfoStore; private ScmPathInfoStore scmPathInfoStore;
public abstract GitRepositoryConfigDto map(GitRepositoryConfig config, @Context Repository repository); public abstract GitRepositoryConfigDto map(GitRepositoryConfig config, @Context Repository repository);
public abstract GitRepositoryConfig map(GitRepositoryConfigDto dto);
@AfterMapping @AfterMapping
void appendLinks(GitRepositoryConfig config, @MappingTarget GitRepositoryConfigDto target, @Context Repository repository) { void appendLinks(@MappingTarget GitRepositoryConfigDto target, @Context Repository repository) {
Links.Builder linksBuilder = linkingTo().self(self()); Links.Builder linksBuilder = linkingTo().self(self());
if (RepositoryPermissions.modify(repository).isPermitted()) { if (RepositoryPermissions.modify(repository).isPermitted()) {
linksBuilder.single(link("update", update())); linksBuilder.single(link("update", update()));

View File

@@ -9,7 +9,9 @@ import sonia.scm.store.ConfigurationStoreFactory;
import sonia.scm.web.GitVndMediaType; import sonia.scm.web.GitVndMediaType;
import javax.inject.Inject; import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
@@ -20,13 +22,13 @@ import static sonia.scm.NotFoundException.notFound;
public class GitRepositoryConfigResource { public class GitRepositoryConfigResource {
private final GitRepositoryConfigToGitRepositoryConfigDtoMapper repositoryConfigToDtoMapper; private final GitRepositoryConfigMapper repositoryConfigMapper;
private final RepositoryManager repositoryManager; private final RepositoryManager repositoryManager;
private final ConfigurationStoreFactory configurationStoreFactory; private final ConfigurationStoreFactory configurationStoreFactory;
@Inject @Inject
public GitRepositoryConfigResource(GitRepositoryConfigToGitRepositoryConfigDtoMapper repositoryConfigToDtoMapper, RepositoryManager repositoryManager, ConfigurationStoreFactory configurationStoreFactory) { public GitRepositoryConfigResource(GitRepositoryConfigMapper repositoryConfigMapper, RepositoryManager repositoryManager, ConfigurationStoreFactory configurationStoreFactory) {
this.repositoryConfigToDtoMapper = repositoryConfigToDtoMapper; this.repositoryConfigMapper = repositoryConfigMapper;
this.repositoryManager = repositoryManager; this.repositoryManager = repositoryManager;
this.configurationStoreFactory = configurationStoreFactory; this.configurationStoreFactory = configurationStoreFactory;
} }
@@ -35,18 +37,37 @@ public class GitRepositoryConfigResource {
@Path("/") @Path("/")
@Produces(GitVndMediaType.GIT_REPOSITORY_CONFIG) @Produces(GitVndMediaType.GIT_REPOSITORY_CONFIG)
public Response getRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name) { public Response getRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name) {
Repository repository = getRepository(namespace, name);
ConfigurationStore<GitRepositoryConfig> repositoryConfigStore = getStore(repository);
GitRepositoryConfig config = repositoryConfigStore.get();
if (config == null) {
config = new GitRepositoryConfig();
}
GitRepositoryConfigDto dto = repositoryConfigMapper.map(config, repository);
return Response.ok(dto).build();
}
@PUT
@Path("/")
@Consumes(GitVndMediaType.GIT_REPOSITORY_CONFIG)
public Response setRepositoryConfig(@PathParam("namespace") String namespace, @PathParam("name") String name, GitRepositoryConfigDto dto) {
Repository repository = getRepository(namespace, name);
ConfigurationStore<GitRepositoryConfig> repositoryConfigStore = getStore(repository);
GitRepositoryConfig config = repositoryConfigMapper.map(dto);
repositoryConfigStore.set(config);
return Response.noContent().build();
}
private Repository getRepository(@PathParam("namespace") String namespace, @PathParam("name") String name) {
NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name); NamespaceAndName namespaceAndName = new NamespaceAndName(namespace, name);
Repository repository = repositoryManager.get(namespaceAndName); Repository repository = repositoryManager.get(namespaceAndName);
if (repository == null) { if (repository == null) {
throw notFound(entity(namespaceAndName)); throw notFound(entity(namespaceAndName));
} }
return repository;
}
ConfigurationStore<GitRepositoryConfig> repositoryConfigStore = configurationStoreFactory.withType(GitRepositoryConfig.class).withName("gitConfig").forRepository(repository).build(); private ConfigurationStore<GitRepositoryConfig> getStore(Repository repository) {
GitRepositoryConfig config = repositoryConfigStore.get(); return configurationStoreFactory.withType(GitRepositoryConfig.class).withName("gitConfig").forRepository(repository).build();
if (config == null) {
config = new GitRepositoryConfig();
}
GitRepositoryConfigDto dto = repositoryConfigToDtoMapper.map(config, repository);
return Response.ok(dto).build();
} }
} }

View File

@@ -1,5 +1,11 @@
package sonia.scm.repository; package sonia.scm.repository;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "config")
@XmlAccessorType(XmlAccessType.FIELD)
public class GitRepositoryConfig { public class GitRepositoryConfig {
private String defaultBranch; private String defaultBranch;

View File

@@ -40,7 +40,7 @@ import org.eclipse.jgit.transport.ScmTransportProtocol;
import org.mapstruct.factory.Mappers; import org.mapstruct.factory.Mappers;
import sonia.scm.api.v2.resources.GitConfigDtoToGitConfigMapper; import sonia.scm.api.v2.resources.GitConfigDtoToGitConfigMapper;
import sonia.scm.api.v2.resources.GitConfigToGitConfigDtoMapper; import sonia.scm.api.v2.resources.GitConfigToGitConfigDtoMapper;
import sonia.scm.api.v2.resources.GitRepositoryConfigToGitRepositoryConfigDtoMapper; import sonia.scm.api.v2.resources.GitRepositoryConfigMapper;
import sonia.scm.plugin.Extension; import sonia.scm.plugin.Extension;
import sonia.scm.repository.GitWorkdirFactory; import sonia.scm.repository.GitWorkdirFactory;
import sonia.scm.repository.spi.SimpleGitWorkdirFactory; import sonia.scm.repository.spi.SimpleGitWorkdirFactory;
@@ -66,7 +66,7 @@ public class GitServletModule extends ServletModule
bind(GitConfigDtoToGitConfigMapper.class).to(Mappers.getMapper(GitConfigDtoToGitConfigMapper.class).getClass()); bind(GitConfigDtoToGitConfigMapper.class).to(Mappers.getMapper(GitConfigDtoToGitConfigMapper.class).getClass());
bind(GitConfigToGitConfigDtoMapper.class).to(Mappers.getMapper(GitConfigToGitConfigDtoMapper.class).getClass()); bind(GitConfigToGitConfigDtoMapper.class).to(Mappers.getMapper(GitConfigToGitConfigDtoMapper.class).getClass());
bind(GitRepositoryConfigToGitRepositoryConfigDtoMapper.class).to(Mappers.getMapper(GitRepositoryConfigToGitRepositoryConfigDtoMapper.class).getClass()); bind(GitRepositoryConfigMapper.class).to(Mappers.getMapper(GitRepositoryConfigMapper.class).getClass());
bind(GitWorkdirFactory.class).to(SimpleGitWorkdirFactory.class); bind(GitWorkdirFactory.class).to(SimpleGitWorkdirFactory.class);
} }

View File

@@ -12,8 +12,11 @@ import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Answers; import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks; import org.mockito.InjectMocks;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.Spy;
import org.mockito.runners.MockitoJUnitRunner; import org.mockito.runners.MockitoJUnitRunner;
import sonia.scm.repository.GitConfig; import sonia.scm.repository.GitConfig;
import sonia.scm.repository.GitRepositoryConfig; import sonia.scm.repository.GitRepositoryConfig;
@@ -35,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@SubjectAware( @SubjectAware(
@@ -66,21 +70,23 @@ public class GitConfigResourceTest {
@InjectMocks @InjectMocks
private GitConfigToGitConfigDtoMapperImpl configToDtoMapper; private GitConfigToGitConfigDtoMapperImpl configToDtoMapper;
@InjectMocks @InjectMocks
private GitRepositoryConfigToGitRepositoryConfigDtoMapperImpl repositoryConfigToDtoMapper; private GitRepositoryConfigMapperImpl repositoryConfigMapper;
@Mock @Mock
private GitRepositoryHandler repositoryHandler; private GitRepositoryHandler repositoryHandler;
@Mock(answer = Answers.CALLS_REAL_METHODS) @Mock(answer = Answers.CALLS_REAL_METHODS)
private ConfigurationStoreFactory configurationStoreFactory; private ConfigurationStoreFactory configurationStoreFactory;
@Mock @Spy
private ConfigurationStore configurationStore; private ConfigurationStore<Object> configurationStore;
@Captor
private ArgumentCaptor<Object> configurationStoreCaptor;
@Before @Before
public void prepareEnvironment() { public void prepareEnvironment() {
GitConfig gitConfig = createConfiguration(); GitConfig gitConfig = createConfiguration();
when(repositoryHandler.getConfig()).thenReturn(gitConfig); when(repositoryHandler.getConfig()).thenReturn(gitConfig);
GitRepositoryConfigResource gitRepositoryConfigResource = new GitRepositoryConfigResource(repositoryConfigToDtoMapper, repositoryManager, configurationStoreFactory); GitRepositoryConfigResource gitRepositoryConfigResource = new GitRepositoryConfigResource(repositoryConfigMapper, repositoryManager, configurationStoreFactory);
GitConfigResource gitConfigResource = new GitConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, of(gitRepositoryConfigResource)); GitConfigResource gitConfigResource = new GitConfigResource(dtoToConfigMapper, configToDtoMapper, repositoryHandler, of(gitRepositoryConfigResource));
dispatcher.getRegistry().addSingletonResource(gitConfigResource); dispatcher.getRegistry().addSingletonResource(gitConfigResource);
when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri); when(scmPathInfoStore.get().getApiRestUri()).thenReturn(baseUri);
@@ -89,6 +95,7 @@ public class GitConfigResourceTest {
@Before @Before
public void initConfigStore() { public void initConfigStore() {
when(configurationStoreFactory.getStore(any())).thenReturn(configurationStore); when(configurationStoreFactory.getStore(any())).thenReturn(configurationStore);
doNothing().when(configurationStore).set(configurationStoreCaptor.capture());
} }
@Test @Test
@@ -202,6 +209,26 @@ public class GitConfigResourceTest {
.contains("\"defaultBranch\":\"test\""); .contains("\"defaultBranch\":\"test\"");
} }
@Test
@SubjectAware(username = "writeOnly")
public void shouldStoreChangedRepositoryConfig() throws URISyntaxException {
when(repositoryManager.get(new NamespaceAndName("space", "X"))).thenReturn(new Repository("id", "git", "space", "X"));
MockHttpRequest request = MockHttpRequest
.put("/" + GitConfigResource.GIT_CONFIG_PATH_V2 + "/space/X")
.contentType(GitVndMediaType.GIT_REPOSITORY_CONFIG)
.content("{\"defaultBranch\": \"new\"}".getBytes());
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(HttpServletResponse.SC_NO_CONTENT, response.getStatus());
assertThat(configurationStoreCaptor.getValue())
.isInstanceOfSatisfying(GitRepositoryConfig.class, x -> { })
.extracting("defaultBranch")
.containsExactly("new");
}
private MockHttpResponse get() throws URISyntaxException { private MockHttpResponse get() throws URISyntaxException {
MockHttpRequest request = MockHttpRequest.get("/" + GitConfigResource.GIT_CONFIG_PATH_V2); MockHttpRequest request = MockHttpRequest.get("/" + GitConfigResource.GIT_CONFIG_PATH_V2);
MockHttpResponse response = new MockHttpResponse(); MockHttpResponse response = new MockHttpResponse();