Bootstrap migration strategies

This commit is contained in:
René Pfeuffer
2019-05-22 14:28:53 +02:00
parent 3d28f800be
commit 1674bc2e7d
11 changed files with 335 additions and 10 deletions

View File

@@ -0,0 +1,21 @@
package sonia.scm.repository.update;
import sonia.scm.SCMContextProvider;
import javax.inject.Inject;
import java.nio.file.Path;
class CopyMigrationStrategy implements MigrationStrategy.Instance {
private final SCMContextProvider contextProvider;
@Inject
public CopyMigrationStrategy(SCMContextProvider contextProvider) {
this.contextProvider = contextProvider;
}
@Override
public Path migrate(String id, String name, String type) {
return null;
}
}

View File

@@ -0,0 +1,21 @@
package sonia.scm.repository.update;
import sonia.scm.SCMContextProvider;
import javax.inject.Inject;
import java.nio.file.Path;
class InlineMigrationStrategy implements MigrationStrategy.Instance {
private final SCMContextProvider contextProvider;
@Inject
public InlineMigrationStrategy(SCMContextProvider contextProvider) {
this.contextProvider = contextProvider;
}
@Override
public Path migrate(String id, String name, String type) {
return null;
}
}

View File

@@ -0,0 +1,26 @@
package sonia.scm.repository.update;
import com.google.inject.Injector;
import java.nio.file.Path;
enum MigrationStrategy {
COPY(CopyMigrationStrategy.class),
MOVE(MoveMigrationStrategy.class),
INLINE(InlineMigrationStrategy.class);
private Class<? extends Instance> implementationClass;
MigrationStrategy(Class<? extends Instance> implementationClass) {
this.implementationClass = implementationClass;
}
Instance from(Injector injector) {
return injector.getInstance(implementationClass);
}
interface Instance {
Path migrate(String id, String name, String type);
}
}

View File

@@ -0,0 +1,28 @@
package sonia.scm.repository.update;
import sonia.scm.store.ConfigurationStore;
import sonia.scm.store.ConfigurationStoreFactory;
import javax.inject.Inject;
import java.util.Optional;
public class MigrationStrategyDao {
private final RepositoryMigrationPlan plan;
private final ConfigurationStore<RepositoryMigrationPlan> store;
@Inject
public MigrationStrategyDao(ConfigurationStoreFactory storeFactory) {
store = storeFactory.withType(RepositoryMigrationPlan.class).withName("migration-plan").build();
this.plan = store.getOptional().orElse(new RepositoryMigrationPlan());
}
public Optional<MigrationStrategy> get(String id) {
return plan.get(id);
}
public void set(String repositoryId, MigrationStrategy strategy) {
plan.set(repositoryId, strategy);
store.set(plan);
}
}

View File

@@ -0,0 +1,21 @@
package sonia.scm.repository.update;
import sonia.scm.SCMContextProvider;
import javax.inject.Inject;
import java.nio.file.Path;
class MoveMigrationStrategy implements MigrationStrategy.Instance {
private final SCMContextProvider contextProvider;
@Inject
public MoveMigrationStrategy(SCMContextProvider contextProvider) {
this.contextProvider = contextProvider;
}
@Override
public Path migrate(String id, String name, String type) {
return null;
}
}

View File

@@ -0,0 +1,69 @@
package sonia.scm.repository.update;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static java.util.Arrays.asList;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "repository-migration")
class RepositoryMigrationPlan {
private List<RepositoryEntry> entries;
RepositoryMigrationPlan() {
this(new RepositoryEntry[0]);
}
RepositoryMigrationPlan(RepositoryEntry... entries) {
this.entries = new ArrayList<>(asList(entries));
}
Optional<MigrationStrategy> get(String repositoryId) {
return findEntry(repositoryId)
.map(RepositoryEntry::getDataMigrationStrategy);
}
public void set(String repositoryId, MigrationStrategy strategy) {
Optional<RepositoryEntry> entry = findEntry(repositoryId);
if (entry.isPresent()) {
entry.get().setStrategy(strategy);
} else {
entries.add(new RepositoryEntry(repositoryId, strategy));
}
}
private Optional<RepositoryEntry> findEntry(String repositoryId) {
return entries.stream()
.filter(repositoryEntry -> repositoryId.equals(repositoryEntry.repositoryId))
.findFirst();
}
@XmlRootElement(name = "entries")
@XmlAccessorType(XmlAccessType.FIELD)
static class RepositoryEntry {
private String repositoryId;
private MigrationStrategy dataMigrationStrategy;
RepositoryEntry() {
}
RepositoryEntry(String repositoryId, MigrationStrategy dataMigrationStrategy) {
this.repositoryId = repositoryId;
this.dataMigrationStrategy = dataMigrationStrategy;
}
public MigrationStrategy getDataMigrationStrategy() {
return dataMigrationStrategy;
}
private void setStrategy(MigrationStrategy strategy) {
this.dataMigrationStrategy = strategy;
}
}
}

View File

@@ -1,5 +1,8 @@
package sonia.scm.repository.update;
import com.google.inject.Injector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.migration.UpdateStep;
import sonia.scm.plugin.Extension;
@@ -17,6 +20,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -27,13 +31,19 @@ import static sonia.scm.version.Version.parse;
@Extension
public class XmlRepositoryV1UpdateStep implements UpdateStep {
private static Logger LOG = LoggerFactory.getLogger(XmlRepositoryV1UpdateStep.class);
private final SCMContextProvider contextProvider;
private final XmlRepositoryDAO dao;
private final XmlRepositoryDAO repositoryDao;
private final MigrationStrategyDao migrationStrategyDao;
private final Injector injector;
@Inject
public XmlRepositoryV1UpdateStep(SCMContextProvider contextProvider, XmlRepositoryDAO dao) {
public XmlRepositoryV1UpdateStep(SCMContextProvider contextProvider, XmlRepositoryDAO repositoryDao, MigrationStrategyDao migrationStrategyDao, Injector injector) {
this.contextProvider = contextProvider;
this.dao = dao;
this.repositoryDao = repositoryDao;
this.migrationStrategyDao = migrationStrategyDao;
this.injector = injector;
}
@Override
@@ -57,6 +67,7 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep {
}
private void update(V1Repository v1Repository) {
Path destination = handleDataDirectory(v1Repository);
Repository repository = new Repository(
v1Repository.id,
v1Repository.type,
@@ -65,7 +76,14 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep {
v1Repository.contact,
v1Repository.description,
createPermissions(v1Repository));
dao.add(repository);
repositoryDao.add(repository);
}
private Path handleDataDirectory(V1Repository v1Repository) {
MigrationStrategy dataMigrationStrategy =
migrationStrategyDao.get(v1Repository.id)
.orElseThrow(() -> new IllegalStateException("no strategy found for repository with id " + v1Repository.id + " and name " + v1Repository.name));
return dataMigrationStrategy.from(injector).migrate(v1Repository.id, v1Repository.name, v1Repository.type);
}
private RepositoryPermission[] createPermissions(V1Repository v1Repository) {