Merge pull request #1324 from scm-manager/feature/template_plugin

Feature/template plugin
This commit is contained in:
Sebastian Sdorra
2020-09-10 10:00:06 +02:00
committed by GitHub
17 changed files with 317 additions and 41 deletions

View File

@@ -0,0 +1,81 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import sonia.scm.ContextEntry;
import sonia.scm.ExceptionWithContext;
import java.util.Optional;
import static org.assertj.core.api.Assertions.assertThat;
class ExceptionWithContextToErrorDtoMapperTest {
private final ExceptionWithContextToErrorDtoMapper mapper = Mappers.getMapper(ExceptionWithContextToErrorDtoMapper.class);
@Test
void shouldMapUrl() {
ExceptionWithUrl exception = new ExceptionWithUrl();
ErrorDto dto = mapper.map(exception);
assertThat(dto.getUrl()).isEqualTo("https://scm-manager.org");
}
@Test
void shouldMapUrlToNull() {
ExceptionWithoutUrl exception = new ExceptionWithoutUrl();
ErrorDto dto = mapper.map(exception);
assertThat(dto.getUrl()).isNull();
}
private static class ExceptionWithUrl extends ExceptionWithContext {
public ExceptionWithUrl() {
super(ContextEntry.ContextBuilder.noContext(), "With Url");
}
@Override
public String getCode() {
return "42";
}
@Override
public Optional<String> getUrl() {
return Optional.of("https://scm-manager.org");
}
}
private static class ExceptionWithoutUrl extends ExceptionWithContext {
public ExceptionWithoutUrl() {
super(ContextEntry.ContextBuilder.noContext(), "Without Url");
}
@Override
public String getCode() {
return "21";
}
}
}

View File

@@ -74,6 +74,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
@@ -315,7 +316,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
assertEquals(HttpServletResponse.SC_CREATED, response.getStatus());
assertEquals("/v2/repositories/otherspace/repo", response.getOutputHeaders().get("Location").get(0).toString());
verify(repositoryManager).create(any(Repository.class));
verify(repositoryInitializer, never()).initialize(any(Repository.class));
verify(repositoryInitializer, never()).initialize(any(Repository.class), anyMap());
}
@Test
@@ -336,7 +337,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
assertEquals(HttpServletResponse.SC_CREATED, response.getStatus());
ArgumentCaptor<Repository> captor = ArgumentCaptor.forClass(Repository.class);
verify(repositoryInitializer).initialize(captor.capture());
verify(repositoryInitializer).initialize(captor.capture(), anyMap());
Repository repository = captor.getValue();
assertEquals("space", repository.getNamespace());

View File

@@ -48,7 +48,7 @@ class ReadmeRepositoryContentInitializerTest {
private Repository repository;
private ReadmeRepositoryContentInitializer initializer = new ReadmeRepositoryContentInitializer();
private final ReadmeRepositoryContentInitializer initializer = new ReadmeRepositoryContentInitializer();
@BeforeEach
void setUpContext() {

View File

@@ -21,15 +21,16 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.repository;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableSet;
import com.google.common.io.ByteSource;
import com.google.common.io.ByteStreams;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Answers;
import org.mockito.ArgumentCaptor;
@@ -44,6 +45,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@@ -51,15 +55,13 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
class RepositoryInitializerTest {
private final ObjectMapper mapper = new ObjectMapper();
@Mock
private RepositoryServiceFactory repositoryServiceFactory;
@@ -88,7 +90,7 @@ class RepositoryInitializerTest {
);
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
initializer.initialize(repository);
initializer.initialize(repository, Collections.emptyMap());
verifyFileCreation(readmeContentLoader, "# HeartOfGold");
verifyFileCreation(licenseContentLoader, "MIT");
@@ -108,7 +110,7 @@ class RepositoryInitializerTest {
);
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
initializer.initialize(repository);
initializer.initialize(repository, Collections.emptyMap());
verifyFileCreationWithStream(contentLoader, "awesome");
@@ -138,7 +140,7 @@ class RepositoryInitializerTest {
);
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
initializer.initialize(repository);
initializer.initialize(repository, Collections.emptyMap());
assertThat(reference.get()).isEqualTo("MIT");
}
@@ -149,7 +151,45 @@ class RepositoryInitializerTest {
doThrow(new IOException("epic fail")).when(contentLoader).withData(any(ByteSource.class));
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, ImmutableSet.of(new ReadmeContentInitializer()));
assertThrows(InternalRepositoryException.class, () -> initializer.initialize(repository));
Map<String, JsonNode> contextEntries = Collections.emptyMap();
assertThrows(InternalRepositoryException.class, () -> initializer.initialize(repository, contextEntries));
verify(repositoryService).close();
}
@Test
void shouldCallRepositoryContentInitializerWithContext() throws IOException {
ModifyCommandBuilder.WithOverwriteFlagContentLoader slartiContentLoader = mockContentLoader("Slarti.md");
Set<RepositoryContentInitializer> repositoryContentInitializers = ImmutableSet.of(
new NamedFileInitializer()
);
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
Named named = new Named();
named.setName("Slarti");
initializer.initialize(repository, Collections.singletonMap("named", mapper.valueToTree(named)));
verifyFileCreation(slartiContentLoader, "# Named file");
verify(modifyCommand).setCommitMessage("initialize repository");
verify(modifyCommand).execute();
verify(repositoryService).close();
}
@Test
void shouldDoNoInitializationWithoutContextType() {
Set<RepositoryContentInitializer> repositoryContentInitializers = ImmutableSet.of(
new NamedFileInitializer()
);
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
initializer.initialize(repository, Collections.emptyMap());
verify(modifyCommand, never()).createFile(any());
verify(modifyCommand).setCommitMessage("initialize repository");
verify(modifyCommand).execute();
verify(repositoryService).close();
}
@@ -175,6 +215,29 @@ class RepositoryInitializerTest {
assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(expectedContent);
}
private static class NamedFileInitializer implements RepositoryContentInitializer {
@Override
public void initialize(InitializerContext context) throws IOException {
Optional<Named> named = context.getEntry("named", Named.class);
if (named.isPresent()) {
context.create(named.get().getName() + ".md").from("# Named file");
}
}
}
static class Named {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Priority(1)
private static class ReadmeContentInitializer implements RepositoryContentInitializer {