mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-02-21 22:16:55 +01:00
Repository export read-only lock (#1519)
* Lock repository for read-only access only while exporting * Create read-only check api Co-authored-by: René Pfeuffer <rene.pfeuffer@cloudogu.com>
This commit is contained in:
@@ -88,6 +88,7 @@ import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static java.util.stream.Stream.of;
|
||||
@@ -104,23 +105,24 @@ import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyMap;
|
||||
import static org.mockito.ArgumentMatchers.anyObject;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.RETURNS_SELF;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
import static org.mockito.MockitoAnnotations.openMocks;
|
||||
|
||||
@SubjectAware(
|
||||
username = "trillian",
|
||||
password = "secret",
|
||||
configuration = "classpath:sonia/scm/repository/shiro.ini"
|
||||
)
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
private static final String REALM = "AdminRealm";
|
||||
@@ -160,6 +162,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
private final URI baseUri = URI.create("/");
|
||||
private final ResourceLinks resourceLinks = ResourceLinksMock.createMock(baseUri);
|
||||
private Repository repositoryMarkedAsExported;
|
||||
|
||||
@InjectMocks
|
||||
private RepositoryToRepositoryDtoMapperImpl repositoryToDtoMapper;
|
||||
@@ -168,7 +171,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() {
|
||||
initMocks(this);
|
||||
openMocks(this);
|
||||
super.repositoryToDtoMapper = repositoryToDtoMapper;
|
||||
super.dtoToRepositoryMapper = dtoToRepositoryMapper;
|
||||
super.manager = repositoryManager;
|
||||
@@ -316,7 +319,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(SC_NO_CONTENT, response.getStatus());
|
||||
verify(repositoryManager).modify(anyObject());
|
||||
verify(repositoryManager).modify(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -336,7 +339,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
|
||||
assertEquals(SC_CONFLICT, response.getStatus());
|
||||
assertThat(response.getContentAsString()).contains("space/repo");
|
||||
verify(repositoryManager, never()).modify(anyObject());
|
||||
verify(repositoryManager, never()).modify(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -355,7 +358,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(SC_BAD_REQUEST, response.getStatus());
|
||||
verify(repositoryManager, never()).modify(anyObject());
|
||||
verify(repositoryManager, never()).modify(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -368,7 +371,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(SC_NO_CONTENT, response.getStatus());
|
||||
verify(repositoryManager).delete(anyObject());
|
||||
verify(repositoryManager).delete(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -826,7 +829,7 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
/**
|
||||
* This method is a slightly adapted copy of Lin Zaho's gist at https://gist.github.com/lin-zhao/9985191
|
||||
*/
|
||||
private MockHttpRequest multipartRequest(MockHttpRequest request, Map<String, InputStream> files, RepositoryDto repository) throws IOException {
|
||||
private void multipartRequest(MockHttpRequest request, Map<String, InputStream> files, RepositoryDto repository) throws IOException {
|
||||
String boundary = UUID.randomUUID().toString();
|
||||
request.contentType("multipart/form-data; boundary=" + boundary);
|
||||
|
||||
@@ -864,6 +867,5 @@ public class RepositoryRootResourceTest extends RepositoryTestBase {
|
||||
formWriter.flush();
|
||||
}
|
||||
request.setInputStream(new ByteArrayInputStream(buffer.toByteArray()));
|
||||
return request;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.repository.Repository;
|
||||
import sonia.scm.repository.RepositoryExportingCheck;
|
||||
import sonia.scm.repository.RepositoryTestData;
|
||||
import sonia.scm.repository.api.BundleCommandBuilder;
|
||||
import sonia.scm.repository.api.RepositoryService;
|
||||
@@ -47,6 +48,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -70,6 +72,8 @@ class FullScmRepositoryExporterTest {
|
||||
private TarArchiveRepositoryStoreExporter storeExporter;
|
||||
@Mock
|
||||
private WorkdirProvider workdirProvider;
|
||||
@Mock
|
||||
private RepositoryExportingCheck repositoryExportingCheck;
|
||||
|
||||
@InjectMocks
|
||||
private FullScmRepositoryExporter exporter;
|
||||
@@ -81,6 +85,7 @@ class FullScmRepositoryExporterTest {
|
||||
when(serviceFactory.create(REPOSITORY)).thenReturn(repositoryService);
|
||||
when(environmentGenerator.generate()).thenReturn(new byte[0]);
|
||||
when(metadataGenerator.generate(REPOSITORY)).thenReturn(new byte[0]);
|
||||
when(repositoryExportingCheck.withExportingLock(any(), any())).thenAnswer(invocation -> invocation.getArgument(1, Supplier.class).get());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -96,6 +101,7 @@ class FullScmRepositoryExporterTest {
|
||||
verify(environmentGenerator, times(1)).generate();
|
||||
verify(metadataGenerator, times(1)).generate(REPOSITORY);
|
||||
verify(bundleCommandBuilder, times(1)).bundle(any(OutputStream.class));
|
||||
verify(repositoryExportingCheck).withExportingLock(eq(REPOSITORY), any());
|
||||
workDirsCreated.forEach(wd -> assertThat(wd).doesNotExist());
|
||||
}
|
||||
|
||||
|
||||
@@ -108,8 +108,7 @@ public class DefaultRepositoryManagerPerfTest {
|
||||
Set<RepositoryHandler> handlerSet = ImmutableSet.of(repositoryHandler);
|
||||
NamespaceStrategy namespaceStrategy = mock(NamespaceStrategy.class);
|
||||
repositoryManager = new DefaultRepositoryManager(
|
||||
configuration,
|
||||
contextProvider,
|
||||
contextProvider,
|
||||
keyGenerator,
|
||||
repositoryDAO,
|
||||
handlerSet,
|
||||
|
||||
@@ -65,7 +65,6 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptySet;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.hasProperty;
|
||||
@@ -109,7 +108,7 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
|
||||
private RepositoryDAO repositoryDAO;
|
||||
|
||||
{
|
||||
static {
|
||||
ThreadContext.unbindSubject();
|
||||
}
|
||||
|
||||
@@ -121,8 +120,6 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
|
||||
private NamespaceStrategy namespaceStrategy = mock(NamespaceStrategy.class);
|
||||
|
||||
private ScmConfiguration configuration;
|
||||
|
||||
private String mockedNamespace = "default_namespace";
|
||||
|
||||
@Before
|
||||
@@ -552,11 +549,9 @@ public class DefaultRepositoryManagerTest extends ManagerTestBase<Repository> {
|
||||
handlerSet.add(createRepositoryHandler("hg", "Mercurial"));
|
||||
handlerSet.add(createRepositoryHandler("svn", "SVN"));
|
||||
|
||||
this.configuration = new ScmConfiguration();
|
||||
|
||||
when(namespaceStrategy.createNamespace(Mockito.any(Repository.class))).thenAnswer(invocation -> mockedNamespace);
|
||||
|
||||
return new DefaultRepositoryManager(configuration, contextProvider,
|
||||
return new DefaultRepositoryManager(contextProvider,
|
||||
keyGenerator, repositoryDAO, handlerSet, Providers.of(namespaceStrategy));
|
||||
}
|
||||
|
||||
|
||||
@@ -21,13 +21,12 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm.update;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import sonia.scm.migration.UpdateStep;
|
||||
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
||||
import sonia.scm.store.InMemoryConfigurationEntryStore;
|
||||
import sonia.scm.store.InMemoryConfigurationEntryStoreFactory;
|
||||
import sonia.scm.version.Version;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user