mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-07 05:55:44 +01:00
Cleanup
This commit is contained in:
@@ -27,11 +27,11 @@ package sonia.scm.repository.util;
|
|||||||
import com.google.common.base.Stopwatch;
|
import com.google.common.base.Stopwatch;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import sonia.scm.repository.InternalRepositoryException;
|
||||||
import sonia.scm.util.IOUtil;
|
import sonia.scm.util.IOUtil;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@@ -49,13 +49,13 @@ public class CachingAllWorkingCopyPool implements WorkingCopyPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, W, C> SimpleWorkingCopyFactory.ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> workingCopyContext) throws IOException {
|
public <R, W, C> ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> workingCopyContext) {
|
||||||
String id = workingCopyContext.getScmRepository().getId();
|
String id = workingCopyContext.getScmRepository().getId();
|
||||||
File existingWorkdir = workdirs.remove(id);
|
File existingWorkdir = workdirs.remove(id);
|
||||||
if (existingWorkdir != null) {
|
if (existingWorkdir != null) {
|
||||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||||
try {
|
try {
|
||||||
SimpleWorkingCopyFactory.ParentAndClone<R, W> reclaimed = workingCopyContext.getReclaimer().reclaim(existingWorkdir);
|
ParentAndClone<R, W> reclaimed = workingCopyContext.getReclaimer().reclaim(existingWorkdir);
|
||||||
LOG.debug("reclaimed workdir for {} in path {} in {}", workingCopyContext.getScmRepository().getNamespaceAndName(), existingWorkdir, stopwatch.stop());
|
LOG.debug("reclaimed workdir for {} in path {} in {}", workingCopyContext.getScmRepository().getNamespaceAndName(), existingWorkdir, stopwatch.stop());
|
||||||
return reclaimed;
|
return reclaimed;
|
||||||
} catch (SimpleWorkingCopyFactory.ReclaimFailedException e) {
|
} catch (SimpleWorkingCopyFactory.ReclaimFailedException e) {
|
||||||
@@ -63,13 +63,17 @@ public class CachingAllWorkingCopyPool implements WorkingCopyPool {
|
|||||||
deleteWorkdir(existingWorkdir);
|
deleteWorkdir(existingWorkdir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
return createNewWorkdir(workingCopyContext);
|
return createNewWorkdir(workingCopyContext);
|
||||||
|
} catch (WorkingCopyFailedException e) {
|
||||||
|
throw new InternalRepositoryException(workingCopyContext.getScmRepository(), "failed to create working copy", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <R, W> SimpleWorkingCopyFactory.ParentAndClone<R, W> createNewWorkdir(WorkingCopyContext<R, W, ?> workingCopyContext) throws IOException {
|
private <R, W> ParentAndClone<R, W> createNewWorkdir(WorkingCopyContext<R, W, ?> workingCopyContext) throws WorkingCopyFailedException {
|
||||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||||
File newWorkdir = workdirProvider.createNewWorkdir();
|
File newWorkdir = workdirProvider.createNewWorkdir();
|
||||||
SimpleWorkingCopyFactory.ParentAndClone<R, W> parentAndClone = workingCopyContext.getInitializer().initialize(newWorkdir);
|
ParentAndClone<R, W> parentAndClone = workingCopyContext.getInitializer().initialize(newWorkdir);
|
||||||
LOG.debug("initialized new workdir for {} in path {} in {}", workingCopyContext.getScmRepository().getNamespaceAndName(), newWorkdir, stopwatch.stop());
|
LOG.debug("initialized new workdir for {} in path {} in {}", workingCopyContext.getScmRepository().getNamespaceAndName(), newWorkdir, stopwatch.stop());
|
||||||
return parentAndClone;
|
return parentAndClone;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import sonia.scm.util.IOUtil;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class NoneCachingWorkingCopyPool implements WorkingCopyPool {
|
public class NoneCachingWorkingCopyPool implements WorkingCopyPool {
|
||||||
|
|
||||||
@@ -40,13 +39,13 @@ public class NoneCachingWorkingCopyPool implements WorkingCopyPool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <R, W, C> SimpleWorkingCopyFactory.ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> context) throws IOException {
|
public <R, W, C> ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> context) throws WorkingCopyFailedException {
|
||||||
return context.getInitializer().initialize(workdirProvider.createNewWorkdir());
|
return context.getInitializer().initialize(workdirProvider.createNewWorkdir());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextClosed(WorkingCopyContext<?, ?, ?> workingCopyContext, File workdir) throws IOException {
|
public void contextClosed(WorkingCopyContext<?, ?, ?> workingCopyContext, File workdir) {
|
||||||
IOUtil.delete(workdir, true);
|
IOUtil.deleteSilently(workdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -26,14 +26,12 @@ package sonia.scm.repository.util;
|
|||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import sonia.scm.plugin.Extension;
|
|
||||||
import sonia.scm.repository.InternalRepositoryException;
|
import sonia.scm.repository.InternalRepositoryException;
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
|
|
||||||
import javax.servlet.ServletContextEvent;
|
import javax.servlet.ServletContextEvent;
|
||||||
import javax.servlet.ServletContextListener;
|
import javax.servlet.ServletContextListener;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public abstract class SimpleWorkingCopyFactory<R, W, C> implements WorkingCopyFactory<R, W, C>, ServletContextListener {
|
public abstract class SimpleWorkingCopyFactory<R, W, C> implements WorkingCopyFactory<R, W, C>, ServletContextListener {
|
||||||
|
|
||||||
@@ -49,16 +47,14 @@ public abstract class SimpleWorkingCopyFactory<R, W, C> implements WorkingCopyFa
|
|||||||
public WorkingCopy<R, W> createWorkingCopy(C repositoryContext, String initialBranch) {
|
public WorkingCopy<R, W> createWorkingCopy(C repositoryContext, String initialBranch) {
|
||||||
try {
|
try {
|
||||||
WorkingCopyContext<R, W, C> workingCopyContext = createWorkingCopyContext(repositoryContext, initialBranch);
|
WorkingCopyContext<R, W, C> workingCopyContext = createWorkingCopyContext(repositoryContext, initialBranch);
|
||||||
ParentAndClone<R, W> parentAndClone = workingCopyPool.getWorkingCopy(workingCopyContext);
|
WorkingCopyPool.ParentAndClone<R, W> parentAndClone = workingCopyPool.getWorkingCopy(workingCopyContext);
|
||||||
return new WorkingCopy<>(parentAndClone.getClone(), parentAndClone.getParent(), () -> this.close(workingCopyContext, parentAndClone), parentAndClone.getDirectory());
|
return new WorkingCopy<>(parentAndClone.getClone(), parentAndClone.getParent(), () -> this.close(workingCopyContext, parentAndClone), parentAndClone.getDirectory());
|
||||||
} catch (RuntimeException e) {
|
} catch (WorkingCopyFailedException e) {
|
||||||
throw e;
|
throw new InternalRepositoryException(getScmRepository(repositoryContext), "could not create working copy for repository in temporary directory", e);
|
||||||
} catch (Exception e) {
|
|
||||||
throw new InternalRepositoryException(getScmRepository(repositoryContext), "could not clone repository in temporary directory", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public WorkingCopyContext<R, W, C> createWorkingCopyContext(C repositoryContext, String initialBranch) {
|
private WorkingCopyContext<R, W, C> createWorkingCopyContext(C repositoryContext, String initialBranch) {
|
||||||
return new WorkingCopyContext<>(
|
return new WorkingCopyContext<>(
|
||||||
getScmRepository(repositoryContext),
|
getScmRepository(repositoryContext),
|
||||||
initialBranch,
|
initialBranch,
|
||||||
@@ -68,7 +64,7 @@ public abstract class SimpleWorkingCopyFactory<R, W, C> implements WorkingCopyFa
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void close(WorkingCopyContext<R, W, C> workingCopyContext, ParentAndClone<R, W> parentAndClone) {
|
private void close(WorkingCopyContext<R, W, C> workingCopyContext, WorkingCopyPool.ParentAndClone<R, W> parentAndClone) {
|
||||||
try {
|
try {
|
||||||
closeRepository(parentAndClone.getParent());
|
closeRepository(parentAndClone.getParent());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -98,12 +94,12 @@ public abstract class SimpleWorkingCopyFactory<R, W, C> implements WorkingCopyFa
|
|||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface WorkingCopyInitializer<R, W> {
|
public interface WorkingCopyInitializer<R, W> {
|
||||||
ParentAndClone<R, W> initialize(File target) throws IOException;
|
WorkingCopyPool.ParentAndClone<R, W> initialize(File target) throws WorkingCopyFailedException;
|
||||||
}
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface WorkingCopyReclaimer<R, W> {
|
public interface WorkingCopyReclaimer<R, W> {
|
||||||
ParentAndClone<R, W> reclaim(File target) throws IOException, ReclaimFailedException;
|
WorkingCopyPool.ParentAndClone<R, W> reclaim(File target) throws ReclaimFailedException;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Repository getScmRepository(C context);
|
protected abstract Repository getScmRepository(C context);
|
||||||
@@ -115,40 +111,21 @@ public abstract class SimpleWorkingCopyFactory<R, W, C> implements WorkingCopyFa
|
|||||||
// We do allow implementations to throw arbitrary exceptions here, so that we can handle them in closeWorkingCopy
|
// We do allow implementations to throw arbitrary exceptions here, so that we can handle them in closeWorkingCopy
|
||||||
protected abstract void closeWorkingCopyInternal(W workingCopy) throws Exception;
|
protected abstract void closeWorkingCopyInternal(W workingCopy) throws Exception;
|
||||||
|
|
||||||
protected abstract ParentAndClone<R, W> cloneRepository(C context, File target, String initialBranch) throws IOException;
|
protected abstract WorkingCopyPool.ParentAndClone<R, W> cloneRepository(C context, File target, String initialBranch) throws WorkingCopyFailedException;
|
||||||
|
|
||||||
protected abstract ParentAndClone<R, W> reclaimRepository(C context, File target, String initialBranch) throws IOException, ReclaimFailedException;
|
protected abstract WorkingCopyPool.ParentAndClone<R, W> reclaimRepository(C context, File target, String initialBranch) throws ReclaimFailedException;
|
||||||
|
|
||||||
protected static class ParentAndClone<R, W> {
|
|
||||||
private final R parent;
|
|
||||||
private final W clone;
|
|
||||||
private final File directory;
|
|
||||||
|
|
||||||
public ParentAndClone(R parent, W clone, File directory) {
|
|
||||||
this.parent = parent;
|
|
||||||
this.clone = clone;
|
|
||||||
this.directory = directory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public R getParent() {
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public W getClone() {
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getDirectory() {
|
|
||||||
return directory;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ReclaimFailedException extends Exception {
|
public static class ReclaimFailedException extends Exception {
|
||||||
public ReclaimFailedException() {
|
public ReclaimFailedException(String message) {
|
||||||
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ReclaimFailedException(Throwable cause) {
|
public ReclaimFailedException(Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ReclaimFailedException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package sonia.scm.repository.util;
|
||||||
|
|
||||||
|
public class WorkingCopyFailedException extends Exception {
|
||||||
|
public WorkingCopyFailedException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkingCopyFailedException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkingCopyFailedException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,9 +27,33 @@ package sonia.scm.repository.util;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public interface WorkingCopyPool {
|
public interface WorkingCopyPool {
|
||||||
<R, W, C> SimpleWorkingCopyFactory.ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> context) throws Exception;
|
<R, W, C> ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> context) throws WorkingCopyFailedException;
|
||||||
|
|
||||||
void contextClosed(WorkingCopyContext<?, ?, ?> workingCopyContext, File workdir) throws Exception;
|
void contextClosed(WorkingCopyContext<?, ?, ?> workingCopyContext, File workdir);
|
||||||
|
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|
||||||
|
class ParentAndClone<R, W> {
|
||||||
|
private final R parent;
|
||||||
|
private final W clone;
|
||||||
|
private final File directory;
|
||||||
|
|
||||||
|
public ParentAndClone(R parent, W clone, File directory) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.clone = clone;
|
||||||
|
this.directory = directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public R getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public W getClone() {
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getDirectory() {
|
||||||
|
return directory;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
@@ -62,34 +61,34 @@ class CachingAllWorkingCopyPoolTest {
|
|||||||
SimpleWorkingCopyFactory.WorkingCopyReclaimer<Object, Path> reclaimer;
|
SimpleWorkingCopyFactory.WorkingCopyReclaimer<Object, Path> reclaimer;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
void initContext() throws IOException, SimpleWorkingCopyFactory.ReclaimFailedException {
|
void initContext() throws SimpleWorkingCopyFactory.ReclaimFailedException, WorkingCopyFailedException {
|
||||||
lenient().when(workingCopyContext.getInitializer()).thenReturn(initializer);
|
lenient().when(workingCopyContext.getInitializer()).thenReturn(initializer);
|
||||||
lenient().when(workingCopyContext.getReclaimer()).thenReturn(reclaimer);
|
lenient().when(workingCopyContext.getReclaimer()).thenReturn(reclaimer);
|
||||||
|
|
||||||
lenient().when(initializer.initialize(any()))
|
lenient().when(initializer.initialize(any()))
|
||||||
.thenAnswer(invocationOnMock -> new SimpleWorkingCopyFactory.ParentAndClone<>(null, null, invocationOnMock.getArgument(0, File.class)));
|
.thenAnswer(invocationOnMock -> new WorkingCopyPool.ParentAndClone<>(null, null, invocationOnMock.getArgument(0, File.class)));
|
||||||
lenient().when(reclaimer.reclaim(any()))
|
lenient().when(reclaimer.reclaim(any()))
|
||||||
.thenAnswer(invocationOnMock -> new SimpleWorkingCopyFactory.ParentAndClone<>(null, null, invocationOnMock.getArgument(0, File.class)));
|
.thenAnswer(invocationOnMock -> new WorkingCopyPool.ParentAndClone<>(null, null, invocationOnMock.getArgument(0, File.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCreateNewWorkdirForTheFirstRequest(@TempDir Path temp) throws IOException {
|
void shouldCreateNewWorkdirForTheFirstRequest(@TempDir Path temp) throws WorkingCopyFailedException {
|
||||||
when(workingCopyContext.getScmRepository()).thenReturn(REPOSITORY);
|
when(workingCopyContext.getScmRepository()).thenReturn(REPOSITORY);
|
||||||
when(workdirProvider.createNewWorkdir()).thenReturn(temp.toFile());
|
when(workdirProvider.createNewWorkdir()).thenReturn(temp.toFile());
|
||||||
|
|
||||||
SimpleWorkingCopyFactory.ParentAndClone<?, ?> workdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
WorkingCopyPool.ParentAndClone<?, ?> workdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
||||||
|
|
||||||
verify(initializer).initialize(temp.toFile());
|
verify(initializer).initialize(temp.toFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCreateWorkdirOnlyOnceForTheSameRepository(@TempDir Path temp) throws IOException, SimpleWorkingCopyFactory.ReclaimFailedException {
|
void shouldCreateWorkdirOnlyOnceForTheSameRepository(@TempDir Path temp) throws SimpleWorkingCopyFactory.ReclaimFailedException, WorkingCopyFailedException {
|
||||||
when(workingCopyContext.getScmRepository()).thenReturn(REPOSITORY);
|
when(workingCopyContext.getScmRepository()).thenReturn(REPOSITORY);
|
||||||
when(workdirProvider.createNewWorkdir()).thenReturn(temp.toFile());
|
when(workdirProvider.createNewWorkdir()).thenReturn(temp.toFile());
|
||||||
|
|
||||||
SimpleWorkingCopyFactory.ParentAndClone<?, ?> firstWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
WorkingCopyPool.ParentAndClone<?, ?> firstWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
||||||
cachingAllWorkingCopyPool.contextClosed(workingCopyContext, firstWorkdir.getDirectory());
|
cachingAllWorkingCopyPool.contextClosed(workingCopyContext, firstWorkdir.getDirectory());
|
||||||
SimpleWorkingCopyFactory.ParentAndClone<?, ?> secondWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
WorkingCopyPool.ParentAndClone<?, ?> secondWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
||||||
|
|
||||||
verify(initializer).initialize(temp.toFile());
|
verify(initializer).initialize(temp.toFile());
|
||||||
verify(reclaimer).reclaim(temp.toFile());
|
verify(reclaimer).reclaim(temp.toFile());
|
||||||
@@ -97,7 +96,7 @@ class CachingAllWorkingCopyPoolTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldCacheOnlyOneWorkdirForRepository(@TempDir Path temp) throws IOException, SimpleWorkingCopyFactory.ReclaimFailedException {
|
void shouldCacheOnlyOneWorkdirForRepository(@TempDir Path temp) throws SimpleWorkingCopyFactory.ReclaimFailedException, WorkingCopyFailedException {
|
||||||
when(workingCopyContext.getScmRepository()).thenReturn(REPOSITORY);
|
when(workingCopyContext.getScmRepository()).thenReturn(REPOSITORY);
|
||||||
File firstDirectory = temp.resolve("first").toFile();
|
File firstDirectory = temp.resolve("first").toFile();
|
||||||
firstDirectory.mkdirs();
|
firstDirectory.mkdirs();
|
||||||
@@ -107,8 +106,8 @@ class CachingAllWorkingCopyPoolTest {
|
|||||||
firstDirectory,
|
firstDirectory,
|
||||||
secondDirectory);
|
secondDirectory);
|
||||||
|
|
||||||
SimpleWorkingCopyFactory.ParentAndClone<?, ?> firstWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
WorkingCopyPool.ParentAndClone<?, ?> firstWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
||||||
SimpleWorkingCopyFactory.ParentAndClone<?, ?> secondWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
WorkingCopyPool.ParentAndClone<?, ?> secondWorkdir = cachingAllWorkingCopyPool.getWorkingCopy(workingCopyContext);
|
||||||
cachingAllWorkingCopyPool.contextClosed(workingCopyContext, firstWorkdir.getDirectory());
|
cachingAllWorkingCopyPool.contextClosed(workingCopyContext, firstWorkdir.getDirectory());
|
||||||
cachingAllWorkingCopyPool.contextClosed(workingCopyContext, secondWorkdir.getDirectory());
|
cachingAllWorkingCopyPool.contextClosed(workingCopyContext, secondWorkdir.getDirectory());
|
||||||
|
|
||||||
|
|||||||
@@ -61,15 +61,15 @@ public class SimpleWorkingCopyFactoryTest {
|
|||||||
WorkdirProvider workdirProvider = new WorkdirProvider(temporaryFolder.newFolder());
|
WorkdirProvider workdirProvider = new WorkdirProvider(temporaryFolder.newFolder());
|
||||||
WorkingCopyPool configurableTestWorkingCopyPool = new WorkingCopyPool() {
|
WorkingCopyPool configurableTestWorkingCopyPool = new WorkingCopyPool() {
|
||||||
@Override
|
@Override
|
||||||
public <R, W, C> SimpleWorkingCopyFactory.ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> context) throws IOException {
|
public <R, W, C> ParentAndClone<R, W> getWorkingCopy(WorkingCopyContext<R, W, C> context) throws WorkingCopyFailedException {
|
||||||
workdir = workdirProvider.createNewWorkdir();
|
workdir = workdirProvider.createNewWorkdir();
|
||||||
return context.getInitializer().initialize(workdir);
|
return context.getInitializer().initialize(workdir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextClosed(WorkingCopyContext<?, ?, ?> createWorkdirContext, File workdir) throws Exception {
|
public void contextClosed(WorkingCopyContext<?, ?, ?> createWorkdirContext, File workdir) {
|
||||||
if (!workdirIsCached) {
|
if (!workdirIsCached) {
|
||||||
IOUtil.delete(workdir);
|
IOUtil.deleteSilently(workdir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ public class SimpleWorkingCopyFactoryTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ParentAndClone<Closeable, Closeable> reclaimRepository(Context context, File target, String initialBranch) throws IOException {
|
protected WorkingCopyPool.ParentAndClone<Closeable, Closeable> reclaimRepository(Context context, File target, String initialBranch) {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,9 +99,9 @@ public class SimpleWorkingCopyFactoryTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ParentAndClone<Closeable, Closeable> cloneRepository(Context context, File target, String initialBranch) {
|
protected WorkingCopyPool.ParentAndClone<Closeable, Closeable> cloneRepository(Context context, File target, String initialBranch) {
|
||||||
initialBranchForLastCloneCall = initialBranch;
|
initialBranchForLastCloneCall = initialBranch;
|
||||||
return new ParentAndClone<>(parent, clone, target);
|
return new WorkingCopyPool.ParentAndClone<>(parent, clone, target);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import sonia.scm.repository.GitWorkingCopyFactory;
|
|||||||
import sonia.scm.repository.InternalRepositoryException;
|
import sonia.scm.repository.InternalRepositoryException;
|
||||||
import sonia.scm.repository.util.WorkingCopyPool;
|
import sonia.scm.repository.util.WorkingCopyPool;
|
||||||
import sonia.scm.repository.util.SimpleWorkingCopyFactory;
|
import sonia.scm.repository.util.SimpleWorkingCopyFactory;
|
||||||
|
import sonia.scm.repository.util.WorkingCopyPool.ParentAndClone;
|
||||||
import sonia.scm.util.SystemUtil;
|
import sonia.scm.util.SystemUtil;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -85,10 +86,10 @@ public class SimpleGitWorkingCopyFactory extends SimpleWorkingCopyFactory<Reposi
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ParentAndClone<Repository, Repository> reclaimRepository(GitContext context, File target, String initialBranch) throws IOException, ReclaimFailedException {
|
protected ParentAndClone<Repository, Repository> reclaimRepository(GitContext context, File target, String initialBranch) throws ReclaimFailedException {
|
||||||
LOG.trace("reclaim repository {}", context.getRepository().getId());
|
LOG.trace("reclaim repository {}", context.getRepository().getId());
|
||||||
long start = System.nanoTime();
|
long start = System.nanoTime();
|
||||||
Repository repo = GitUtil.open(target);
|
Repository repo = openTarget(target);
|
||||||
try (Git git = Git.open(target)) {
|
try (Git git = Git.open(target)) {
|
||||||
git.reset().setMode(ResetCommand.ResetType.HARD).call();
|
git.reset().setMode(ResetCommand.ResetType.HARD).call();
|
||||||
git.clean().setForce(true).setCleanDirectories(true).call();
|
git.clean().setForce(true).setCleanDirectories(true).call();
|
||||||
@@ -97,7 +98,7 @@ public class SimpleGitWorkingCopyFactory extends SimpleWorkingCopyFactory<Reposi
|
|||||||
git.branchDelete().setBranchNames(initialBranch).setForce(true).call();
|
git.branchDelete().setBranchNames(initialBranch).setForce(true).call();
|
||||||
git.checkout().setName(initialBranch).setCreateBranch(true).call();
|
git.checkout().setName(initialBranch).setCreateBranch(true).call();
|
||||||
return new ParentAndClone<>(null, repo, target);
|
return new ParentAndClone<>(null, repo, target);
|
||||||
} catch (GitAPIException e) {
|
} catch (GitAPIException | IOException e) {
|
||||||
throw new ReclaimFailedException(e);
|
throw new ReclaimFailedException(e);
|
||||||
} finally {
|
} finally {
|
||||||
long end = System.nanoTime();
|
long end = System.nanoTime();
|
||||||
@@ -106,6 +107,14 @@ public class SimpleGitWorkingCopyFactory extends SimpleWorkingCopyFactory<Reposi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Repository openTarget(File target) throws ReclaimFailedException {
|
||||||
|
try {
|
||||||
|
return GitUtil.open(target);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new ReclaimFailedException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String createScmTransportProtocolUri(File bareRepository) {
|
String createScmTransportProtocolUri(File bareRepository) {
|
||||||
if (SystemUtil.isWindows()) {
|
if (SystemUtil.isWindows()) {
|
||||||
return ScmTransportProtocol.NAME + ":///" + bareRepository.getAbsolutePath().replaceAll("\\\\", "/");
|
return ScmTransportProtocol.NAME + ":///" + bareRepository.getAbsolutePath().replaceAll("\\\\", "/");
|
||||||
|
|||||||
@@ -32,8 +32,10 @@ import com.aragost.javahg.commands.PullCommand;
|
|||||||
import com.aragost.javahg.commands.StatusCommand;
|
import com.aragost.javahg.commands.StatusCommand;
|
||||||
import com.aragost.javahg.commands.UpdateCommand;
|
import com.aragost.javahg.commands.UpdateCommand;
|
||||||
import com.aragost.javahg.commands.flags.CloneCommandFlags;
|
import com.aragost.javahg.commands.flags.CloneCommandFlags;
|
||||||
|
import sonia.scm.repository.util.WorkingCopyFailedException;
|
||||||
import sonia.scm.repository.util.WorkingCopyPool;
|
import sonia.scm.repository.util.WorkingCopyPool;
|
||||||
import sonia.scm.repository.util.SimpleWorkingCopyFactory;
|
import sonia.scm.repository.util.SimpleWorkingCopyFactory;
|
||||||
|
import sonia.scm.repository.util.WorkingCopyPool.ParentAndClone;
|
||||||
import sonia.scm.util.IOUtil;
|
import sonia.scm.util.IOUtil;
|
||||||
import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
||||||
|
|
||||||
@@ -54,13 +56,17 @@ public class SimpleHgWorkingCopyFactory extends SimpleWorkingCopyFactory<Reposit
|
|||||||
this.hgRepositoryEnvironmentBuilder = hgRepositoryEnvironmentBuilder;
|
this.hgRepositoryEnvironmentBuilder = hgRepositoryEnvironmentBuilder;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public ParentAndClone<Repository, Repository> cloneRepository(HgCommandContext context, File target, String initialBranch) throws IOException {
|
public ParentAndClone<Repository, Repository> cloneRepository(HgCommandContext context, File target, String initialBranch) throws WorkingCopyFailedException {
|
||||||
Repository centralRepository = openCentral(context);
|
Repository centralRepository = openCentral(context);
|
||||||
CloneCommand cloneCommand = CloneCommandFlags.on(centralRepository);
|
CloneCommand cloneCommand = CloneCommandFlags.on(centralRepository);
|
||||||
if (initialBranch != null) {
|
if (initialBranch != null) {
|
||||||
cloneCommand.updaterev(initialBranch);
|
cloneCommand.updaterev(initialBranch);
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
cloneCommand.execute(target.getAbsolutePath());
|
cloneCommand.execute(target.getAbsolutePath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new WorkingCopyFailedException(e);
|
||||||
|
}
|
||||||
|
|
||||||
BaseRepository clone = Repository.open(target);
|
BaseRepository clone = Repository.open(target);
|
||||||
|
|
||||||
|
|||||||
@@ -31,13 +31,10 @@ import org.junit.Assert;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.junitpioneer.jupiter.TempDirectory;
|
|
||||||
import sonia.scm.repository.HgHookManager;
|
import sonia.scm.repository.HgHookManager;
|
||||||
import sonia.scm.repository.HgTestUtil;
|
import sonia.scm.repository.HgTestUtil;
|
||||||
import sonia.scm.repository.util.CachingAllWorkingCopyPool;
|
import sonia.scm.repository.util.CachingAllWorkingCopyPool;
|
||||||
import sonia.scm.repository.util.NoneCachingWorkingCopyPool;
|
|
||||||
import sonia.scm.repository.util.WorkdirProvider;
|
import sonia.scm.repository.util.WorkdirProvider;
|
||||||
import sonia.scm.repository.util.WorkingCopy;
|
import sonia.scm.repository.util.WorkingCopy;
|
||||||
import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
import sonia.scm.web.HgRepositoryEnvironmentBuilder;
|
||||||
@@ -50,7 +47,6 @@ import java.util.Collections;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
@ExtendWith(TempDirectory.class)
|
|
||||||
public class SimpleHgWorkingCopyFactoryTest extends AbstractHgCommandTestBase {
|
public class SimpleHgWorkingCopyFactoryTest extends AbstractHgCommandTestBase {
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import sonia.scm.repository.Repository;
|
|||||||
import sonia.scm.repository.SvnWorkingCopyFactory;
|
import sonia.scm.repository.SvnWorkingCopyFactory;
|
||||||
import sonia.scm.repository.util.WorkingCopyPool;
|
import sonia.scm.repository.util.WorkingCopyPool;
|
||||||
import sonia.scm.repository.util.SimpleWorkingCopyFactory;
|
import sonia.scm.repository.util.SimpleWorkingCopyFactory;
|
||||||
|
import sonia.scm.repository.util.WorkingCopyPool.ParentAndClone;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|||||||
Reference in New Issue
Block a user