Differentiate types for central and cloned repository

This commit is contained in:
Rene Pfeuffer
2019-10-21 14:10:50 +02:00
parent f7b8050dfa
commit a93380b867
13 changed files with 73 additions and 45 deletions

View File

@@ -8,7 +8,7 @@ import sonia.scm.repository.Repository;
import java.io.File;
import java.io.IOException;
public abstract class SimpleWorkdirFactory<R, C> implements WorkdirFactory<R, C> {
public abstract class SimpleWorkdirFactory<R, W, C> implements WorkdirFactory<R, W, C> {
private static final Logger logger = LoggerFactory.getLogger(SimpleWorkdirFactory.class);
@@ -19,11 +19,11 @@ public abstract class SimpleWorkdirFactory<R, C> implements WorkdirFactory<R, C>
}
@Override
public WorkingCopy<R> createWorkingCopy(C context, String initialBranch) {
public WorkingCopy<R, W> createWorkingCopy(C context, String initialBranch) {
try {
File directory = workdirProvider.createNewWorkdir();
ParentAndClone<R> parentAndClone = cloneRepository(context, directory, initialBranch);
return new WorkingCopy<>(parentAndClone.getClone(), parentAndClone.getParent(), this::close, directory);
ParentAndClone<R, W> parentAndClone = cloneRepository(context, directory, initialBranch);
return new WorkingCopy<>(parentAndClone.getClone(), parentAndClone.getParent(), this::closeWorkdir, this::closeCentral, directory);
} catch (IOException e) {
throw new InternalRepositoryException(getScmRepository(context), "could not clone repository in temporary directory", e);
}
@@ -34,10 +34,11 @@ public abstract class SimpleWorkdirFactory<R, C> implements WorkdirFactory<R, C>
@SuppressWarnings("squid:S00112")
// We do allow implementations to throw arbitrary exceptions here, so that we can handle them in close
protected abstract void closeRepository(R repository) throws Exception;
protected abstract void closeWorkdirInternal(W workdir) throws Exception;
protected abstract ParentAndClone<R> cloneRepository(C context, File target, String initialBranch) throws IOException;
protected abstract ParentAndClone<R, W> cloneRepository(C context, File target, String initialBranch) throws IOException;
private void close(R repository) {
private void closeCentral(R repository) {
try {
closeRepository(repository);
} catch (Exception e) {
@@ -45,11 +46,19 @@ public abstract class SimpleWorkdirFactory<R, C> implements WorkdirFactory<R, C>
}
}
protected static class ParentAndClone<R> {
private final R parent;
private final R clone;
private void closeWorkdir(W repository) {
try {
closeWorkdirInternal(repository);
} catch (Exception e) {
logger.warn("could not close temporary repository clone", e);
}
}
public ParentAndClone(R parent, R clone) {
protected static class ParentAndClone<R, W> {
private final R parent;
private final W clone;
public ParentAndClone(R parent, W clone) {
this.parent = parent;
this.clone = clone;
}
@@ -58,7 +67,7 @@ public abstract class SimpleWorkdirFactory<R, C> implements WorkdirFactory<R, C>
return parent;
}
public R getClone() {
public W getClone() {
return clone;
}
}

View File

@@ -1,5 +1,5 @@
package sonia.scm.repository.util;
public interface WorkdirFactory<R, C> {
WorkingCopy<R> createWorkingCopy(C context, String initialBranch);
public interface WorkdirFactory<R, W, C> {
WorkingCopy<R, W> createWorkingCopy(C context, String initialBranch);
}

View File

@@ -8,23 +8,25 @@ import java.io.File;
import java.io.IOException;
import java.util.function.Consumer;
public class WorkingCopy<R> implements AutoCloseable {
public class WorkingCopy<R, W> implements AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(WorkingCopy.class);
private final File directory;
private final R workingRepository;
private final W workingRepository;
private final R centralRepository;
private final Consumer<R> cleanup;
private final Consumer<W> cleanupWorkdir;
private final Consumer<R> cleanupCentral;
public WorkingCopy(R workingRepository, R centralRepository, Consumer<R> cleanup, File directory) {
public WorkingCopy(W workingRepository, R centralRepository, Consumer<W> cleanupWorkdir, Consumer<R> cleanupCentral, File directory) {
this.directory = directory;
this.workingRepository = workingRepository;
this.centralRepository = centralRepository;
this.cleanup = cleanup;
this.cleanupCentral = cleanupCentral;
this.cleanupWorkdir = cleanupWorkdir;
}
public R getWorkingRepository() {
public W getWorkingRepository() {
return workingRepository;
}
@@ -39,8 +41,8 @@ public class WorkingCopy<R> implements AutoCloseable {
@Override
public void close() {
try {
cleanup.accept(workingRepository);
cleanup.accept(centralRepository);
cleanupWorkdir.accept(workingRepository);
cleanupCentral.accept(centralRepository);
IOUtil.delete(directory);
} catch (IOException e) {
LOG.warn("could not delete temporary workdir '{}'", directory, e);

View File

@@ -24,14 +24,14 @@ public class SimpleWorkdirFactoryTest {
@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();
private SimpleWorkdirFactory<Closeable, Context> simpleWorkdirFactory;
private SimpleWorkdirFactory<Closeable, Closeable, Context> simpleWorkdirFactory;
private String initialBranchForLastCloneCall;
@Before
public void initFactory() throws IOException {
WorkdirProvider workdirProvider = new WorkdirProvider(temporaryFolder.newFolder());
simpleWorkdirFactory = new SimpleWorkdirFactory<Closeable, Context>(workdirProvider) {
simpleWorkdirFactory = new SimpleWorkdirFactory<Closeable, Closeable, Context>(workdirProvider) {
@Override
protected Repository getScmRepository(Context context) {
return REPOSITORY;
@@ -43,7 +43,12 @@ public class SimpleWorkdirFactoryTest {
}
@Override
protected ParentAndClone<Closeable> cloneRepository(Context context, File target, String initialBranch) {
protected void closeWorkdirInternal(Closeable workdir) throws Exception {
workdir.close();
}
@Override
protected ParentAndClone<Closeable, Closeable> cloneRepository(Context context, File target, String initialBranch) {
initialBranchForLastCloneCall = initialBranch;
return new ParentAndClone<>(parent, clone);
}
@@ -53,7 +58,7 @@ public class SimpleWorkdirFactoryTest {
@Test
public void shouldCreateParentAndClone() {
Context context = new Context();
try (WorkingCopy<Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {
try (WorkingCopy<Closeable, Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {
assertThat(workingCopy.getCentralRepository()).isSameAs(parent);
assertThat(workingCopy.getWorkingRepository()).isSameAs(clone);
}
@@ -62,7 +67,7 @@ public class SimpleWorkdirFactoryTest {
@Test
public void shouldCloseParent() throws IOException {
Context context = new Context();
try (WorkingCopy<Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {}
try (WorkingCopy<Closeable, Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {}
verify(parent).close();
}
@@ -70,7 +75,7 @@ public class SimpleWorkdirFactoryTest {
@Test
public void shouldCloseClone() throws IOException {
Context context = new Context();
try (WorkingCopy<Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {}
try (WorkingCopy<Closeable, Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, null)) {}
verify(clone).close();
}
@@ -78,7 +83,7 @@ public class SimpleWorkdirFactoryTest {
@Test
public void shouldPropagateInitialBranch() {
Context context = new Context();
try (WorkingCopy<Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, "some")) {
try (WorkingCopy<Closeable, Closeable> workingCopy = simpleWorkdirFactory.createWorkingCopy(context, "some")) {
assertThat(initialBranchForLastCloneCall).isEqualTo("some");
}
}

View File

@@ -4,5 +4,5 @@ import org.eclipse.jgit.lib.Repository;
import sonia.scm.repository.spi.GitContext;
import sonia.scm.repository.util.WorkdirFactory;
public interface GitWorkdirFactory extends WorkdirFactory<Repository, GitContext> {
public interface GitWorkdirFactory extends WorkdirFactory<Repository, Repository, GitContext> {
}

View File

@@ -142,7 +142,7 @@ class AbstractGitCommand
}
<R, W extends GitCloneWorker<R>> R inClone(Function<Git, W> workerSupplier, GitWorkdirFactory workdirFactory, String initialBranch) {
try (WorkingCopy<Repository> workingCopy = workdirFactory.createWorkingCopy(context, initialBranch)) {
try (WorkingCopy<Repository, Repository> workingCopy = workdirFactory.createWorkingCopy(context, initialBranch)) {
Repository repository = workingCopy.getWorkingRepository();
logger.debug("cloned repository to folder {}", repository.getWorkTree());
return workerSupplier.apply(new Git(repository)).run();

View File

@@ -58,7 +58,7 @@ public class GitBranchCommand extends AbstractGitCommand implements BranchComman
@Override
public Branch branch(BranchRequest request) {
try (WorkingCopy<org.eclipse.jgit.lib.Repository> workingCopy = workdirFactory.createWorkingCopy(context, request.getParentBranch())) {
try (WorkingCopy<org.eclipse.jgit.lib.Repository, org.eclipse.jgit.lib.Repository> workingCopy = workdirFactory.createWorkingCopy(context, request.getParentBranch())) {
Git clone = new Git(workingCopy.getWorkingRepository());
Ref ref = clone.branchCreate().setName(request.getNewBranch()).call();
Iterable<PushResult> call = clone.push().add(request.getNewBranch()).call();

View File

@@ -18,7 +18,7 @@ import java.io.IOException;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
public class SimpleGitWorkdirFactory extends SimpleWorkdirFactory<Repository, GitContext> implements GitWorkdirFactory {
public class SimpleGitWorkdirFactory extends SimpleWorkdirFactory<Repository, Repository, GitContext> implements GitWorkdirFactory {
@Inject
public SimpleGitWorkdirFactory(WorkdirProvider workdirProvider) {
@@ -26,7 +26,7 @@ public class SimpleGitWorkdirFactory extends SimpleWorkdirFactory<Repository, Gi
}
@Override
public ParentAndClone<Repository> cloneRepository(GitContext context, File target, String initialBranch) {
public ParentAndClone<Repository, Repository> cloneRepository(GitContext context, File target, String initialBranch) {
try {
Repository clone = Git.cloneRepository()
.setURI(createScmTransportProtocolUri(context.getDirectory()))
@@ -60,6 +60,13 @@ public class SimpleGitWorkdirFactory extends SimpleWorkdirFactory<Repository, Gi
}
}
@Override
protected void closeWorkdirInternal(Repository workdir) throws Exception {
if (workdir != null) {
workdir.close();
}
}
@Override
protected sonia.scm.repository.Repository getScmRepository(GitContext context) {
return context.getRepository();

View File

@@ -45,7 +45,7 @@ public class SimpleGitWorkdirFactoryTest extends AbstractGitCommandTestBase {
SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider);
File masterRepo = createRepositoryDirectory();
try (WorkingCopy<Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
try (WorkingCopy<Repository, Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
assertThat(workingCopy.getDirectory())
.exists()
@@ -62,7 +62,7 @@ public class SimpleGitWorkdirFactoryTest extends AbstractGitCommandTestBase {
public void shouldCheckoutInitialBranch() {
SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider);
try (WorkingCopy<Repository> workingCopy = factory.createWorkingCopy(createContext(), "test-branch")) {
try (WorkingCopy<Repository, Repository> workingCopy = factory.createWorkingCopy(createContext(), "test-branch")) {
assertThat(new File(workingCopy.getWorkingRepository().getWorkTree(), "a.txt"))
.exists()
.isFile()
@@ -75,10 +75,10 @@ public class SimpleGitWorkdirFactoryTest extends AbstractGitCommandTestBase {
SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider);
File firstDirectory;
try (WorkingCopy<Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
try (WorkingCopy<Repository, Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
firstDirectory = workingCopy.getDirectory();
}
try (WorkingCopy<Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
try (WorkingCopy<Repository, Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
File secondDirectory = workingCopy.getDirectory();
assertThat(secondDirectory).isNotEqualTo(firstDirectory);
}
@@ -89,7 +89,7 @@ public class SimpleGitWorkdirFactoryTest extends AbstractGitCommandTestBase {
SimpleGitWorkdirFactory factory = new SimpleGitWorkdirFactory(workdirProvider);
File directory;
try (WorkingCopy<Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
try (WorkingCopy<Repository, Repository> workingCopy = factory.createWorkingCopy(createContext(), null)) {
directory = workingCopy.getWorkingRepository().getWorkTree();
}
assertThat(directory).doesNotExist();

View File

@@ -59,7 +59,7 @@ public class HgBranchCommand extends AbstractCommand implements BranchCommand {
@Override
public Branch branch(BranchRequest request) {
try (WorkingCopy<com.aragost.javahg.Repository> workingCopy = workdirFactory.createWorkingCopy(getContext(), request.getParentBranch())) {
try (WorkingCopy<com.aragost.javahg.Repository, com.aragost.javahg.Repository> workingCopy = workdirFactory.createWorkingCopy(getContext(), request.getParentBranch())) {
com.aragost.javahg.Repository repository = workingCopy.getWorkingRepository();
Changeset emptyChangeset = createNewBranchWithEmptyCommit(request, repository);
@@ -83,7 +83,7 @@ public class HgBranchCommand extends AbstractCommand implements BranchCommand {
.execute();
}
private void pullNewBranchIntoCentralRepository(BranchRequest request, WorkingCopy<com.aragost.javahg.Repository> workingCopy) {
private void pullNewBranchIntoCentralRepository(BranchRequest request, WorkingCopy<com.aragost.javahg.Repository, com.aragost.javahg.Repository> workingCopy) {
try {
PullCommand pullCommand = PullCommand.on(workingCopy.getCentralRepository());
workdirFactory.configure(pullCommand);

View File

@@ -29,7 +29,7 @@ public class HgModifyCommand implements ModifyCommand {
@Override
public String execute(ModifyCommandRequest request) {
try (WorkingCopy<com.aragost.javahg.Repository> workingCopy = workdirFactory.createWorkingCopy(context, request.getBranch())) {
try (WorkingCopy<com.aragost.javahg.Repository, com.aragost.javahg.Repository> workingCopy = workdirFactory.createWorkingCopy(context, request.getBranch())) {
Repository workingRepository = workingCopy.getWorkingRepository();
request.getRequests().forEach(
partialRequest -> {
@@ -85,7 +85,7 @@ public class HgModifyCommand implements ModifyCommand {
}
}
private List<Changeset> pullModifyChangesToCentralRepository(ModifyCommandRequest request, WorkingCopy<com.aragost.javahg.Repository> workingCopy) {
private List<Changeset> pullModifyChangesToCentralRepository(ModifyCommandRequest request, WorkingCopy<com.aragost.javahg.Repository, com.aragost.javahg.Repository> workingCopy) {
try {
com.aragost.javahg.commands.PullCommand pullCommand = PullCommand.on(workingCopy.getCentralRepository());
workdirFactory.configure(pullCommand);

View File

@@ -4,6 +4,6 @@ import com.aragost.javahg.Repository;
import com.aragost.javahg.commands.PullCommand;
import sonia.scm.repository.util.WorkdirFactory;
public interface HgWorkdirFactory extends WorkdirFactory<Repository, HgCommandContext> {
public interface HgWorkdirFactory extends WorkdirFactory<Repository, Repository, HgCommandContext> {
void configure(PullCommand pullCommand);
}

View File

@@ -16,7 +16,7 @@ import java.io.IOException;
import java.util.Map;
import java.util.function.BiConsumer;
public class SimpleHgWorkdirFactory extends SimpleWorkdirFactory<Repository, HgCommandContext> implements HgWorkdirFactory {
public class SimpleHgWorkdirFactory extends SimpleWorkdirFactory<Repository, Repository, HgCommandContext> implements HgWorkdirFactory {
private final Provider<HgRepositoryEnvironmentBuilder> hgRepositoryEnvironmentBuilder;
@@ -26,7 +26,7 @@ public class SimpleHgWorkdirFactory extends SimpleWorkdirFactory<Repository, HgC
this.hgRepositoryEnvironmentBuilder = hgRepositoryEnvironmentBuilder;
}
@Override
public ParentAndClone<Repository> cloneRepository(HgCommandContext context, File target, String initialBranch) throws IOException {
public ParentAndClone<Repository, Repository> cloneRepository(HgCommandContext context, File target, String initialBranch) throws IOException {
BiConsumer<sonia.scm.repository.Repository, Map<String, String>> repositoryMapBiConsumer =
(repository, environment) -> hgRepositoryEnvironmentBuilder.get().buildFor(repository, null, environment);
Repository centralRepository = context.openWithSpecialEnvironment(repositoryMapBiConsumer);
@@ -46,6 +46,11 @@ public class SimpleHgWorkdirFactory extends SimpleWorkdirFactory<Repository, HgC
repository.close();
}
@Override
protected void closeWorkdirInternal(Repository workdir) throws Exception {
workdir.close();
}
@Override
protected sonia.scm.repository.Repository getScmRepository(HgCommandContext context) {
return context.getScmRepository();