Subversion repository export

Add the repository export function for Subversion repositories. The repository will be exported as dump file which can be downloaded directly or inside a gzip compressed archive.
This commit is contained in:
Eduard Heimbuch
2021-01-08 09:19:33 +01:00
committed by GitHub
parent badcf3ecb4
commit adf7bac665
21 changed files with 451 additions and 49 deletions

View File

@@ -54,6 +54,7 @@ import sonia.scm.repository.RepositoryInitializer;
import sonia.scm.repository.RepositoryManager;
import sonia.scm.repository.RepositoryTestData;
import sonia.scm.repository.RepositoryType;
import sonia.scm.repository.api.BundleCommandBuilder;
import sonia.scm.repository.api.Command;
import sonia.scm.repository.api.ImportFailedException;
import sonia.scm.repository.api.PullCommandBuilder;
@@ -66,6 +67,7 @@ import sonia.scm.web.RestDispatcher;
import sonia.scm.web.VndMediaType;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.core.MediaType;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@@ -98,7 +100,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.anyString;
@@ -167,6 +168,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
RepositoryCollectionToDtoMapper repositoryCollectionToDtoMapper = new RepositoryCollectionToDtoMapper(repositoryToDtoMapper, resourceLinks);
super.repositoryCollectionResource = new RepositoryCollectionResource(repositoryManager, repositoryCollectionToDtoMapper, dtoToRepositoryMapper, resourceLinks, repositoryInitializer);
super.repositoryImportResource = new RepositoryImportResource(repositoryManager, dtoToRepositoryMapper, serviceFactory, resourceLinks, eventBus);
super.repositoryExportResource = new RepositoryExportResource(repositoryManager, serviceFactory);
dispatcher.addSingletonResource(getRepositoryRootResource());
when(serviceFactory.create(any(Repository.class))).thenReturn(service);
when(scmPathInfoStore.get()).thenReturn(uriInfo);
@@ -710,6 +712,59 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
verify(repositoryManager).unarchive(repository);
}
@Test
public void shouldExportRepository() throws URISyntaxException {
String namespace = "space";
String name = "repo";
Repository repository = mockRepository(namespace, name);
when(manager.get(new NamespaceAndName(namespace, name))).thenReturn(repository);
mockRepositoryHandler(ImmutableSet.of(Command.BUNDLE));
BundleCommandBuilder bundleCommandBuilder = mock(BundleCommandBuilder.class);
when(service.getBundleCommand()).thenReturn(bundleCommandBuilder);
MockHttpRequest request = MockHttpRequest
.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/export/svn");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(SC_OK, response.getStatus());
assertEquals(MediaType.APPLICATION_OCTET_STREAM, response.getOutputHeaders().get("Content-Type").get(0).toString());
verify(service).getBundleCommand();
}
@Test
public void shouldExportRepositoryCompressed() throws URISyntaxException {
String namespace = "space";
String name = "repo";
Repository repository = mockRepository(namespace, name);
when(manager.get(new NamespaceAndName(namespace, name))).thenReturn(repository);
mockRepositoryHandler(ImmutableSet.of(Command.BUNDLE));
BundleCommandBuilder bundleCommandBuilder = mock(BundleCommandBuilder.class);
when(service.getBundleCommand()).thenReturn(bundleCommandBuilder);
MockHttpRequest request = MockHttpRequest
.get("/" + RepositoryRootResource.REPOSITORIES_PATH_V2 + "space/repo/export/svn?compressed=true");
MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
assertEquals(SC_OK, response.getStatus());
assertEquals("application/x-gzip", response.getOutputHeaders().get("Content-Type").get(0).toString());
verify(service).getBundleCommand();
}
private void mockRepositoryHandler(Set<Command> cmds) {
RepositoryHandler repositoryHandler = mock(RepositoryHandler.class);
RepositoryType repositoryType = mock(RepositoryType.class);
when(manager.getHandler("svn")).thenReturn(repositoryHandler);
when(repositoryHandler.getType()).thenReturn(repositoryType);
when(repositoryType.getSupportedCommands()).thenReturn(cmds);
}
private PageResult<Repository> createSingletonPageResult(Repository repository) {
return new PageResult<>(singletonList(repository), 0);
}

View File

@@ -46,6 +46,7 @@ abstract class RepositoryTestBase {
RepositoryCollectionResource repositoryCollectionResource;
AnnotateResource annotateResource;
RepositoryImportResource repositoryImportResource;
RepositoryExportResource repositoryExportResource;
RepositoryRootResource getRepositoryRootResource() {
RepositoryBasedResourceProvider repositoryBasedResourceProvider = new RepositoryBasedResourceProvider(
@@ -59,7 +60,8 @@ abstract class RepositoryTestBase {
of(modificationsRootResource),
of(fileHistoryRootResource),
of(incomingRootResource),
of(annotateResource));
of(annotateResource),
of(repositoryExportResource));
return new RepositoryRootResource(
of(new RepositoryResource(
repositoryToDtoMapper,

View File

@@ -284,6 +284,16 @@ public class RepositoryToRepositoryDtoMapperTest {
dto.getLinks().getLinkBy("unarchive").get().getHref());
}
@Test
public void shouldCreateExportLink() {
Repository repository = createTestRepository();
repository.setType("svn");
RepositoryDto dto = mapper.map(repository);
assertEquals(
"http://example.com/base/v2/repositories/testspace/test/export/svn",
dto.getLinks().getLinkBy("export").get().getHref());
}
private ScmProtocol mockProtocol(String type, String protocol) {
return new MockScmProtocol(type, protocol);
}