From 9581bf946b8dd31b57d73d36f1cdda4e1cd4179e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 20 Jun 2019 16:12:16 +0200 Subject: [PATCH] Enable plugins to create config stores for repository config Therefore we have to - add an API to create stores for repository ids, not only for repositories, - make v1 properties available in scm-core - make sure that properties are extracted from repositories before the update step of a plugin runs (this is done by sorting the update steps in a way so that "core" update steps are executed before plugin update steps with the same version) --- .../sonia/scm/store/BlobStoreFactory.java | 19 +++++++++--- .../store/ConfigurationEntryStoreFactory.java | 13 +++++++- .../scm/store/ConfigurationStoreFactory.java | 13 +++++++- .../sonia/scm/store/DataStoreFactory.java | 13 +++++++- .../java/sonia/scm/store/StoreParameters.java | 2 +- .../sonia/scm/store/TypedStoreParameters.java | 2 +- .../scm/store/TypedStoreParametersImpl.java | 12 ++++---- .../update/RepositoryV1PropertyReader.java | 23 ++++++++++++++ .../java/sonia/scm/update}/V1Properties.java | 6 ++-- .../java/sonia/scm/update}/V1Property.java | 2 +- .../java/sonia/scm/update/V1PropertyDAO.java | 5 ++++ .../sonia/scm/update/V1PropertyReader.java | 15 ++++++++++ .../scm/store/FileBasedStoreFactory.java | 19 ++++++------ .../JAXBConfigurationEntryStoreFactory.java | 6 ++-- .../store/JAXBConfigurationStoreFactory.java | 6 +++- .../scm/update/xml/XmlV1PropertyDAO.java | 30 +++++++++++++++++++ .../spi/GitIncomingCommandTest.java | 5 ++-- .../spi/GitOutgoingCommandTest.java | 3 +- .../scm/web/lfs/LfsBlobStoreFactoryTest.java | 2 +- .../java/sonia/scm/boot/BootstrapModule.java | 3 ++ .../java/sonia/scm/update/CoreUpdateStep.java | 6 ++++ .../java/sonia/scm/update/UpdateEngine.java | 10 ++++++- .../update/group/XmlGroupV1UpdateStep.java | 2 +- .../scm/update/repository/V1Repository.java | 2 +- .../repository/XmlRepositoryV1UpdateStep.java | 8 +++-- .../scm/update/user/XmlUserV1UpdateStep.java | 2 +- .../sonia/scm/update/UpdateEngineTest.java | 26 ++++++++++++++-- .../group/XmlGroupV1UpdateStepTest.java | 15 ++++------ .../update/user/XmlUserV1UpdateStepTest.java | 16 ++++------ 29 files changed, 220 insertions(+), 66 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java rename {scm-webapp/src/main/java/sonia/scm/update/properties => scm-core/src/main/java/sonia/scm/update}/V1Properties.java (71%) rename {scm-webapp/src/main/java/sonia/scm/update/properties => scm-core/src/main/java/sonia/scm/update}/V1Property.java (96%) create mode 100644 scm-core/src/main/java/sonia/scm/update/V1PropertyDAO.java create mode 100644 scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java create mode 100644 scm-dao-xml/src/main/java/sonia/scm/update/xml/XmlV1PropertyDAO.java create mode 100644 scm-webapp/src/main/java/sonia/scm/update/CoreUpdateStep.java diff --git a/scm-core/src/main/java/sonia/scm/store/BlobStoreFactory.java b/scm-core/src/main/java/sonia/scm/store/BlobStoreFactory.java index cf58fc43c7..4cc124c5d7 100644 --- a/scm-core/src/main/java/sonia/scm/store/BlobStoreFactory.java +++ b/scm-core/src/main/java/sonia/scm/store/BlobStoreFactory.java @@ -82,7 +82,7 @@ public interface BlobStoreFactory { final class FloatingStoreParameters implements StoreParameters { private String name; - private Repository repository; + private String repositoryId; private final BlobStoreFactory factory; @@ -96,8 +96,8 @@ final class FloatingStoreParameters implements StoreParameters { } @Override - public Repository getRepository() { - return repository; + public String getRepositoryId() { + return repositoryId; } public class Builder { @@ -113,7 +113,18 @@ final class FloatingStoreParameters implements StoreParameters { * @return Floating API to finish the call. */ public FloatingStoreParameters.Builder forRepository(Repository repository) { - FloatingStoreParameters.this.repository = repository; + FloatingStoreParameters.this.repositoryId = repository.getId(); + return this; + } + + /** + * Use this to create or get a {@link BlobStore} for a specific repository. This step is optional. If you want to + * have a global {@link BlobStore}, omit this. + * @param repositoryId The id of the optional repository for the {@link BlobStore}. + * @return Floating API to finish the call. + */ + public FloatingStoreParameters.Builder forRepository(String repositoryId) { + FloatingStoreParameters.this.repositoryId = repositoryId; return this; } diff --git a/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStoreFactory.java b/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStoreFactory.java index 80f9cb3df9..7ff1633dc3 100644 --- a/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStoreFactory.java +++ b/scm-core/src/main/java/sonia/scm/store/ConfigurationEntryStoreFactory.java @@ -120,7 +120,18 @@ final class TypedFloatingConfigurationEntryStoreParameters { * @return Floating API to finish the call. */ public OptionalRepositoryBuilder forRepository(Repository repository) { - parameters.setRepository(repository); + parameters.setRepositoryId(repository.getId()); + return this; + } + + /** + * Use this to create or get a {@link ConfigurationEntryStore} for a specific repository. This step is optional. If + * you want to have a global {@link ConfigurationEntryStore}, omit this. + * @param repositoryId The id of the optional repository for the {@link ConfigurationEntryStore}. + * @return Floating API to finish the call. + */ + public OptionalRepositoryBuilder forRepository(String repositoryId) { + parameters.setRepositoryId(repositoryId); return this; } diff --git a/scm-core/src/main/java/sonia/scm/store/ConfigurationStoreFactory.java b/scm-core/src/main/java/sonia/scm/store/ConfigurationStoreFactory.java index 6624f307e7..cef39a303b 100644 --- a/scm-core/src/main/java/sonia/scm/store/ConfigurationStoreFactory.java +++ b/scm-core/src/main/java/sonia/scm/store/ConfigurationStoreFactory.java @@ -120,7 +120,18 @@ final class TypedFloatingConfigurationStoreParameters { * @return Floating API to finish the call. */ public OptionalRepositoryBuilder forRepository(Repository repository) { - parameters.setRepository(repository); + parameters.setRepositoryId(repository.getId()); + return this; + } + + /** + * Use this to create or get a {@link ConfigurationStore} for a specific repository. This step is optional. If you + * want to have a global {@link ConfigurationStore}, omit this. + * @param repositoryId The id of the optional repository for the {@link ConfigurationStore}. + * @return Floating API to finish the call. + */ + public OptionalRepositoryBuilder forRepository(String repositoryId) { + parameters.setRepositoryId(repositoryId); return this; } diff --git a/scm-core/src/main/java/sonia/scm/store/DataStoreFactory.java b/scm-core/src/main/java/sonia/scm/store/DataStoreFactory.java index 564c339d3d..cc149d46ce 100644 --- a/scm-core/src/main/java/sonia/scm/store/DataStoreFactory.java +++ b/scm-core/src/main/java/sonia/scm/store/DataStoreFactory.java @@ -117,7 +117,18 @@ final class TypedFloatingDataStoreParameters { * @return Floating API to finish the call. */ public OptionalRepositoryBuilder forRepository(Repository repository) { - parameters.setRepository(repository); + parameters.setRepositoryId(repository.getId()); + return this; + } + + /** + * Use this to create or get a {@link DataStore} for a specific repository. This step is optional. If you + * want to have a global {@link DataStore}, omit this. + * @param repositoryId The id of the optional repository for the {@link DataStore}. + * @return Floating API to finish the call. + */ + public OptionalRepositoryBuilder forRepository(String repositoryId) { + parameters.setRepositoryId(repositoryId); return this; } diff --git a/scm-core/src/main/java/sonia/scm/store/StoreParameters.java b/scm-core/src/main/java/sonia/scm/store/StoreParameters.java index da8ee4c916..38404398cc 100644 --- a/scm-core/src/main/java/sonia/scm/store/StoreParameters.java +++ b/scm-core/src/main/java/sonia/scm/store/StoreParameters.java @@ -12,5 +12,5 @@ public interface StoreParameters { String getName(); - Repository getRepository(); + String getRepositoryId(); } diff --git a/scm-core/src/main/java/sonia/scm/store/TypedStoreParameters.java b/scm-core/src/main/java/sonia/scm/store/TypedStoreParameters.java index 116bccac41..060a9706f8 100644 --- a/scm-core/src/main/java/sonia/scm/store/TypedStoreParameters.java +++ b/scm-core/src/main/java/sonia/scm/store/TypedStoreParameters.java @@ -15,5 +15,5 @@ public interface TypedStoreParameters { String getName(); - Repository getRepository(); + String getRepositoryId(); } diff --git a/scm-core/src/main/java/sonia/scm/store/TypedStoreParametersImpl.java b/scm-core/src/main/java/sonia/scm/store/TypedStoreParametersImpl.java index 50ce6a496b..3abf1d2192 100644 --- a/scm-core/src/main/java/sonia/scm/store/TypedStoreParametersImpl.java +++ b/scm-core/src/main/java/sonia/scm/store/TypedStoreParametersImpl.java @@ -1,11 +1,9 @@ package sonia.scm.store; -import sonia.scm.repository.Repository; - class TypedStoreParametersImpl implements TypedStoreParameters { private Class type; private String name; - private Repository repository; + private String repositoryId; @Override public Class getType() { @@ -26,11 +24,11 @@ class TypedStoreParametersImpl implements TypedStoreParameters { } @Override - public Repository getRepository() { - return repository; + public String getRepositoryId() { + return repositoryId; } - void setRepository(Repository repository) { - this.repository = repository; + void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; } } diff --git a/scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java b/scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java new file mode 100644 index 0000000000..cb9f2d01d9 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/update/RepositoryV1PropertyReader.java @@ -0,0 +1,23 @@ +package sonia.scm.update; + +import java.util.Map; +import java.util.function.BiConsumer; + +public class RepositoryV1PropertyReader implements V1PropertyReader { + @Override + public String getStoreName() { + return "repository-properties-v1"; + } + + @Override + public Instance createInstance(Map all) { + return propertiesForNameConsumer -> + all + .entrySet() + .forEach(e -> call(e.getKey(), e.getValue(), propertiesForNameConsumer)); + } + + private void call(String repositoryId, V1Properties properties, BiConsumer propertiesForNameConsumer) { + propertiesForNameConsumer.accept(repositoryId, properties); + } +} diff --git a/scm-webapp/src/main/java/sonia/scm/update/properties/V1Properties.java b/scm-core/src/main/java/sonia/scm/update/V1Properties.java similarity index 71% rename from scm-webapp/src/main/java/sonia/scm/update/properties/V1Properties.java rename to scm-core/src/main/java/sonia/scm/update/V1Properties.java index 156fdae73f..5776fc91c7 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/properties/V1Properties.java +++ b/scm-core/src/main/java/sonia/scm/update/V1Properties.java @@ -1,4 +1,4 @@ -package sonia.scm.update.properties; +package sonia.scm.update; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -14,7 +14,7 @@ public class V1Properties { @XmlElement(name = "item") private List properties; - public List getProperties() { - return unmodifiableList(properties); + public String get(String key) { + return properties.stream().filter(p -> key.equals(p.getKey())).map(V1Property::getValue).findFirst().orElse(null); } } diff --git a/scm-webapp/src/main/java/sonia/scm/update/properties/V1Property.java b/scm-core/src/main/java/sonia/scm/update/V1Property.java similarity index 96% rename from scm-webapp/src/main/java/sonia/scm/update/properties/V1Property.java rename to scm-core/src/main/java/sonia/scm/update/V1Property.java index 86f16a085a..c3dcf6a590 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/properties/V1Property.java +++ b/scm-core/src/main/java/sonia/scm/update/V1Property.java @@ -1,4 +1,4 @@ -package sonia.scm.update.properties; +package sonia.scm.update; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; diff --git a/scm-core/src/main/java/sonia/scm/update/V1PropertyDAO.java b/scm-core/src/main/java/sonia/scm/update/V1PropertyDAO.java new file mode 100644 index 0000000000..b8cac19edf --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/update/V1PropertyDAO.java @@ -0,0 +1,5 @@ +package sonia.scm.update; + +public interface V1PropertyDAO { + V1PropertyReader.Instance getProperties(V1PropertyReader reader); +} diff --git a/scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java b/scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java new file mode 100644 index 0000000000..2d20a9aeed --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/update/V1PropertyReader.java @@ -0,0 +1,15 @@ +package sonia.scm.update; + +import java.util.Map; +import java.util.function.BiConsumer; + +public interface V1PropertyReader { + + String getStoreName(); + + Instance createInstance(Map all); + + interface Instance { + void forEachEntry(BiConsumer propertiesForNameConsumer); + } +} diff --git a/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java b/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java index d31179c1c2..967aa8fb1c 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java +++ b/scm-dao-xml/src/main/java/sonia/scm/store/FileBasedStoreFactory.java @@ -35,7 +35,6 @@ package sonia.scm.store; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.SCMContextProvider; -import sonia.scm.repository.Repository; import sonia.scm.repository.RepositoryLocationResolver; import sonia.scm.util.IOUtil; @@ -66,18 +65,18 @@ public abstract class FileBasedStoreFactory { } protected File getStoreLocation(StoreParameters storeParameters) { - return getStoreLocation(storeParameters.getName(), null, storeParameters.getRepository()); + return getStoreLocation(storeParameters.getName(), null, storeParameters.getRepositoryId()); } protected File getStoreLocation(TypedStoreParameters storeParameters) { - return getStoreLocation(storeParameters.getName(), storeParameters.getType(), storeParameters.getRepository()); + return getStoreLocation(storeParameters.getName(), storeParameters.getType(), storeParameters.getRepositoryId()); } - protected File getStoreLocation(String name, Class type, Repository repository) { + protected File getStoreLocation(String name, Class type, String repositoryId) { File storeDirectory; - if (repository != null) { - LOG.debug("create store with type: {}, name: {} and repository: {}", type, name, repository.getNamespaceAndName()); - storeDirectory = this.getStoreDirectory(store, repository); + if (repositoryId != null) { + LOG.debug("create store with type: {}, name: {} and repository id: {}", type, name, repositoryId); + storeDirectory = this.getStoreDirectory(store, repositoryId); } else { LOG.debug("create store with type: {} and name: {} ", type, name); storeDirectory = this.getStoreDirectory(store); @@ -89,11 +88,11 @@ public abstract class FileBasedStoreFactory { /** * Get the store directory of a specific repository * @param store the type of the store - * @param repository the repo + * @param repositoryId the id of the repossitory * @return the store directory of a specific repository */ - private File getStoreDirectory(Store store, Repository repository) { - return new File(repositoryLocationResolver.forClass(Path.class).getLocation(repository.getId()).toFile(), store.getRepositoryStoreDirectory()); + private File getStoreDirectory(Store store, String repositoryId) { + return new File(repositoryLocationResolver.forClass(Path.class).getLocation(repositoryId).toFile(), store.getRepositoryStoreDirectory()); } /** diff --git a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStoreFactory.java b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStoreFactory.java index 96403140ef..f66bccb7ba 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStoreFactory.java +++ b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationEntryStoreFactory.java @@ -59,7 +59,9 @@ public class JAXBConfigurationEntryStoreFactory extends FileBasedStoreFactory @Override public ConfigurationEntryStore getStore(TypedStoreParameters storeParameters) { - return new JAXBConfigurationEntryStore<>(getStoreLocation(storeParameters.getName().concat(StoreConstants.FILE_EXTENSION), storeParameters.getType(), storeParameters.getRepository()), keyGenerator, storeParameters.getType()); + return new JAXBConfigurationEntryStore<>( + getStoreLocation(storeParameters.getName().concat(StoreConstants.FILE_EXTENSION), storeParameters.getType(), storeParameters.getRepositoryId()), + keyGenerator, + storeParameters.getType()); } - } diff --git a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationStoreFactory.java b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationStoreFactory.java index bb68ab93dc..e66394cb5d 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationStoreFactory.java +++ b/scm-dao-xml/src/main/java/sonia/scm/store/JAXBConfigurationStoreFactory.java @@ -55,6 +55,10 @@ public class JAXBConfigurationStoreFactory extends FileBasedStoreFactory impleme @Override public JAXBConfigurationStore getStore(TypedStoreParameters storeParameters) { - return new JAXBConfigurationStore<>(storeParameters.getType(), getStoreLocation(storeParameters.getName().concat(StoreConstants.FILE_EXTENSION), storeParameters.getType(), storeParameters.getRepository())); + return new JAXBConfigurationStore<>( + storeParameters.getType(), + getStoreLocation(storeParameters.getName().concat(StoreConstants.FILE_EXTENSION), + storeParameters.getType(), + storeParameters.getRepositoryId())); } } diff --git a/scm-dao-xml/src/main/java/sonia/scm/update/xml/XmlV1PropertyDAO.java b/scm-dao-xml/src/main/java/sonia/scm/update/xml/XmlV1PropertyDAO.java new file mode 100644 index 0000000000..5bdee89c68 --- /dev/null +++ b/scm-dao-xml/src/main/java/sonia/scm/update/xml/XmlV1PropertyDAO.java @@ -0,0 +1,30 @@ +package sonia.scm.update.xml; + +import sonia.scm.store.ConfigurationEntryStore; +import sonia.scm.store.ConfigurationEntryStoreFactory; +import sonia.scm.update.V1Properties; +import sonia.scm.update.V1PropertyDAO; +import sonia.scm.update.V1PropertyReader; + +import javax.inject.Inject; +import java.util.Map; + +public class XmlV1PropertyDAO implements V1PropertyDAO { + + private final ConfigurationEntryStoreFactory configurationEntryStoreFactory; + + @Inject + public XmlV1PropertyDAO(ConfigurationEntryStoreFactory configurationEntryStoreFactory) { + this.configurationEntryStoreFactory = configurationEntryStoreFactory; + } + + @Override + public V1PropertyReader.Instance getProperties(V1PropertyReader reader) { + ConfigurationEntryStore propertyStore = configurationEntryStoreFactory + .withType(V1Properties.class) + .withName(reader.getStoreName()) + .build(); + Map all = propertyStore.getAll(); + return reader.createInstance(all); + } +} diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java index 376d7cdf7a..fc5c9c9fc2 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitIncomingCommandTest.java @@ -40,6 +40,7 @@ import org.junit.Ignore; import org.junit.Test; import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.repository.ChangesetPagingResult; +import sonia.scm.repository.Repository; import sonia.scm.store.InMemoryConfigurationStoreFactory; import java.io.IOException; @@ -189,7 +190,7 @@ public class GitIncomingCommandTest */ private GitIncomingCommand createCommand() { - return new GitIncomingCommand(handler, new GitContext(incomingDirectory, null, new GitRepositoryConfigStoreProvider(new InMemoryConfigurationStoreFactory())), - incomingRepository); + return new GitIncomingCommand(handler, new GitContext(incomingDirectory, incomingRepository, new GitRepositoryConfigStoreProvider(new InMemoryConfigurationStoreFactory())), + this.incomingRepository); } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java index 2525a6fa38..158973e710 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/repository/spi/GitOutgoingCommandTest.java @@ -40,6 +40,7 @@ import org.eclipse.jgit.revwalk.RevCommit; import org.junit.Test; import sonia.scm.api.v2.resources.GitRepositoryConfigStoreProvider; import sonia.scm.repository.ChangesetPagingResult; +import sonia.scm.repository.Repository; import sonia.scm.store.InMemoryConfigurationStoreFactory; import java.io.IOException; @@ -160,7 +161,7 @@ public class GitOutgoingCommandTest extends AbstractRemoteCommandTestBase */ private GitOutgoingCommand createCommand() { - return new GitOutgoingCommand(handler, new GitContext(outgoingDirectory, null, new GitRepositoryConfigStoreProvider(new InMemoryConfigurationStoreFactory())), + return new GitOutgoingCommand(handler, new GitContext(outgoingDirectory, outgoingRepository, new GitRepositoryConfigStoreProvider(new InMemoryConfigurationStoreFactory())), outgoingRepository); } } diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java index 93eadf8935..9af1125696 100644 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java +++ b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsBlobStoreFactoryTest.java @@ -71,7 +71,7 @@ public class LfsBlobStoreFactoryTest { // the return value (and should not be part of this test) verify(blobStoreFactory).getStore(argThat(blobStoreParameters -> { assertThat(blobStoreParameters.getName()).isEqualTo("the-id-git-lfs"); - assertThat(blobStoreParameters.getRepository()).isEqualTo(repository); + assertThat(blobStoreParameters.getRepositoryId()).isEqualTo("the-id"); return true; })); diff --git a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapModule.java b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapModule.java index 57c05b9d21..29f5770378 100644 --- a/scm-webapp/src/main/java/sonia/scm/boot/BootstrapModule.java +++ b/scm-webapp/src/main/java/sonia/scm/boot/BootstrapModule.java @@ -24,6 +24,8 @@ import sonia.scm.store.FileBlobStoreFactory; import sonia.scm.store.JAXBConfigurationEntryStoreFactory; import sonia.scm.store.JAXBConfigurationStoreFactory; import sonia.scm.store.JAXBDataStoreFactory; +import sonia.scm.update.V1PropertyDAO; +import sonia.scm.update.xml.XmlV1PropertyDAO; public class BootstrapModule extends AbstractModule { @@ -60,6 +62,7 @@ public class BootstrapModule extends AbstractModule { bind(DataStoreFactory.class, JAXBDataStoreFactory.class); bind(BlobStoreFactory.class, FileBlobStoreFactory.class); bind(PluginLoader.class).toInstance(pluginLoader); + bind(V1PropertyDAO.class, XmlV1PropertyDAO.class); } private void bind(Class clazz, Class defaultImplementation) { diff --git a/scm-webapp/src/main/java/sonia/scm/update/CoreUpdateStep.java b/scm-webapp/src/main/java/sonia/scm/update/CoreUpdateStep.java new file mode 100644 index 0000000000..c0468eef39 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/update/CoreUpdateStep.java @@ -0,0 +1,6 @@ +package sonia.scm.update; + +import sonia.scm.migration.UpdateStep; + +public interface CoreUpdateStep extends UpdateStep { +} diff --git a/scm-webapp/src/main/java/sonia/scm/update/UpdateEngine.java b/scm-webapp/src/main/java/sonia/scm/update/UpdateEngine.java index 910d9ee054..a3c0ffd875 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/UpdateEngine.java +++ b/scm-webapp/src/main/java/sonia/scm/update/UpdateEngine.java @@ -32,12 +32,20 @@ public class UpdateEngine { private List sortSteps(Set steps) { LOG.trace("sorting available update steps:"); List sortedSteps = steps.stream() - .sorted(Comparator.comparing(UpdateStep::getTargetVersion).reversed()) + .sorted( + Comparator + .comparing(UpdateStep::getTargetVersion) + .thenComparing(this::isCoreUpdateStep) + .reversed()) .collect(toList()); sortedSteps.forEach(step -> LOG.trace("{} for version {}", step.getAffectedDataType(), step.getTargetVersion())); return sortedSteps; } + private boolean isCoreUpdateStep(UpdateStep updateStep) { + return updateStep instanceof CoreUpdateStep; + } + public void update() { steps .stream() diff --git a/scm-webapp/src/main/java/sonia/scm/update/group/XmlGroupV1UpdateStep.java b/scm-webapp/src/main/java/sonia/scm/update/group/XmlGroupV1UpdateStep.java index 7130ead4a9..aa853a8b55 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/group/XmlGroupV1UpdateStep.java +++ b/scm-webapp/src/main/java/sonia/scm/update/group/XmlGroupV1UpdateStep.java @@ -11,7 +11,7 @@ import sonia.scm.plugin.Extension; import sonia.scm.store.ConfigurationEntryStore; import sonia.scm.store.ConfigurationEntryStoreFactory; import sonia.scm.store.StoreConstants; -import sonia.scm.update.properties.V1Properties; +import sonia.scm.update.V1Properties; import sonia.scm.version.Version; import javax.inject.Inject; diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/V1Repository.java b/scm-webapp/src/main/java/sonia/scm/update/repository/V1Repository.java index 256e2ad397..4ce823bd33 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/repository/V1Repository.java +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/V1Repository.java @@ -1,6 +1,6 @@ package sonia.scm.update.repository; -import sonia.scm.update.properties.V1Properties; +import sonia.scm.update.V1Properties; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; 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 ad20b59529..6882d7b1ca 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 @@ -13,7 +13,9 @@ import sonia.scm.repository.xml.XmlRepositoryDAO; import sonia.scm.store.ConfigurationEntryStore; import sonia.scm.store.ConfigurationEntryStoreFactory; import sonia.scm.store.StoreConstants; -import sonia.scm.update.properties.V1Properties; +import sonia.scm.update.CoreUpdateStep; +import sonia.scm.update.V1Properties; +import sonia.scm.update.RepositoryV1PropertyReader; import sonia.scm.version.Version; import javax.inject.Inject; @@ -56,7 +58,7 @@ import static sonia.scm.version.Version.parse; * */ @Extension -public class XmlRepositoryV1UpdateStep implements UpdateStep { +public class XmlRepositoryV1UpdateStep implements CoreUpdateStep { private static Logger LOG = LoggerFactory.getLogger(XmlRepositoryV1UpdateStep.class); @@ -80,7 +82,7 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep { this.injector = injector; this.propertyStore = configurationEntryStoreFactory .withType(V1Properties.class) - .withName("repository-properties-v1") + .withName(new RepositoryV1PropertyReader().getStoreName()) .build(); } diff --git a/scm-webapp/src/main/java/sonia/scm/update/user/XmlUserV1UpdateStep.java b/scm-webapp/src/main/java/sonia/scm/update/user/XmlUserV1UpdateStep.java index 24d96d3654..70bdb55059 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/user/XmlUserV1UpdateStep.java +++ b/scm-webapp/src/main/java/sonia/scm/update/user/XmlUserV1UpdateStep.java @@ -10,7 +10,7 @@ import sonia.scm.security.AssignedPermission; import sonia.scm.store.ConfigurationEntryStore; import sonia.scm.store.ConfigurationEntryStoreFactory; import sonia.scm.store.StoreConstants; -import sonia.scm.update.properties.V1Properties; +import sonia.scm.update.V1Properties; import sonia.scm.user.User; import sonia.scm.user.xml.XmlUserDAO; import sonia.scm.version.Version; diff --git a/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java b/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java index 746eabc2ea..f94d7cd27a 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/UpdateEngineTest.java @@ -32,7 +32,21 @@ class UpdateEngineTest { updateEngine.update(); assertThat(processedUpdates) - .containsExactly("1.1.0", "1.1.1", "1.2.0"); + .containsExactly("test:1.1.0", "test:1.1.1", "test:1.2.0"); + } + + @Test + void shouldProcessCoreStepsBeforeOther() { + LinkedHashSet updateSteps = new LinkedHashSet<>(); + + updateSteps.add(new FixedVersionUpdateStep("test", "1.2.0")); + updateSteps.add(new CoreFixedVersionUpdateStep("core", "1.2.0")); + + UpdateEngine updateEngine = new UpdateEngine(updateSteps, storeFactory); + updateEngine.update(); + + assertThat(processedUpdates) + .containsExactly("core:1.2.0", "test:1.2.0"); } @Test @@ -67,7 +81,7 @@ class UpdateEngineTest { updateEngine = new UpdateEngine(updateSteps, storeFactory); updateEngine.update(); - assertThat(processedUpdates).containsExactly("1.1.1"); + assertThat(processedUpdates).containsExactly("other:1.1.1"); } class FixedVersionUpdateStep implements UpdateStep { @@ -91,7 +105,13 @@ class UpdateEngineTest { @Override public void doUpdate() { - processedUpdates.add(version); + processedUpdates.add(type + ":" + version); + } + } + + class CoreFixedVersionUpdateStep extends FixedVersionUpdateStep implements CoreUpdateStep { + CoreFixedVersionUpdateStep(String type, String version) { + super(type, version); } } } diff --git a/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java index 415bd508eb..9d550e20b1 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/group/XmlGroupV1UpdateStepTest.java @@ -14,8 +14,8 @@ import sonia.scm.group.xml.XmlGroupDAO; import sonia.scm.store.ConfigurationEntryStore; import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; import sonia.scm.update.UpdateStepTestUtil; -import sonia.scm.update.properties.V1Properties; -import sonia.scm.update.properties.V1Property; +import sonia.scm.update.V1Properties; +import sonia.scm.update.V1Property; import javax.xml.bind.JAXBException; import java.io.IOException; @@ -89,13 +89,10 @@ class XmlGroupV1UpdateStepTest { @Test void shouldExtractProperties() throws JAXBException { updateStep.doUpdate(); - ConfigurationEntryStore propertiesStore = storeFactory.get("group-properties-v1"); - assertThat(propertiesStore.get("normals")) - .isNotNull() - .extracting(V1Properties::getProperties) - .first() - .asList() - .contains(new V1Property("mostly", "humans")); + ConfigurationEntryStore propertiesStore = storeFactory.get("group-properties-v1"); + V1Properties properties = propertiesStore.get("normals"); + assertThat(properties).isNotNull(); + assertThat(properties.get("mostly")).isEqualTo("humans"); } } diff --git a/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java index ec26db00a2..ce3a4a391e 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/user/XmlUserV1UpdateStepTest.java @@ -13,8 +13,8 @@ import sonia.scm.security.AssignedPermission; import sonia.scm.store.ConfigurationEntryStore; import sonia.scm.store.InMemoryConfigurationEntryStoreFactory; import sonia.scm.update.UpdateStepTestUtil; -import sonia.scm.update.properties.V1Properties; -import sonia.scm.update.properties.V1Property; +import sonia.scm.update.V1Properties; +import sonia.scm.update.V1Property; import sonia.scm.user.User; import sonia.scm.user.xml.XmlUserDAO; @@ -105,14 +105,10 @@ class XmlUserV1UpdateStepTest { void shouldExtractProperties() throws JAXBException { updateStep.doUpdate(); ConfigurationEntryStore propertiesStore = storeFactory.get("user-properties-v1"); - assertThat(propertiesStore.get("dent")) - .isNotNull() - .extracting(V1Properties::getProperties) - .first() - .asList() - .contains( - new V1Property("born.on", "earth"), - new V1Property("last.seen", "end of the universe")); + V1Properties properties = propertiesStore.get("dent"); + assertThat(properties).isNotNull(); + assertThat(properties.get("born.on")).isEqualTo("earth"); + assertThat(properties.get("last.seen")).isEqualTo("end of the universe"); } }