From 8a6b57e06c998a81000fe23c6cce8d30b351a800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Fri, 7 Jun 2019 13:52:54 +0200 Subject: [PATCH] Add new migration strategies "delete" and "ignore" --- .../repository/CopyMigrationStrategy.java | 7 ++-- .../repository/DeleteMigrationStrategy.java | 32 +++++++++++++++++++ .../repository/IgnoreMigrationStrategy.java | 13 ++++++++ .../repository/InlineMigrationStrategy.java | 7 ++-- .../update/repository/MigrationStrategy.java | 15 +++++++-- .../repository/MoveMigrationStrategy.java | 6 ++-- .../repository/XmlRepositoryV1UpdateStep.java | 30 +++++++++-------- .../repository/CopyMigrationStrategyTest.java | 4 +-- .../InlineMigrationStrategyTest.java | 2 +- .../repository/MigrationStrategyMock.java | 10 ++++++ .../repository/MoveMigrationStrategyTest.java | 4 +-- .../XmlRepositoryV1UpdateStepTest.java | 18 ++++++++++- 12 files changed, 121 insertions(+), 27 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/update/repository/DeleteMigrationStrategy.java create mode 100644 scm-webapp/src/main/java/sonia/scm/update/repository/IgnoreMigrationStrategy.java diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/CopyMigrationStrategy.java b/scm-webapp/src/main/java/sonia/scm/update/repository/CopyMigrationStrategy.java index f96413d195..b66b2ea9c9 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/repository/CopyMigrationStrategy.java +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/CopyMigrationStrategy.java @@ -9,6 +9,9 @@ import sonia.scm.repository.RepositoryLocationResolver; import javax.inject.Inject; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Optional; + +import static java.util.Optional.of; class CopyMigrationStrategy extends BaseMigrationStrategy { @@ -23,14 +26,14 @@ class CopyMigrationStrategy extends BaseMigrationStrategy { } @Override - public Path migrate(String id, String name, String type) { + public Optional migrate(String id, String name, String type) { Path repositoryBasePath = locationResolver.forClass(Path.class).createLocation(id); Path targetDataPath = repositoryBasePath .resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY); Path sourceDataPath = getSourceDataPath(name, type); LOG.info("copying repository data from {} to {}", sourceDataPath, targetDataPath); copyData(sourceDataPath, targetDataPath); - return repositoryBasePath; + return of(repositoryBasePath); } private void copyData(Path sourceDirectory, Path targetDirectory) { diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/DeleteMigrationStrategy.java b/scm-webapp/src/main/java/sonia/scm/update/repository/DeleteMigrationStrategy.java new file mode 100644 index 0000000000..cf61152613 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/DeleteMigrationStrategy.java @@ -0,0 +1,32 @@ +package sonia.scm.update.repository; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import sonia.scm.SCMContextProvider; +import sonia.scm.util.IOUtil; + +import javax.inject.Inject; +import java.io.IOException; +import java.nio.file.Path; +import java.util.Optional; + +public class DeleteMigrationStrategy extends BaseMigrationStrategy { + + private static final Logger LOG = LoggerFactory.getLogger(DeleteMigrationStrategy.class); + + @Inject + DeleteMigrationStrategy(SCMContextProvider contextProvider) { + super(contextProvider); + } + + @Override + public Optional migrate(String id, String name, String type) { + Path sourceDataPath = getSourceDataPath(name, type); + try { + IOUtil.delete(sourceDataPath.toFile(), true); + } catch (IOException e) { + LOG.warn("could not delete old repository path for repository {} with type {} and id {}", name, type, id); + } + return Optional.empty(); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/IgnoreMigrationStrategy.java b/scm-webapp/src/main/java/sonia/scm/update/repository/IgnoreMigrationStrategy.java new file mode 100644 index 0000000000..945538009a --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/IgnoreMigrationStrategy.java @@ -0,0 +1,13 @@ +package sonia.scm.update.repository; + +import java.nio.file.Path; +import java.util.Optional; + +import static java.util.Optional.empty; + +public class IgnoreMigrationStrategy implements MigrationStrategy.Instance { + @Override + public Optional migrate(String id, String name, String type) { + return empty(); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/InlineMigrationStrategy.java b/scm-webapp/src/main/java/sonia/scm/update/repository/InlineMigrationStrategy.java index 60f03666a5..a75ff5e571 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/repository/InlineMigrationStrategy.java +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/InlineMigrationStrategy.java @@ -10,6 +10,9 @@ import javax.inject.Inject; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Optional; + +import static java.util.Optional.of; class InlineMigrationStrategy extends BaseMigrationStrategy { @@ -24,14 +27,14 @@ class InlineMigrationStrategy extends BaseMigrationStrategy { } @Override - public Path migrate(String id, String name, String type) { + public Optional migrate(String id, String name, String type) { Path repositoryBasePath = getSourceDataPath(name, type); locationResolver.forClass(Path.class).setLocation(id, repositoryBasePath); Path targetDataPath = repositoryBasePath .resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY); LOG.info("moving repository data from {} to {}", repositoryBasePath, targetDataPath); moveData(repositoryBasePath, targetDataPath); - return repositoryBasePath; + return of(repositoryBasePath); } private void moveData(Path sourceDirectory, Path targetDirectory) { diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/MigrationStrategy.java b/scm-webapp/src/main/java/sonia/scm/update/repository/MigrationStrategy.java index f3de48cfd9..46604d327e 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/repository/MigrationStrategy.java +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/MigrationStrategy.java @@ -3,6 +3,7 @@ package sonia.scm.update.repository; import com.google.inject.Injector; import java.nio.file.Path; +import java.util.Optional; public enum MigrationStrategy { @@ -15,7 +16,13 @@ public enum MigrationStrategy { INLINE(InlineMigrationStrategy.class, "Use the current directory where the repository data files are stored, but modify the directory " + "structure so that it can be used for SCM-Manager v2. The repository data files will be moved to a new " + - "subdirectory 'data' inside the current directory."); + "subdirectory 'data' inside the current directory."), + IGNORE(IgnoreMigrationStrategy.class, + "The repository will not be migrated and will not be visible inside SCM-Manager. " + + "The data files will be kept at the current location."), + DELETE(DeleteMigrationStrategy.class, + "The repository will not be migrated and will not be visible inside SCM-Manager. " + + "The data files will be deleted!"); private final Class implementationClass; private final String description; @@ -25,6 +32,10 @@ public enum MigrationStrategy { this.description = description; } + public Class getImplementationClass() { + return implementationClass; + } + public String getDescription() { return description; } @@ -34,6 +45,6 @@ public enum MigrationStrategy { } interface Instance { - Path migrate(String id, String name, String type); + Optional migrate(String id, String name, String type); } } diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/MoveMigrationStrategy.java b/scm-webapp/src/main/java/sonia/scm/update/repository/MoveMigrationStrategy.java index deb8a8782b..5b364d8bc3 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/repository/MoveMigrationStrategy.java +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/MoveMigrationStrategy.java @@ -11,8 +11,10 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.Optional; import static java.util.Arrays.asList; +import static java.util.Optional.of; class MoveMigrationStrategy extends BaseMigrationStrategy { @@ -27,7 +29,7 @@ class MoveMigrationStrategy extends BaseMigrationStrategy { } @Override - public Path migrate(String id, String name, String type) { + public Optional migrate(String id, String name, String type) { Path repositoryBasePath = locationResolver.forClass(Path.class).createLocation(id); Path targetDataPath = repositoryBasePath .resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY); @@ -35,7 +37,7 @@ class MoveMigrationStrategy extends BaseMigrationStrategy { LOG.info("moving repository data from {} to {}", sourceDataPath, targetDataPath); moveData(sourceDataPath, targetDataPath); deleteOldDataDir(getTypeDependentPath(type), name); - return repositoryBasePath; + return of(repositoryBasePath); } private void deleteOldDataDir(Path rootPath, String name) { diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStep.java b/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStep.java index aeb74971a9..0d40a1b413 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStep.java +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStep.java @@ -141,21 +141,25 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep { } private void update(V1Repository v1Repository) { - Path destination = handleDataDirectory(v1Repository); - Repository repository = new Repository( - v1Repository.id, - v1Repository.type, - v1Repository.getNewNamespace(), - v1Repository.getNewName(), - v1Repository.contact, - v1Repository.description, - createPermissions(v1Repository)); - LOG.info("creating new repository {} with id {} from old repository {} in directory {}", repository.getNamespaceAndName(), repository.getId(), v1Repository.name, destination); - repositoryDao.add(repository, destination); - propertyStore.put(v1Repository.id, v1Repository.properties); + Optional destination = handleDataDirectory(v1Repository); + destination.ifPresent( + newPath -> { + Repository repository = new Repository( + v1Repository.id, + v1Repository.type, + v1Repository.getNewNamespace(), + v1Repository.getNewName(), + v1Repository.contact, + v1Repository.description, + createPermissions(v1Repository)); + LOG.info("creating new repository {} with id {} from old repository {} in directory {}", repository.getNamespaceAndName(), repository.getId(), v1Repository.name, newPath); + repositoryDao.add(repository, newPath); + propertyStore.put(v1Repository.id, v1Repository.properties); + } + ); } - private Path handleDataDirectory(V1Repository v1Repository) { + private Optional handleDataDirectory(V1Repository v1Repository) { MigrationStrategy dataMigrationStrategy = readMigrationStrategy(v1Repository); LOG.info("using strategy {} to migrate repository {} with id {}", dataMigrationStrategy.getClass(), v1Repository.name, v1Repository.id); return dataMigrationStrategy.from(injector).migrate(v1Repository.id, v1Repository.name, v1Repository.type); diff --git a/scm-webapp/src/test/java/sonia/scm/update/repository/CopyMigrationStrategyTest.java b/scm-webapp/src/test/java/sonia/scm/update/repository/CopyMigrationStrategyTest.java index d718554dfe..d3f18a1ff7 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/repository/CopyMigrationStrategyTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/repository/CopyMigrationStrategyTest.java @@ -48,13 +48,13 @@ class CopyMigrationStrategyTest { @Test void shouldUseStandardDirectory(@TempDirectory.TempDir Path tempDir) { - Path target = new CopyMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git"); + Path target = new CopyMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git").get(); assertThat(target).isEqualTo(tempDir.resolve("b4f-a9f0-49f7-ad1f-37d3aae1c55f")); } @Test void shouldCopyDataDirectory(@TempDirectory.TempDir Path tempDir) { - Path target = new CopyMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git"); + Path target = new CopyMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git").get(); assertThat(target.resolve("data")).exists(); Path originalDataDir = tempDir .resolve("repositories") diff --git a/scm-webapp/src/test/java/sonia/scm/update/repository/InlineMigrationStrategyTest.java b/scm-webapp/src/test/java/sonia/scm/update/repository/InlineMigrationStrategyTest.java index fa237e78b0..2b97c1d79b 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/repository/InlineMigrationStrategyTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/repository/InlineMigrationStrategyTest.java @@ -41,7 +41,7 @@ class InlineMigrationStrategyTest { @Test void shouldUseExistingDirectory(@TempDirectory.TempDir Path tempDir) { - Path target = new InlineMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git"); + Path target = new InlineMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git").get(); assertThat(target).isEqualTo(resolveOldDirectory(tempDir)); verify(locationResolverInstance).setLocation("b4f-a9f0-49f7-ad1f-37d3aae1c55f", target); } diff --git a/scm-webapp/src/test/java/sonia/scm/update/repository/MigrationStrategyMock.java b/scm-webapp/src/test/java/sonia/scm/update/repository/MigrationStrategyMock.java index e0018f584f..c04c9477bb 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/repository/MigrationStrategyMock.java +++ b/scm-webapp/src/test/java/sonia/scm/update/repository/MigrationStrategyMock.java @@ -3,10 +3,13 @@ package sonia.scm.update.repository; import com.google.inject.Injector; import sonia.scm.update.repository.MigrationStrategy.Instance; +import java.nio.file.Paths; import java.util.HashMap; import java.util.Map; +import static java.util.Optional.of; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -20,6 +23,13 @@ class MigrationStrategyMock { .thenAnswer( invocationOnMock -> mocks.computeIfAbsent(invocationOnMock.getArgument(0), key -> mock((Class) key)) ); + + for (MigrationStrategy strategy : MigrationStrategy.values()) { + MigrationStrategy.Instance strategyMock = mock(strategy.getImplementationClass()); + when(strategyMock.migrate(any(), any(), any())).thenReturn(of(Paths.get(""))); + lenient().when(mock.getInstance((Class) strategy.getImplementationClass())).thenReturn(strategyMock); + } + return mock; } } diff --git a/scm-webapp/src/test/java/sonia/scm/update/repository/MoveMigrationStrategyTest.java b/scm-webapp/src/test/java/sonia/scm/update/repository/MoveMigrationStrategyTest.java index e248f82217..fa58eb8ea1 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/repository/MoveMigrationStrategyTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/repository/MoveMigrationStrategyTest.java @@ -45,13 +45,13 @@ class MoveMigrationStrategyTest { @Test void shouldUseStandardDirectory(@TempDirectory.TempDir Path tempDir) { - Path target = new MoveMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git"); + Path target = new MoveMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git").get(); assertThat(target).isEqualTo(tempDir.resolve("b4f-a9f0-49f7-ad1f-37d3aae1c55f")); } @Test void shouldMoveDataDirectory(@TempDirectory.TempDir Path tempDir) { - Path target = new MoveMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git"); + Path target = new MoveMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git").get(); assertThat(target.resolve("data")).exists(); Path originalDataDir = tempDir .resolve("repositories") diff --git a/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java index b07f7f786c..76a74993b3 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryV1UpdateStepTest.java @@ -25,6 +25,7 @@ import java.io.IOException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Optional; import static java.util.Optional.empty; @@ -33,10 +34,12 @@ 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.Mockito.lenient; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static sonia.scm.update.repository.MigrationStrategy.COPY; +import static sonia.scm.update.repository.MigrationStrategy.DELETE; import static sonia.scm.update.repository.MigrationStrategy.INLINE; import static sonia.scm.update.repository.MigrationStrategy.MOVE; @@ -177,13 +180,26 @@ class XmlRepositoryV1UpdateStepTest { void shouldUseDirectoryFromStrategy(@TempDirectory.TempDir Path tempDir) throws JAXBException { Path targetDir = tempDir.resolve("someDir"); MigrationStrategy.Instance strategyMock = injectorMock.getInstance(InlineMigrationStrategy.class); - when(strategyMock.migrate("454972da-faf9-4437-b682-dc4a4e0aa8eb", "simple", "git")).thenReturn(targetDir); + when(strategyMock.migrate("454972da-faf9-4437-b682-dc4a4e0aa8eb", "simple", "git")).thenReturn(of(targetDir)); updateStep.doUpdate(); assertThat(locationCaptor.getAllValues()).contains(targetDir); } + @Test + void shouldSkipWhenStrategyGivesNoNewPath() throws JAXBException { + for (MigrationStrategy strategy : MigrationStrategy.values()) { + MigrationStrategy.Instance strategyMock = mock(strategy.getImplementationClass()); + lenient().when(strategyMock.migrate(any(), any(), any())).thenReturn(empty()); + lenient().when(injectorMock.getInstance((Class) strategy.getImplementationClass())).thenReturn(strategyMock); + } + + updateStep.doUpdate(); + + assertThat(locationCaptor.getAllValues()).isEmpty(); + } + @Test void shouldFailForMissingMigrationStrategy() { lenient().when(migrationStrategyDao.get("c1597b4f-a9f0-49f7-ad1f-37d3aae1c55f")).thenReturn(empty());