mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-18 03:01:05 +01:00
Cleanup
- 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:
@@ -13,8 +13,9 @@ public abstract class RepositoryLocationResolver {
|
|||||||
return create(type);
|
return create(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
|
||||||
public interface RepositoryLocationResolverInstance<T> {
|
public interface RepositoryLocationResolverInstance<T> {
|
||||||
T getLocation(String repositoryId);
|
T getLocation(String repositoryId);
|
||||||
|
|
||||||
|
void setLocation(String repositoryId, T location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import sonia.scm.repository.InternalRepositoryException;
|
|||||||
import sonia.scm.store.StoreConstants;
|
import sonia.scm.store.StoreConstants;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -28,6 +29,7 @@ import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
|||||||
*
|
*
|
||||||
* @since 2.0.0
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
|
@Singleton
|
||||||
public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocationResolver<Path> {
|
public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocationResolver<Path> {
|
||||||
|
|
||||||
public static final String STORE_NAME = "repository-paths";
|
public static final String STORE_NAME = "repository-paths";
|
||||||
@@ -64,19 +66,26 @@ public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocation
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> RepositoryLocationResolverInstance<T> create(Class<T> type) {
|
protected <T> RepositoryLocationResolverInstance<T> create(Class<T> type) {
|
||||||
return repositoryId -> {
|
return new RepositoryLocationResolverInstance<T>() {
|
||||||
if (pathById.containsKey(repositoryId)) {
|
@Override
|
||||||
return (T) contextProvider.resolve(pathById.get(repositoryId));
|
public T getLocation(String repositoryId) {
|
||||||
} else {
|
if (pathById.containsKey(repositoryId)) {
|
||||||
return (T) create(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 create(String repositoryId) {
|
||||||
Path path = initialRepositoryLocationResolver.getPath(repositoryId);
|
Path path = initialRepositoryLocationResolver.getPath(repositoryId);
|
||||||
pathById.put(repositoryId, path);
|
setLocation(repositoryId, path);
|
||||||
writePathDatabase();
|
|
||||||
Path resolvedPath = contextProvider.resolve(path);
|
Path resolvedPath = contextProvider.resolve(path);
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(resolvedPath);
|
Files.createDirectories(resolvedPath);
|
||||||
@@ -138,4 +147,9 @@ public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocation
|
|||||||
.resolve(StoreConstants.CONFIG_DIRECTORY_NAME)
|
.resolve(StoreConstants.CONFIG_DIRECTORY_NAME)
|
||||||
.resolve(STORE_NAME.concat(StoreConstants.FILE_EXTENSION));
|
.resolve(STORE_NAME.concat(StoreConstants.FILE_EXTENSION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setLocation(String repositoryId, Path repositoryBasePath) {
|
||||||
|
pathById.put(repositoryId, repositoryBasePath);
|
||||||
|
writePathDatabase();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import sonia.scm.io.DefaultFileSystem;
|
|||||||
import sonia.scm.io.FileSystem;
|
import sonia.scm.io.FileSystem;
|
||||||
import sonia.scm.repository.NamespaceAndName;
|
import sonia.scm.repository.NamespaceAndName;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
import sonia.scm.repository.RepositoryPermission;
|
import sonia.scm.repository.RepositoryPermission;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -56,7 +57,18 @@ class XmlRepositoryDAOTest {
|
|||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void createDAO(@TempDirectory.TempDir Path basePath) {
|
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.create(anyString())).thenAnswer(invocation -> createMockedRepoPath(basePath, invocation));
|
||||||
when(locationResolver.remove(anyString())).thenAnswer(invocation -> basePath.resolve(invocation.getArgument(0).toString()));
|
when(locationResolver.remove(anyString())).thenAnswer(invocation -> basePath.resolve(invocation.getArgument(0).toString()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package sonia.scm;
|
package sonia.scm;
|
||||||
|
|
||||||
import sonia.scm.repository.BasicRepositoryLocationResolver;
|
import sonia.scm.repository.BasicRepositoryLocationResolver;
|
||||||
import sonia.scm.repository.RepositoryLocationResolver;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
@@ -16,6 +15,16 @@ public class TempDirRepositoryLocationResolver extends BasicRepositoryLocationRe
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> RepositoryLocationResolverInstance<T> create(Class<T> type) {
|
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");
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
package sonia.scm.update;
|
package sonia.scm.update;
|
||||||
|
|
||||||
import com.google.inject.servlet.ServletModule;
|
import com.google.inject.servlet.ServletModule;
|
||||||
import sonia.scm.update.repository.XmlRepositoryV1UpdateStep;
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
class MigrationWizardModule extends ServletModule {
|
class MigrationWizardModule extends ServletModule {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(MigrationWizardModule.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configureServlets() {
|
protected void configureServlets() {
|
||||||
|
LOG.info("==========================================================");
|
||||||
|
LOG.info("= =");
|
||||||
|
LOG.info("= STARTING MIGRATION SERVLET =");
|
||||||
|
LOG.info("= =");
|
||||||
|
LOG.info("==========================================================");
|
||||||
serve("/*").with(MigrationWizardServlet.class);
|
serve("/*").with(MigrationWizardServlet.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package sonia.scm.update.repository;
|
package sonia.scm.update.repository;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import sonia.scm.SCMContextProvider;
|
import sonia.scm.SCMContextProvider;
|
||||||
import sonia.scm.repository.RepositoryDirectoryHandler;
|
import sonia.scm.repository.RepositoryDirectoryHandler;
|
||||||
import sonia.scm.repository.RepositoryLocationResolver;
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
@@ -10,6 +12,8 @@ import java.nio.file.Path;
|
|||||||
|
|
||||||
class CopyMigrationStrategy extends BaseMigrationStrategy {
|
class CopyMigrationStrategy extends BaseMigrationStrategy {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(CopyMigrationStrategy.class);
|
||||||
|
|
||||||
private final RepositoryLocationResolver locationResolver;
|
private final RepositoryLocationResolver locationResolver;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -24,6 +28,7 @@ class CopyMigrationStrategy extends BaseMigrationStrategy {
|
|||||||
Path targetDataPath = repositoryBasePath
|
Path targetDataPath = repositoryBasePath
|
||||||
.resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY);
|
.resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY);
|
||||||
Path sourceDataPath = getSourceDataPath(name, type);
|
Path sourceDataPath = getSourceDataPath(name, type);
|
||||||
|
LOG.info("copying repository data from {} to {}", sourceDataPath, targetDataPath);
|
||||||
copyData(sourceDataPath, targetDataPath);
|
copyData(sourceDataPath, targetDataPath);
|
||||||
return repositoryBasePath;
|
return repositoryBasePath;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package sonia.scm.update.repository;
|
package sonia.scm.update.repository;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import sonia.scm.SCMContextProvider;
|
import sonia.scm.SCMContextProvider;
|
||||||
import sonia.scm.repository.RepositoryDirectoryHandler;
|
import sonia.scm.repository.RepositoryDirectoryHandler;
|
||||||
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@@ -9,16 +12,23 @@ import java.nio.file.Path;
|
|||||||
|
|
||||||
class InlineMigrationStrategy extends BaseMigrationStrategy {
|
class InlineMigrationStrategy extends BaseMigrationStrategy {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(InlineMigrationStrategy.class);
|
||||||
|
|
||||||
|
private final RepositoryLocationResolver locationResolver;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public InlineMigrationStrategy(SCMContextProvider contextProvider) {
|
public InlineMigrationStrategy(SCMContextProvider contextProvider, RepositoryLocationResolver locationResolver) {
|
||||||
super(contextProvider);
|
super(contextProvider);
|
||||||
|
this.locationResolver = locationResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Path migrate(String id, String name, String type) {
|
public Path migrate(String id, String name, String type) {
|
||||||
Path repositoryBasePath = getSourceDataPath(name, type);
|
Path repositoryBasePath = getSourceDataPath(name, type);
|
||||||
|
locationResolver.forClass(Path.class).setLocation(id, repositoryBasePath);
|
||||||
Path targetDataPath = repositoryBasePath
|
Path targetDataPath = repositoryBasePath
|
||||||
.resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY);
|
.resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY);
|
||||||
|
LOG.info("moving repository data from {} to {}", repositoryBasePath, targetDataPath);
|
||||||
moveData(repositoryBasePath, targetDataPath);
|
moveData(repositoryBasePath, targetDataPath);
|
||||||
return repositoryBasePath;
|
return repositoryBasePath;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class MoveMigrationStrategy extends BaseMigrationStrategy {
|
|||||||
Path targetDataPath = repositoryBasePath
|
Path targetDataPath = repositoryBasePath
|
||||||
.resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY);
|
.resolve(RepositoryDirectoryHandler.REPOSITORIES_NATIVE_DIRECTORY);
|
||||||
Path sourceDataPath = getSourceDataPath(name, type);
|
Path sourceDataPath = getSourceDataPath(name, type);
|
||||||
|
LOG.info("moving repository data from {} to {}", sourceDataPath, targetDataPath);
|
||||||
moveData(sourceDataPath, targetDataPath);
|
moveData(sourceDataPath, targetDataPath);
|
||||||
deleteOldDataDir(getTypeDependentPath(type), name);
|
deleteOldDataDir(getTypeDependentPath(type), name);
|
||||||
return repositoryBasePath;
|
return repositoryBasePath;
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep {
|
|||||||
|
|
||||||
private Path handleDataDirectory(V1Repository v1Repository) {
|
private Path handleDataDirectory(V1Repository v1Repository) {
|
||||||
MigrationStrategy dataMigrationStrategy = readMigrationStrategy(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);
|
return dataMigrationStrategy.from(injector).migrate(v1Repository.id, v1Repository.name, v1Repository.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,6 +232,10 @@ public class XmlRepositoryV1UpdateStep implements UpdateStep {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
public String getNewNamespace() {
|
public String getNewNamespace() {
|
||||||
String[] nameParts = getNameParts(name);
|
String[] nameParts = getNameParts(name);
|
||||||
return nameParts.length > 1 ? nameParts[0] : type;
|
return nameParts.length > 1 ? nameParts[0] : type;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ You have migrated from SCM-Manager v1 to SCM-Manager v2.
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>original name</th>
|
<th>original name</th>
|
||||||
|
<th>type</th>
|
||||||
<th>new namespace/name</th>
|
<th>new namespace/name</th>
|
||||||
<th>Strategy</th>
|
<th>Strategy</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -19,6 +20,9 @@ You have migrated from SCM-Manager v1 to SCM-Manager v2.
|
|||||||
<td>
|
<td>
|
||||||
{{name}}
|
{{name}}
|
||||||
</td>
|
</td>
|
||||||
|
<td>
|
||||||
|
{{type}}
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{newNamespace}}/{{newName}}
|
{{newNamespace}}/{{newName}}
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ import org.junitpioneer.jupiter.TempDirectory;
|
|||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
import sonia.scm.SCMContextProvider;
|
import sonia.scm.SCMContextProvider;
|
||||||
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
|
import sonia.scm.repository.xml.PathBasedRepositoryLocationResolver;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
@ExtendWith(TempDirectory.class)
|
@ExtendWith(TempDirectory.class)
|
||||||
@@ -20,9 +23,14 @@ class InlineMigrationStrategyTest {
|
|||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
SCMContextProvider contextProvider;
|
SCMContextProvider contextProvider;
|
||||||
|
@Mock
|
||||||
|
PathBasedRepositoryLocationResolver locationResolver;
|
||||||
|
@Mock
|
||||||
|
RepositoryLocationResolver.RepositoryLocationResolverInstance locationResolverInstance;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void mockContextProvider(@TempDirectory.TempDir Path tempDir) {
|
void mockContextProvider(@TempDirectory.TempDir Path tempDir) {
|
||||||
|
when(locationResolver.forClass(Path.class)).thenReturn(locationResolverInstance);
|
||||||
when(contextProvider.getBaseDirectory()).thenReturn(tempDir.toFile());
|
when(contextProvider.getBaseDirectory()).thenReturn(tempDir.toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,13 +41,14 @@ class InlineMigrationStrategyTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldUseExistingDirectory(@TempDirectory.TempDir Path tempDir) {
|
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));
|
assertThat(target).isEqualTo(resolveOldDirectory(tempDir));
|
||||||
|
verify(locationResolverInstance).setLocation("b4f-a9f0-49f7-ad1f-37d3aae1c55f", target);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldMoveDataDirectory(@TempDirectory.TempDir Path tempDir) {
|
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();
|
assertThat(resolveOldDirectory(tempDir).resolve("data")).exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user