mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 01:15:44 +01:00
create RepositoryInitializer which can be used to create new files in the initial commit on a new repository
This commit is contained in:
@@ -18,6 +18,7 @@ import org.mockito.Mock;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryInitializer;
|
||||
import sonia.scm.repository.RepositoryManager;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
@@ -76,6 +77,8 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
private ScmPathInfoStore scmPathInfoStore;
|
||||
@Mock
|
||||
private ScmPathInfo uriInfo;
|
||||
@Mock
|
||||
private RepositoryInitializer repositoryInitializer;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<Predicate<Repository>> filterCaptor;
|
||||
@@ -95,7 +98,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
super.dtoToRepositoryMapper = dtoToRepositoryMapper;
|
||||
super.manager = repositoryManager;
|
||||
RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks);
|
||||
super.repositoryCollectionResource = Providers.of(new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks));
|
||||
super.repositoryCollectionResource = Providers.of(new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks, repositoryInitializer));
|
||||
dispatcher.addSingletonResource(getRepositoryRootResource());
|
||||
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
|
||||
when(scmPathInfoStore.get()).thenReturn(uriInfo);
|
||||
@@ -288,6 +291,32 @@ 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));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateNewRepositoryAndInitialize() throws Exception {
|
||||
when(repositoryManager.create(any())).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
|
||||
URL url = Resources.getResource("sonia/scm/api/v2/repository-test-update.json");
|
||||
byte[] repositoryJson = Resources.toByteArray(url);
|
||||
|
||||
MockHttpRequest request = MockHttpRequest
|
||||
.post("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "?initialize=true")
|
||||
.contentType(VndMediaType.REPOSITORY)
|
||||
.content(repositoryJson);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_CREATED, response.getStatus());
|
||||
|
||||
ArgumentCaptor<Repository> captor = ArgumentCaptor.forClass(Repository.class);
|
||||
verify(repositoryInitializer).initialize(captor.capture());
|
||||
|
||||
Repository repository = captor.getValue();
|
||||
assertEquals("space", repository.getNamespace());
|
||||
assertEquals("repo", repository.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
package sonia.scm.repository;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class ReadmeRepositoryContentInitializerTest {
|
||||
|
||||
@Mock
|
||||
private RepositoryContentInitializer.InitializerContext context;
|
||||
|
||||
@Mock
|
||||
private RepositoryContentInitializer.CreateFile createFile;
|
||||
|
||||
private Repository repository;
|
||||
|
||||
private ReadmeRepositoryContentInitializer initializer = new ReadmeRepositoryContentInitializer();
|
||||
|
||||
@BeforeEach
|
||||
void setUpContext() {
|
||||
repository = RepositoryTestData.createHeartOfGold("hg");
|
||||
when(context.getRepository()).thenReturn(repository);
|
||||
when(context.create("README.md")).thenReturn(createFile);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateReadme() throws IOException {
|
||||
initializer.initialize(context);
|
||||
|
||||
verify(createFile).from("# HeartOfGold\n\n" + repository.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateReadmeWithoutDescription() throws IOException {
|
||||
repository.setDescription(null);
|
||||
|
||||
initializer.initialize(context);
|
||||
|
||||
verify(createFile).from("# HeartOfGold");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package sonia.scm.repository;
|
||||
|
||||
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;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.Priority;
|
||||
import sonia.scm.repository.api.ModifyCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
import sonia.scm.repository.api.RepositoryServiceFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
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;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class RepositoryInitializerTest {
|
||||
|
||||
@Mock
|
||||
private RepositoryServiceFactory repositoryServiceFactory;
|
||||
|
||||
@Mock
|
||||
private RepositoryService repositoryService;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private ModifyCommandBuilder modifyCommand;
|
||||
|
||||
private final Repository repository = RepositoryTestData.createHeartOfGold("git");
|
||||
|
||||
@BeforeEach
|
||||
void setUpModifyCommand() {
|
||||
when(repositoryServiceFactory.create(repository)).thenReturn(repositoryService);
|
||||
when(repositoryService.getModifyCommand()).thenReturn(modifyCommand);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCallRepositoryContentInitializer() throws IOException {
|
||||
ModifyCommandBuilder.WithOverwriteFlagContentLoader readmeContentLoader = mockContentLoader("README.md");
|
||||
ModifyCommandBuilder.WithOverwriteFlagContentLoader licenseContentLoader = mockContentLoader("LICENSE.txt");
|
||||
|
||||
Set<RepositoryContentInitializer> repositoryContentInitializers = ImmutableSet.of(
|
||||
new ReadmeContentInitializer(),
|
||||
new LicenseContentInitializer()
|
||||
);
|
||||
|
||||
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
|
||||
initializer.initialize(repository);
|
||||
|
||||
verifyFileCreation(readmeContentLoader, "# HeartOfGold");
|
||||
verifyFileCreation(licenseContentLoader, "MIT");
|
||||
|
||||
verify(modifyCommand).setCommitMessage("initialize repository");
|
||||
verify(modifyCommand).execute();
|
||||
|
||||
verify(repositoryService).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCallRepositoryContentInitializerWithInputStream() throws IOException {
|
||||
ModifyCommandBuilder.WithOverwriteFlagContentLoader contentLoader = mockContentLoader("awesome.txt");
|
||||
|
||||
Set<RepositoryContentInitializer> repositoryContentInitializers = ImmutableSet.of(
|
||||
new StreamingContentInitializer()
|
||||
);
|
||||
|
||||
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
|
||||
initializer.initialize(repository);
|
||||
|
||||
verifyFileCreationWithStream(contentLoader, "awesome");
|
||||
|
||||
verify(modifyCommand).setCommitMessage("initialize repository");
|
||||
verify(modifyCommand).execute();
|
||||
|
||||
verify(repositoryService).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRespectPriorityOrder() throws IOException {
|
||||
ModifyCommandBuilder.WithOverwriteFlagContentLoader contentLoader = mock(ModifyCommandBuilder.WithOverwriteFlagContentLoader.class);
|
||||
when(contentLoader.setOverwrite(true)).thenReturn(contentLoader);
|
||||
|
||||
when(modifyCommand.createFile(anyString())).thenReturn(contentLoader);
|
||||
|
||||
AtomicReference<String> reference = new AtomicReference<>();
|
||||
when(contentLoader.withData(any(ByteSource.class))).thenAnswer(ic -> {
|
||||
ByteSource byteSource = ic.getArgument(0);
|
||||
reference.set(byteSource.asCharSource(StandardCharsets.UTF_8).read());
|
||||
return modifyCommand;
|
||||
});
|
||||
|
||||
Set<RepositoryContentInitializer> repositoryContentInitializers = ImmutableSet.of(
|
||||
new LicenseContentInitializer(),
|
||||
new ReadmeContentInitializer()
|
||||
);
|
||||
|
||||
RepositoryInitializer initializer = new RepositoryInitializer(repositoryServiceFactory, repositoryContentInitializers);
|
||||
initializer.initialize(repository);
|
||||
|
||||
assertThat(reference.get()).isEqualTo("MIT");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCloseRepositoryServiceOnException() throws IOException {
|
||||
ModifyCommandBuilder.WithOverwriteFlagContentLoader contentLoader = mockContentLoader("README.md");
|
||||
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));
|
||||
|
||||
verify(repositoryService).close();
|
||||
}
|
||||
|
||||
private ModifyCommandBuilder.WithOverwriteFlagContentLoader mockContentLoader(String path) {
|
||||
ModifyCommandBuilder.WithOverwriteFlagContentLoader contentLoader = mock(ModifyCommandBuilder.WithOverwriteFlagContentLoader.class);
|
||||
doReturn(contentLoader).when(modifyCommand).createFile(path);
|
||||
when(contentLoader.setOverwrite(true)).thenReturn(contentLoader);
|
||||
return contentLoader;
|
||||
}
|
||||
|
||||
private void verifyFileCreation(ModifyCommandBuilder.WithOverwriteFlagContentLoader contentLoader, String expectedContent) throws IOException {
|
||||
ArgumentCaptor<ByteSource> captor = ArgumentCaptor.forClass(ByteSource.class);
|
||||
verify(contentLoader).withData(captor.capture());
|
||||
String content = captor.getValue().asCharSource(StandardCharsets.UTF_8).read();
|
||||
assertThat(content).isEqualTo(expectedContent);
|
||||
}
|
||||
|
||||
private void verifyFileCreationWithStream(ModifyCommandBuilder.WithOverwriteFlagContentLoader contentLoader, String expectedContent) throws IOException {
|
||||
ArgumentCaptor<InputStream> captor = ArgumentCaptor.forClass(InputStream.class);
|
||||
verify(contentLoader).withData(captor.capture());
|
||||
byte[] bytes = ByteStreams.toByteArray(captor.getValue());
|
||||
assertThat(new String(bytes, StandardCharsets.UTF_8)).isEqualTo(expectedContent);
|
||||
}
|
||||
|
||||
@Priority(1)
|
||||
private static class ReadmeContentInitializer implements RepositoryContentInitializer {
|
||||
|
||||
@Override
|
||||
public void initialize(InitializerContext context) throws IOException {
|
||||
Repository repository = context.getRepository();
|
||||
context.create("README.md").from("# " + repository.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@Priority(2)
|
||||
private static class LicenseContentInitializer implements RepositoryContentInitializer {
|
||||
|
||||
@Override
|
||||
public void initialize(InitializerContext context) throws IOException {
|
||||
context.create("LICENSE.txt").from("MIT");
|
||||
}
|
||||
}
|
||||
|
||||
private static class StreamingContentInitializer implements RepositoryContentInitializer {
|
||||
|
||||
@Override
|
||||
public void initialize(InitializerContext context) throws IOException {
|
||||
context.create("awesome.txt").from(new ByteArrayInputStream("awesome".getBytes(StandardCharsets.UTF_8)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user