Merge with 2.0.0-m3

This commit is contained in:
René Pfeuffer
2019-06-11 13:55:43 +02:00
110 changed files with 7002 additions and 4053 deletions

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,9 +29,10 @@ import static sonia.scm.ContextEntry.ContextBuilder.entity;
*
* @since 2.0.0
*/
@Singleton
public class PathBasedRepositoryLocationResolver extends BasicRepositoryLocationResolver<Path> {
private static final String STORE_NAME = "repositories";
public static final String STORE_NAME = "repository-paths";
private final SCMContextProvider contextProvider;
private final InitialRepositoryLocationResolver initialRepositoryLocationResolver;
@@ -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();
}
}

View File

@@ -95,10 +95,17 @@ public class XmlRepositoryDAO implements RepositoryDAO {
@Override
public void add(Repository repository) {
add(repository, repositoryLocationResolver.create(repository.getId()));
}
public void add(Repository repository, Object location) {
if (!(location instanceof Path)) {
throw new IllegalArgumentException("can only handle locations of type " + Path.class.getName() + ", not of type " + location.getClass().getName());
}
Repository clone = repository.clone();
synchronized (this) {
Path repositoryPath = repositoryLocationResolver.create(repository.getId());
Path repositoryPath = (Path) location;
try {
Path metadataPath = resolveDataPath(repositoryPath);
@@ -111,10 +118,8 @@ public class XmlRepositoryDAO implements RepositoryDAO {
byId.put(repository.getId(), clone);
byNamespaceAndName.put(repository.getNamespaceAndName(), clone);
}
}
@Override
public boolean contains(Repository repository) {
return byId.containsKey(repository.getId());
@@ -193,4 +198,11 @@ public class XmlRepositoryDAO implements RepositoryDAO {
public Long getLastModified() {
return repositoryLocationResolver.getLastModified();
}
public void refresh() {
repositoryLocationResolver.refresh();
byNamespaceAndName.clear();
byId.clear();
init();
}
}

View File

@@ -152,7 +152,7 @@ class PathBasedRepositoryLocationResolverTest {
}
private String getXmlFileContent() {
Path storePath = basePath.resolve("config").resolve("repositories.xml");
Path storePath = basePath.resolve("config").resolve("repository-paths.xml");
assertThat(storePath).isRegularFile();
return content(storePath);

View File

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