Make LocationResolver create directories

This commit is contained in:
René Pfeuffer
2019-05-10 15:47:57 +02:00
parent a83e2813a3
commit e1625bf92f
2 changed files with 151 additions and 14 deletions

View File

@@ -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) {

View File

@@ -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);
}
}
}