mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-15 09:46:16 +01:00
Refresh repository dao after repository.xml file was renamed
Without this, the XmlRepositoryDAO will be initialized at a time where there is no repository-paths.xml file. Therefore the dao cannot initialize with the existing repositories whose paths are kept in repositories.xml at that time. In this commit we trigger a refresh after the file was renamed, so that the PathBasedRepositoryLocationResolver can read the moved repository-paths.xml file and all repositories will be found.
This commit is contained in:
@@ -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";
|
||||
@@ -48,7 +50,7 @@ public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocation
|
||||
this(contextProvider, initialRepositoryLocationResolver, Clock.systemUTC());
|
||||
}
|
||||
|
||||
public PathBasedRepositoryLocationResolver(SCMContextProvider contextProvider, InitialRepositoryLocationResolver initialRepositoryLocationResolver, Clock clock) {
|
||||
PathBasedRepositoryLocationResolver(SCMContextProvider contextProvider, InitialRepositoryLocationResolver initialRepositoryLocationResolver, Clock clock) {
|
||||
super(Path.class);
|
||||
this.contextProvider = contextProvider;
|
||||
this.initialRepositoryLocationResolver = initialRepositoryLocationResolver;
|
||||
@@ -138,4 +140,8 @@ public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocation
|
||||
.resolve(StoreConstants.CONFIG_DIRECTORY_NAME)
|
||||
.resolve(STORE_NAME.concat(StoreConstants.FILE_EXTENSION));
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
this.read();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,4 +198,11 @@ public class XmlRepositoryDAO implements RepositoryDAO {
|
||||
public Long getLastModified() {
|
||||
return repositoryLocationResolver.getLastModified();
|
||||
}
|
||||
|
||||
public void refresh() {
|
||||
repositoryLocationResolver.refresh();
|
||||
byNamespaceAndName.clear();
|
||||
byId.clear();
|
||||
init();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junitpioneer.jupiter.TempDirectory;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
@@ -32,7 +30,9 @@ import static java.util.Arrays.asList;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
@@ -47,9 +47,6 @@ class XmlRepositoryDAOTest {
|
||||
@Mock
|
||||
private PathBasedRepositoryLocationResolver locationResolver;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<BiConsumer<String, Path>> forAllCaptor;
|
||||
|
||||
private FileSystem fileSystem = new DefaultFileSystem();
|
||||
|
||||
private XmlRepositoryDAO dao;
|
||||
@@ -268,43 +265,80 @@ class XmlRepositoryDAOTest {
|
||||
|
||||
verify(locationResolver).updateModificationDate();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReadExistingRepositoriesFromPathDatabase(@TempDirectory.TempDir Path basePath) throws IOException {
|
||||
doNothing().when(locationResolver).forAllPaths(forAllCaptor.capture());
|
||||
XmlRepositoryDAO dao = new XmlRepositoryDAO(locationResolver, fileSystem);
|
||||
private String getXmlFileContent(String id) {
|
||||
Path storePath = metadataFile(id);
|
||||
|
||||
Path repositoryPath = basePath.resolve("existing");
|
||||
Files.createDirectories(repositoryPath);
|
||||
URL metadataUrl = Resources.getResource("sonia/scm/store/repositoryDaoMetadata.xml");
|
||||
Files.copy(metadataUrl.openStream(), repositoryPath.resolve("metadata.xml"));
|
||||
assertThat(storePath).isRegularFile();
|
||||
return content(storePath);
|
||||
}
|
||||
|
||||
forAllCaptor.getValue().accept("existing", repositoryPath);
|
||||
private Path metadataFile(String id) {
|
||||
return locationResolver.create(id).resolve("metadata.xml");
|
||||
}
|
||||
|
||||
assertThat(dao.contains(new NamespaceAndName("space", "existing"))).isTrue();
|
||||
}
|
||||
|
||||
private String getXmlFileContent(String id) {
|
||||
Path storePath = metadataFile(id);
|
||||
|
||||
assertThat(storePath).isRegularFile();
|
||||
return content(storePath);
|
||||
}
|
||||
|
||||
private Path metadataFile(String id) {
|
||||
return locationResolver.create(id).resolve("metadata.xml");
|
||||
}
|
||||
|
||||
private String content(Path storePath) {
|
||||
try {
|
||||
return new String(Files.readAllBytes(storePath), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
private String content(Path storePath) {
|
||||
try {
|
||||
return new String(Files.readAllBytes(storePath), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Repository createRepository(String id) {
|
||||
@Nested
|
||||
class WithExistingRepositories {
|
||||
|
||||
private Path repositoryPath;
|
||||
|
||||
@BeforeEach
|
||||
void createMetadataFileForRepository(@TempDirectory.TempDir Path basePath) throws IOException {
|
||||
repositoryPath = basePath.resolve("existing");
|
||||
|
||||
Files.createDirectories(repositoryPath);
|
||||
URL metadataUrl = Resources.getResource("sonia/scm/store/repositoryDaoMetadata.xml");
|
||||
Files.copy(metadataUrl.openStream(), repositoryPath.resolve("metadata.xml"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldReadExistingRepositoriesFromPathDatabase() {
|
||||
// given
|
||||
mockExistingPath();
|
||||
|
||||
// when
|
||||
XmlRepositoryDAO dao = new XmlRepositoryDAO(locationResolver, fileSystem);
|
||||
|
||||
// then
|
||||
assertThat(dao.contains(new NamespaceAndName("space", "existing"))).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRefreshWithExistingRepositoriesFromPathDatabase() {
|
||||
// given
|
||||
doNothing().when(locationResolver).forAllPaths(any());
|
||||
XmlRepositoryDAO dao = new XmlRepositoryDAO(locationResolver, fileSystem);
|
||||
|
||||
mockExistingPath();
|
||||
|
||||
// when
|
||||
dao.refresh();
|
||||
|
||||
// then
|
||||
verify(locationResolver).refresh();
|
||||
assertThat(dao.contains(new NamespaceAndName("space", "existing"))).isTrue();
|
||||
}
|
||||
|
||||
private void mockExistingPath() {
|
||||
doAnswer(
|
||||
invocation -> {
|
||||
((BiConsumer<String, Path>) invocation.getArgument(0)).accept("existing", repositoryPath);
|
||||
return null;
|
||||
}
|
||||
).when(locationResolver).forAllPaths(any());
|
||||
}
|
||||
}
|
||||
|
||||
private Repository createRepository(String id) {
|
||||
return new Repository(id, "xml", "space", id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.migration.UpdateStep;
|
||||
import sonia.scm.plugin.Extension;
|
||||
import sonia.scm.repository.xml.PathBasedRepositoryLocationResolver;
|
||||
import sonia.scm.repository.xml.XmlRepositoryDAO;
|
||||
import sonia.scm.store.StoreConstants;
|
||||
import sonia.scm.version.Version;
|
||||
|
||||
@@ -27,10 +28,12 @@ public class XmlRepositoryFileNameUpdateStep implements UpdateStep {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(XmlRepositoryFileNameUpdateStep.class);
|
||||
|
||||
private final SCMContextProvider contextProvider;
|
||||
private final XmlRepositoryDAO repositoryDAO;
|
||||
|
||||
@Inject
|
||||
public XmlRepositoryFileNameUpdateStep(SCMContextProvider contextProvider) {
|
||||
public XmlRepositoryFileNameUpdateStep(SCMContextProvider contextProvider, XmlRepositoryDAO repositoryDAO) {
|
||||
this.contextProvider = contextProvider;
|
||||
this.repositoryDAO = repositoryDAO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -41,6 +44,7 @@ public class XmlRepositoryFileNameUpdateStep implements UpdateStep {
|
||||
if (Files.exists(oldRepositoriesFile)) {
|
||||
LOG.info("moving old repositories database files to repository-paths file");
|
||||
Files.move(oldRepositoriesFile, newRepositoryPathsFile);
|
||||
repositoryDAO.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junitpioneer.jupiter.TempDirectory;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.repository.xml.PathBasedRepositoryLocationResolver;
|
||||
import sonia.scm.repository.xml.XmlRepositoryDAO;
|
||||
|
||||
import javax.xml.bind.JAXBException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
@@ -16,12 +16,14 @@ import java.nio.file.Path;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(TempDirectory.class)
|
||||
class XmlRepositoryFileNameUpdateStepTest {
|
||||
|
||||
SCMContextProvider contextProvider = mock(SCMContextProvider.class);
|
||||
XmlRepositoryDAO repositoryDAO = mock(XmlRepositoryDAO.class);
|
||||
|
||||
@BeforeEach
|
||||
void mockScmHome(@TempDirectory.TempDir Path tempDir) {
|
||||
@@ -29,8 +31,8 @@ class XmlRepositoryFileNameUpdateStepTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCopyRepositoriesFileToRepositoryPathsFile(@TempDirectory.TempDir Path tempDir) throws JAXBException, IOException {
|
||||
XmlRepositoryFileNameUpdateStep updateStep = new XmlRepositoryFileNameUpdateStep(contextProvider);
|
||||
void shouldCopyRepositoriesFileToRepositoryPathsFile(@TempDirectory.TempDir Path tempDir) throws IOException {
|
||||
XmlRepositoryFileNameUpdateStep updateStep = new XmlRepositoryFileNameUpdateStep(contextProvider, repositoryDAO);
|
||||
URL url = Resources.getResource("sonia/scm/update/repository/formerV2RepositoryFile.xml");
|
||||
Path configDir = tempDir.resolve("config");
|
||||
Files.createDirectories(configDir);
|
||||
@@ -40,5 +42,6 @@ class XmlRepositoryFileNameUpdateStepTest {
|
||||
|
||||
assertThat(configDir.resolve(PathBasedRepositoryLocationResolver.STORE_NAME + ".xml")).exists();
|
||||
assertThat(configDir.resolve("repositories.xml")).doesNotExist();
|
||||
verify(repositoryDAO).refresh();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user