- Mark PathBasedRepositoryLocationResolver as singleton so that other
  users will get the same instance and will not overwrite the paths
  set by migration.
- Set path kept by InlineMigrationStrategy in location resolver to
  store the path.
- Add logging
- Add type of repository to migration web page
This commit is contained in:
René Pfeuffer
2019-06-05 08:21:37 +02:00
parent b253cd110d
commit e52518a12b
11 changed files with 93 additions and 17 deletions

View File

@@ -13,8 +13,9 @@ public abstract class RepositoryLocationResolver {
return create(type);
}
@FunctionalInterface
public interface RepositoryLocationResolverInstance<T> {
T getLocation(String repositoryId);
void setLocation(String repositoryId, T location);
}
}

View File

@@ -7,6 +7,7 @@ import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.store.StoreConstants;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -28,6 +29,7 @@ import static sonia.scm.ContextEntry.ContextBuilder.entity;
*
* @since 2.0.0
*/
@Singleton
public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocationResolver<Path> {
public static final String STORE_NAME = "repository-paths";
@@ -64,19 +66,26 @@ public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocation
@Override
protected <T> RepositoryLocationResolverInstance<T> create(Class<T> type) {
return repositoryId -> {
return new RepositoryLocationResolverInstance<T>() {
@Override
public T getLocation(String repositoryId) {
if (pathById.containsKey(repositoryId)) {
return (T) contextProvider.resolve(pathById.get(repositoryId));
} else {
return (T) create(repositoryId);
}
}
@Override
public void setLocation(String repositoryId, T location) {
PathBasedRepositoryLocationResolver.this.setLocation(repositoryId, (Path) location);
}
};
}
Path create(String repositoryId) {
Path path = initialRepositoryLocationResolver.getPath(repositoryId);
pathById.put(repositoryId, path);
writePathDatabase();
setLocation(repositoryId, path);
Path resolvedPath = contextProvider.resolve(path);
try {
Files.createDirectories(resolvedPath);
@@ -138,4 +147,9 @@ public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocation
.resolve(StoreConstants.CONFIG_DIRECTORY_NAME)
.resolve(STORE_NAME.concat(StoreConstants.FILE_EXTENSION));
}
public void setLocation(String repositoryId, Path repositoryBasePath) {
pathById.put(repositoryId, repositoryBasePath);
writePathDatabase();
}
}

View File

@@ -19,6 +19,7 @@ import sonia.scm.io.DefaultFileSystem;
import sonia.scm.io.FileSystem;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.repository.RepositoryPermission;
import java.io.IOException;
@@ -56,7 +57,18 @@ class XmlRepositoryDAOTest {
@BeforeEach
void createDAO(@TempDirectory.TempDir Path basePath) {
when(locationResolver.create(Path.class)).thenReturn(locationResolver::create);
when(locationResolver.create(Path.class)).thenReturn(
new RepositoryLocationResolver.RepositoryLocationResolverInstance<Path>() {
@Override
public Path getLocation(String repositoryId) {
return locationResolver.create(repositoryId);
}
@Override
public void setLocation(String repositoryId, Path location) {
}
}
);
when(locationResolver.create(anyString())).thenAnswer(invocation -> createMockedRepoPath(basePath, invocation));
when(locationResolver.remove(anyString())).thenAnswer(invocation -> basePath.resolve(invocation.getArgument(0).toString()));
}

View File

@@ -1,7 +1,6 @@
package sonia.scm;
import sonia.scm.repository.BasicRepositoryLocationResolver;
import sonia.scm.repository.RepositoryLocationResolver;
import java.io.File;
import java.nio.file.Path;
@@ -16,6 +15,16 @@ public class TempDirRepositoryLocationResolver extends BasicRepositoryLocationRe
@Override
protected <T> RepositoryLocationResolverInstance<T> create(Class<T> type) {
return repositoryId -> (T) tempDirectory.toPath();
return new RepositoryLocationResolverInstance<T>() {
@Override
public T getLocation(String repositoryId) {
return (T) tempDirectory.toPath();
}
@Override
public void setLocation(String repositoryId, T location) {
throw new UnsupportedOperationException("not implemented for tests");
}
};
}
}

View File

@@ -1,14 +1,20 @@
package sonia.scm.update;
import com.google.inject.servlet.ServletModule;
import sonia.scm.update.repository.XmlRepositoryV1UpdateStep;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
class MigrationWizardModule extends ServletModule {
private static final Logger LOG = LoggerFactory.getLogger(MigrationWizardModule.class);
@Override
protected void configureServlets() {
LOG.info("==========================================================");
LOG.info("= =");
LOG.info("= STARTING MIGRATION SERVLET =");
LOG.info("= =");
LOG.info("==========================================================");
serve("/*").with(MigrationWizardServlet.class);
}
}

View File

@@ -1,5 +1,7 @@
package sonia.scm.update.repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryDirectoryHandler;
import sonia.scm.repository.RepositoryLocationResolver;
@@ -10,6 +12,8 @@ import java.nio.file.Path;
class CopyMigrationStrategy extends BaseMigrationStrategy {
private static final Logger LOG = LoggerFactory.getLogger(CopyMigrationStrategy.class);
private final RepositoryLocationResolver locationResolver;
@Inject
@@ -24,6 +28,7 @@ class CopyMigrationStrategy extends BaseMigrationStrategy {
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;
}

View File

@@ -1,7 +1,10 @@
package sonia.scm.update.repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryDirectoryHandler;
import sonia.scm.repository.RepositoryLocationResolver;
import javax.inject.Inject;
import java.nio.file.Files;
@@ -9,16 +12,23 @@ import java.nio.file.Path;
class InlineMigrationStrategy extends BaseMigrationStrategy {
private static final Logger LOG = LoggerFactory.getLogger(InlineMigrationStrategy.class);
private final RepositoryLocationResolver locationResolver;
@Inject
public InlineMigrationStrategy(SCMContextProvider contextProvider) {
public InlineMigrationStrategy(SCMContextProvider contextProvider, RepositoryLocationResolver locationResolver) {
super(contextProvider);
this.locationResolver = locationResolver;
}
@Override
public Path 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;
}

View File

@@ -32,6 +32,7 @@ class MoveMigrationStrategy extends BaseMigrationStrategy {
Path targetDataPath = repositoryBasePath
.resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY);
Path sourceDataPath = getSourceDataPath(name, type);
LOG.info("moving repository data from {} to {}", sourceDataPath, targetDataPath);
moveData(sourceDataPath, targetDataPath);
deleteOldDataDir(getTypeDependentPath(type), name);
return repositoryBasePath;

View File

@@ -157,6 +157,7 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep {
private Path 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);
}
@@ -231,6 +232,10 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep {
return name;
}
public String getType() {
return type;
}
public String getNewNamespace() {
String[] nameParts = getNameParts(name);
return nameParts.length > 1 ? nameParts[0] : type;

View File

@@ -11,6 +11,7 @@ You have migrated from SCM-Manager v1 to SCM-Manager v2.
<table>
<tr>
<th>original name</th>
<th>type</th>
<th>new namespace/name</th>
<th>Strategy</th>
</tr>
@@ -19,6 +20,9 @@ You have migrated from SCM-Manager v1 to SCM-Manager v2.
<td>
{{name}}
</td>
<td>
{{type}}
</td>
<td>
{{newNamespace}}/{{newName}}
</td>

View File

@@ -7,11 +7,14 @@ import org.junitpioneer.jupiter.TempDirectory;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import sonia.scm.SCMContextProvider;
import sonia.scm.repository.RepositoryLocationResolver;
import sonia.scm.repository.xml.PathBasedRepositoryLocationResolver;
import java.io.IOException;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@ExtendWith(TempDirectory.class)
@@ -20,9 +23,14 @@ class InlineMigrationStrategyTest {
@Mock
SCMContextProvider contextProvider;
@Mock
PathBasedRepositoryLocationResolver locationResolver;
@Mock
RepositoryLocationResolver.RepositoryLocationResolverInstance locationResolverInstance;
@BeforeEach
void mockContextProvider(@TempDirectory.TempDir Path tempDir) {
when(locationResolver.forClass(Path.class)).thenReturn(locationResolverInstance);
when(contextProvider.getBaseDirectory()).thenReturn(tempDir.toFile());
}
@@ -33,13 +41,14 @@ class InlineMigrationStrategyTest {
@Test
void shouldUseExistingDirectory(@TempDirectory.TempDir Path tempDir) {
Path target = new InlineMigrationStrategy(contextProvider).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");
assertThat(target).isEqualTo(resolveOldDirectory(tempDir));
verify(locationResolverInstance).setLocation("b4f-a9f0-49f7-ad1f-37d3aae1c55f", target);
}
@Test
void shouldMoveDataDirectory(@TempDirectory.TempDir Path tempDir) {
new InlineMigrationStrategy(contextProvider).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git");
new InlineMigrationStrategy(contextProvider, locationResolver).migrate("b4f-a9f0-49f7-ad1f-37d3aae1c55f", "some/more/directories/than/one", "git");
assertThat(resolveOldDirectory(tempDir).resolve("data")).exists();
}