Change file order inside repository archive (#1538)

Change repository archive order to export/import repository stores before the actual repository. This is done due to import stores before importing the actual repository and firing hooks that may trigger unnecessary computations otherwise.

Co-authored-by: René Pfeuffer <rene.pfeuffer@cloudogu.com>
This commit is contained in:
Eduard Heimbuch
2021-02-15 15:43:26 +01:00
committed by GitHub
parent 1a2dabeb66
commit 5ea28a84fc
13 changed files with 641 additions and 133 deletions

View File

@@ -24,7 +24,6 @@
package sonia.scm.importexport;
import com.google.common.io.Files;
import com.google.common.io.Resources;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
@@ -44,15 +43,15 @@ import sonia.scm.repository.api.IncompatibleEnvironmentForImportException;
import sonia.scm.repository.api.RepositoryService;
import sonia.scm.repository.api.RepositoryServiceFactory;
import sonia.scm.repository.api.UnbundleCommandBuilder;
import sonia.scm.repository.work.WorkdirProvider;
import sonia.scm.update.UpdateEngine;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.function.Consumer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -60,6 +59,8 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -83,10 +84,25 @@ class FullScmRepositoryImporterTest {
private TarArchiveRepositoryStoreImporter storeImporter;
@Mock
private UpdateEngine updateEngine;
@Mock
private WorkdirProvider workdirProvider;
@InjectMocks
private EnvironmentCheckStep environmentCheckStep;
@InjectMocks
private MetadataImportStep metadataImportStep;
@InjectMocks
private StoreImportStep storeImportStep;
@InjectMocks
private RepositoryImportStep repositoryImportStep;
private FullScmRepositoryImporter fullImporter;
@BeforeEach
void initTestObject() {
fullImporter = new FullScmRepositoryImporter(environmentCheckStep, metadataImportStep, storeImportStep, repositoryImportStep, repositoryManager);
}
@BeforeEach
void initRepositoryService() {
lenient().when(serviceFactory.create(REPOSITORY)).thenReturn(service);
@@ -95,9 +111,9 @@ class FullScmRepositoryImporterTest {
@Test
void shouldNotImportRepositoryIfFileNotExists(@TempDir Path temp) throws IOException {
File emptyFile = new File(temp.resolve("empty").toString());
Files.touch(emptyFile);
FileInputStream inputStream = new FileInputStream(emptyFile);
Path emptyFile = temp.resolve("empty");
Files.createFile(emptyFile);
FileInputStream inputStream = new FileInputStream(emptyFile.toFile());
assertThrows(
ImportFailedException.class,
() -> fullImporter.importFromStream(REPOSITORY, inputStream)
@@ -119,16 +135,15 @@ class FullScmRepositoryImporterTest {
class WithValidEnvironment {
@BeforeEach
void setUpEnvironment() {
void setUpEnvironment(@TempDir Path temp) {
lenient().when(workdirProvider.createNewWorkdir(REPOSITORY.getId())).thenReturn(temp.toFile());
when(compatibilityChecker.check(any())).thenReturn(true);
when(repositoryManager.create(eq(REPOSITORY), any())).thenAnswer(invocation -> {
invocation.getArgument(1, Consumer.class).accept(REPOSITORY);
return REPOSITORY;
});
when(repositoryManager.create(eq(REPOSITORY))).thenReturn(REPOSITORY);
}
@Test
void shouldImportScmRepositoryArchive() throws IOException {
void shouldImportScmRepositoryArchiveWithWorkDir() throws IOException {
InputStream stream = Resources.getResource("sonia/scm/repository/import/scm-import.tar.gz").openStream();
Repository repository = fullImporter.importFromStream(REPOSITORY, stream);
@@ -138,7 +153,18 @@ class FullScmRepositoryImporterTest {
verify(repositoryManager).modify(REPOSITORY);
Collection<RepositoryPermission> updatedPermissions = REPOSITORY.getPermissions();
assertThat(updatedPermissions).hasSize(2);
verify(unbundleCommandBuilder).unbundle((InputStream) argThat(argument -> argument.getClass().equals(FullScmRepositoryImporter.NoneClosingInputStream.class)));
verify(unbundleCommandBuilder).unbundle((InputStream) argThat(argument -> argument.getClass().equals(NoneClosingInputStream.class)));
verify(workdirProvider, times(1)).createNewWorkdir(REPOSITORY.getId());
}
@Test
void shouldNotExistWorkDirAfterRepositoryImportIsFinished(@TempDir Path temp) throws IOException {
when(workdirProvider.createNewWorkdir(REPOSITORY.getId())).thenReturn(temp.toFile());
InputStream stream = Resources.getResource("sonia/scm/repository/import/scm-import.tar.gz").openStream();
fullImporter.importFromStream(REPOSITORY, stream);
boolean workDirExists = Files.exists(temp);
assertThat(workDirExists).isFalse();
}
@Test
@@ -149,5 +175,17 @@ class FullScmRepositoryImporterTest {
verify(updateEngine).update(REPOSITORY.getId());
}
@Test
void shouldImportRepositoryDirectlyWithoutCopyInWorkDir() throws IOException {
InputStream stream = Resources.getResource("sonia/scm/repository/import/scm-import-stores-before-repository.tar.gz").openStream();
Repository repository = fullImporter.importFromStream(REPOSITORY, stream);
assertThat(repository).isEqualTo(REPOSITORY);
verify(storeImporter).importFromTarArchive(eq(REPOSITORY), any(InputStream.class));
verify(repositoryManager).modify(REPOSITORY);
verify(unbundleCommandBuilder).unbundle((InputStream) argThat(argument -> argument.getClass().equals(NoneClosingInputStream.class)));
verify(workdirProvider, never()).createNewWorkdir(REPOSITORY.getId());
}
}
}