mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-15 17:56:17 +01:00
Make LocationResolver create directories
This commit is contained in:
@@ -1,19 +1,21 @@
|
||||
package sonia.scm.repository.xml;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.repository.BasicRepositoryLocationResolver;
|
||||
import sonia.scm.repository.InitialRepositoryLocationResolver;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.InternalRepositoryException;
|
||||
import sonia.scm.store.StoreConstants;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.Clock;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static sonia.scm.ContextEntry.ContextBuilder.entity;
|
||||
|
||||
/**
|
||||
* A Location Resolver for File based Repository Storage.
|
||||
@@ -75,7 +77,13 @@ public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocation
|
||||
Path path = initialRepositoryLocationResolver.getPath(repositoryId);
|
||||
pathById.put(repositoryId, path);
|
||||
writePathDatabase();
|
||||
return contextProvider.resolve(path);
|
||||
Path resolvedPath = contextProvider.resolve(path);
|
||||
try {
|
||||
Files.createDirectories(resolvedPath);
|
||||
} catch (IOException e) {
|
||||
throw new InternalRepositoryException(entity("Repository", repositoryId), "could not create directory for new repository", e);
|
||||
}
|
||||
return resolvedPath;
|
||||
}
|
||||
|
||||
Path remove(String repositoryId) {
|
||||
|
||||
@@ -1,43 +1,172 @@
|
||||
package sonia.scm.repository.xml;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.junitpioneer.jupiter.TempDirectory;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.mockito.junit.jupiter.MockitoSettings;
|
||||
import org.mockito.quality.Strictness;
|
||||
import org.mockito.stubbing.Answer;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.repository.InitialRepositoryLocationResolver;
|
||||
import sonia.scm.repository.RepositoryDAO;
|
||||
import sonia.scm.repository.RepositoryLocationResolver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.Clock;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith({MockitoExtension.class})
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@ExtendWith(TempDirectory.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
class PathBasedRepositoryLocationResolverTest {
|
||||
|
||||
private static final long CREATION_TIME = 42;
|
||||
|
||||
@Mock
|
||||
private SCMContextProvider contextProvider;
|
||||
|
||||
@Mock
|
||||
private InitialRepositoryLocationResolver initialRepositoryLocationResolver;
|
||||
|
||||
@Mock
|
||||
private Clock clock;
|
||||
|
||||
private Path basePath;
|
||||
|
||||
private PathBasedRepositoryLocationResolver resolver;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
when(contextProvider.resolve(any(Path.class))).then((Answer<Path>) invocationOnMock -> invocationOnMock.getArgument(0));
|
||||
resolver = new PathBasedRepositoryLocationResolver(contextProvider, initialRepositoryLocationResolver);
|
||||
void beforeEach(@TempDirectory.TempDir Path temp) {
|
||||
this.basePath = temp;
|
||||
when(contextProvider.getBaseDirectory()).thenReturn(temp.toFile());
|
||||
when(contextProvider.resolve(any(Path.class))).thenAnswer(invocation -> invocation.getArgument(0));
|
||||
when(initialRepositoryLocationResolver.getPath(anyString())).thenAnswer(invocation -> temp.resolve(invocation.getArgument(0).toString()));
|
||||
when(clock.millis()).thenReturn(CREATION_TIME);
|
||||
resolver = createResolver();
|
||||
}
|
||||
|
||||
// TODO implement tests
|
||||
@Test
|
||||
void shouldCreateInitialDirectory() {
|
||||
Path path = resolver.forClass(Path.class).getLocation("newId");
|
||||
|
||||
assertThat(path).isEqualTo(basePath.resolve("newId"));
|
||||
assertThat(path).isDirectory();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPersistInitialDirectory() {
|
||||
resolver.forClass(Path.class).getLocation("newId");
|
||||
|
||||
String content = getXmlFileContent();
|
||||
|
||||
assertThat(content).contains("newId");
|
||||
assertThat(content).contains(basePath.resolve("newId").toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPersistWithCreationDate() {
|
||||
long now = CREATION_TIME + 100;
|
||||
when(clock.millis()).thenReturn(now);
|
||||
|
||||
resolver.forClass(Path.class).getLocation("newId");
|
||||
|
||||
assertThat(resolver.getCreationTime()).isEqualTo(CREATION_TIME);
|
||||
|
||||
String content = getXmlFileContent();
|
||||
assertThat(content).contains("creation-time=\"" + CREATION_TIME + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUpdateWithModifiedDate() {
|
||||
long now = CREATION_TIME + 100;
|
||||
when(clock.millis()).thenReturn(now);
|
||||
|
||||
resolver.forClass(Path.class).getLocation("newId");
|
||||
|
||||
assertThat(resolver.getCreationTime()).isEqualTo(CREATION_TIME);
|
||||
assertThat(resolver.getLastModified()).isEqualTo(now);
|
||||
|
||||
String content = getXmlFileContent();
|
||||
assertThat(content).contains("creation-time=\"" + CREATION_TIME + "\"");
|
||||
assertThat(content).contains("last-modified=\"" + now + "\"");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class WithExistingData {
|
||||
|
||||
private PathBasedRepositoryLocationResolver resolverWithExistingData;
|
||||
|
||||
@BeforeEach
|
||||
void createExistingDatabase() {
|
||||
resolver.forClass(Path.class).getLocation("existingId_1");
|
||||
resolver.forClass(Path.class).getLocation("existingId_2");
|
||||
resolverWithExistingData = createResolver();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldInitWithExistingData() {
|
||||
Map<String, Path> foundRepositories = new HashMap<>();
|
||||
resolverWithExistingData.forAllPaths(
|
||||
foundRepositories::put
|
||||
);
|
||||
assertThat(foundRepositories)
|
||||
.containsKeys("existingId_1", "existingId_2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRemoveFromFile() {
|
||||
resolverWithExistingData.remove("existingId_1");
|
||||
|
||||
assertThat(getXmlFileContent()).doesNotContain("existingId_1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotUpdateModificationDateForExistingDirectoryMapping() {
|
||||
long now = CREATION_TIME + 100;
|
||||
Path path = resolverWithExistingData.create(Path.class).getLocation("existingId_1");
|
||||
|
||||
assertThat(path).isEqualTo(basePath.resolve("existingId_1"));
|
||||
|
||||
String content = getXmlFileContent();
|
||||
assertThat(content).doesNotContain("last-modified=\"" + now + "\"");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotCreateDirectoryForExistingMapping() throws IOException {
|
||||
Files.delete(basePath.resolve("existingId_1"));
|
||||
|
||||
Path path = resolverWithExistingData.create(Path.class).getLocation("existingId_1");
|
||||
|
||||
assertThat(path).doesNotExist();
|
||||
}
|
||||
}
|
||||
|
||||
private String getXmlFileContent() {
|
||||
Path storePath = basePath.resolve("config").resolve("repositories.xml");
|
||||
|
||||
assertThat(storePath).isRegularFile();
|
||||
return content(storePath);
|
||||
}
|
||||
|
||||
private PathBasedRepositoryLocationResolver createResolver() {
|
||||
return new PathBasedRepositoryLocationResolver(contextProvider, initialRepositoryLocationResolver, clock);
|
||||
}
|
||||
|
||||
private String content(Path storePath) {
|
||||
try {
|
||||
return new String(Files.readAllBytes(storePath), Charsets.UTF_8);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user