From 77a1ad50fea1758b8a00ab15c79752f6ef9b5fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 6 Jun 2019 10:45:56 +0200 Subject: [PATCH 1/4] 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. --- .../PathBasedRepositoryLocationResolver.java | 8 +- .../scm/repository/xml/XmlRepositoryDAO.java | 7 ++ .../repository/xml/XmlRepositoryDAOTest.java | 104 ++++++++++++------ .../XmlRepositoryFileNameUpdateStep.java | 6 +- .../XmlRepositoryFileNameUpdateStepTest.java | 9 +- 5 files changed, 94 insertions(+), 40 deletions(-) diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathBasedRepositoryLocationResolver.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathBasedRepositoryLocationResolver.java index a1ce516069..bfb59f9f35 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathBasedRepositoryLocationResolver.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/PathBasedRepositoryLocationResolver.java @@ -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 { 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(); + } } diff --git a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java index f506793d1a..151e8f1281 100644 --- a/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java +++ b/scm-dao-xml/src/main/java/sonia/scm/repository/xml/XmlRepositoryDAO.java @@ -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(); + } } diff --git a/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java b/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java index 5b9a00aec8..d77bfb3c63 100644 --- a/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java +++ b/scm-dao-xml/src/test/java/sonia/scm/repository/xml/XmlRepositoryDAOTest.java @@ -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> 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) invocation.getArgument(0)).accept("existing", repositoryPath); + return null; + } + ).when(locationResolver).forAllPaths(any()); + } + } + + private Repository createRepository(String id) { return new Repository(id, "xml", "space", id); } } diff --git a/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStep.java b/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStep.java index 62902713f0..9df6f81440 100644 --- a/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStep.java +++ b/scm-webapp/src/main/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStep.java @@ -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(); } } diff --git a/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStepTest.java b/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStepTest.java index 51be47fc82..658330956d 100644 --- a/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStepTest.java +++ b/scm-webapp/src/test/java/sonia/scm/update/repository/XmlRepositoryFileNameUpdateStepTest.java @@ -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(); } } From c39c14bbd15a6abfa8a2c720eee50b15f44215c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 6 Jun 2019 13:31:40 +0200 Subject: [PATCH 2/4] Remove no longer needed LfsStoreRemoveListener With v2 the LFS store resides inside the repository directory that is purged completely on deletion. Therefore an explicit deletion of the LFS folder is no longer necessary. --- .../scm/web/lfs/LfsStoreRemoveListener.java | 97 ------------------- 1 file changed, 97 deletions(-) delete mode 100644 scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java deleted file mode 100644 index 18fb333c74..0000000000 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/web/lfs/LfsStoreRemoveListener.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - -package sonia.scm.web.lfs; - -import com.github.legman.Subscribe; -import com.google.inject.Inject; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import sonia.scm.EagerSingleton; -import sonia.scm.HandlerEventType; -import sonia.scm.plugin.Extension; -import sonia.scm.repository.GitRepositoryHandler; -import sonia.scm.repository.Repository; -import sonia.scm.repository.RepositoryEvent; -import sonia.scm.store.Blob; -import sonia.scm.store.BlobStore; - -/** - * Listener which removes all lfs objects from a blob store, whenever its corresponding git repository gets deleted. - * - * @author Sebastian Sdorra - * @since 1.54 - */ -@Extension -@EagerSingleton -public class LfsStoreRemoveListener { - - private static final Logger LOG = LoggerFactory.getLogger(LfsBlobStoreFactory.class); - - private final LfsBlobStoreFactory lfsBlobStoreFactory; - - @Inject - public LfsStoreRemoveListener(LfsBlobStoreFactory lfsBlobStoreFactory) { - this.lfsBlobStoreFactory = lfsBlobStoreFactory; - } - - /** - * Remove all object from the blob store, if the event is an delete event and the repository is a git repository. - * - * @param event repository event - */ - @Subscribe - public void handleRepositoryEvent(RepositoryEvent event) { - if ( isDeleteEvent(event) && isGitRepositoryEvent(event) ) { - removeLfsStore(event.getItem()); - } - } - - private boolean isDeleteEvent(RepositoryEvent event) { - return HandlerEventType.DELETE == event.getEventType(); - } - - private boolean isGitRepositoryEvent(RepositoryEvent event) { - return event.getItem() != null - && event.getItem().getType().equals(GitRepositoryHandler.TYPE_NAME); - } - - private void removeLfsStore(Repository repository) { - LOG.debug("remove all blobs from store, because corresponding git repository {} was removed", repository.getName()); - BlobStore blobStore = lfsBlobStoreFactory.getLfsBlobStore(repository); - for ( Blob blob : blobStore.getAll() ) { - LOG.trace("remove blob {}, because repository {} was removed", blob.getId(), repository.getName()); - blobStore.remove(blob); - } - } - -} From 1288724d6a9a5f6af3d375f0893af06af9d13c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Pfeuffer?= Date: Thu, 6 Jun 2019 13:46:17 +0200 Subject: [PATCH 3/4] Remove test without implementation --- .../web/lfs/LfsStoreRemoveListenerTest.java | 122 ------------------ 1 file changed, 122 deletions(-) delete mode 100644 scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsStoreRemoveListenerTest.java diff --git a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsStoreRemoveListenerTest.java b/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsStoreRemoveListenerTest.java deleted file mode 100644 index 34a1a3f4d5..0000000000 --- a/scm-plugins/scm-git-plugin/src/test/java/sonia/scm/web/lfs/LfsStoreRemoveListenerTest.java +++ /dev/null @@ -1,122 +0,0 @@ -/** - * Copyright (c) 2010, Sebastian Sdorra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * 3. Neither the name of SCM-Manager; nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * http://bitbucket.org/sdorra/scm-manager - * - */ - - -package sonia.scm.web.lfs; - -import com.google.common.collect.Lists; -import java.util.List; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import static org.mockito.Mockito.*; -import org.mockito.junit.MockitoJUnitRunner; -import sonia.scm.HandlerEventType; -import sonia.scm.repository.Repository; -import sonia.scm.repository.RepositoryEvent; -import sonia.scm.repository.RepositoryTestData; -import sonia.scm.store.Blob; -import sonia.scm.store.BlobStore; - -/** - * Unit tests for {@link LfsStoreRemoveListener}. - * - * @author Sebastian Sdorra - */ -@RunWith(MockitoJUnitRunner.class) -public class LfsStoreRemoveListenerTest { - - @Mock - private LfsBlobStoreFactory lfsBlobStoreFactory; - - @Mock - private BlobStore blobStore; - - @InjectMocks - private LfsStoreRemoveListener lfsStoreRemoveListener; - - @Test - public void testHandleRepositoryEventWithNonDeleteEvents() { - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.BEFORE_CREATE)); - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.CREATE)); - - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.BEFORE_MODIFY)); - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.MODIFY)); - - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.BEFORE_DELETE)); - - verifyZeroInteractions(lfsBlobStoreFactory); - } - - @Test - public void testHandleRepositoryEventWithNonGitRepositories() { - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.DELETE, "svn")); - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.DELETE, "hg")); - lfsStoreRemoveListener.handleRepositoryEvent(event(HandlerEventType.DELETE, "dummy")); - - verifyZeroInteractions(lfsBlobStoreFactory); - } - - @Test - public void testHandleRepositoryEvent() { - Repository heartOfGold = RepositoryTestData.createHeartOfGold("git"); - - when(lfsBlobStoreFactory.getLfsBlobStore(heartOfGold)).thenReturn(blobStore); - Blob blobA = mockBlob("a"); - Blob blobB = mockBlob("b"); - List blobs = Lists.newArrayList(blobA, blobB); - when(blobStore.getAll()).thenReturn(blobs); - - - lfsStoreRemoveListener.handleRepositoryEvent(new RepositoryEvent(HandlerEventType.DELETE, heartOfGold)); - verify(blobStore).getAll(); - verify(blobStore).remove(blobA); - verify(blobStore).remove(blobB); - - verifyNoMoreInteractions(blobStore); - } - - private Blob mockBlob(String id) { - Blob blob = mock(Blob.class); - when(blob.getId()).thenReturn(id); - return blob; - } - - private RepositoryEvent event(HandlerEventType eventType) { - return event(eventType, "git"); - } - - private RepositoryEvent event(HandlerEventType eventType, String repositoryType) { - return new RepositoryEvent(eventType, RepositoryTestData.create42Puzzle(repositoryType)); - } - -} From 13951595c4f89b3bbfa28c0c9100e3f45181dccc Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Fri, 7 Jun 2019 12:34:10 +0000 Subject: [PATCH 4/4] Close branch bugfix/refresh_repo_db_after_upgrade