Use clone and push to create branches

Generalize workdir creation for git and hg and create branches in
clones instead of the scm repository, so that hooks will be fired
correctly once the changes are pushed back.

Missing:

- Evaluation of the git response from the push command
- configuration of the hg environment and the authentication, so that
  the scmhooks.py script can be triggeret correctly and can callback
  the scm manager
This commit is contained in:
René Pfeuffer
2019-03-27 10:08:20 +01:00
parent 58b7dff631
commit b65e84249d
25 changed files with 306 additions and 136 deletions

View File

@@ -0,0 +1,25 @@
package sonia.scm.repository.util;
import java.util.function.Consumer;
public class CloseableWrapper<T> implements AutoCloseable {
private final T wrapped;
private final Consumer<T> cleanup;
public CloseableWrapper(T wrapped, Consumer<T> cleanup) {
this.wrapped = wrapped;
this.cleanup = cleanup;
}
public T get() { return wrapped; }
@Override
public void close() {
try {
cleanup.accept(wrapped);
} catch (Throwable t) {
throw new RuntimeException(t);
}
}
}

View File

@@ -0,0 +1,57 @@
package sonia.scm.repository.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Repository;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
public class SimpleWorkdirFactory<T extends AutoCloseable, C> {
private static final Logger logger = LoggerFactory.getLogger(SimpleWorkdirFactory.class);
private final File poolDirectory;
private final CloneProvider<T, C> cloneProvider;
private final Repository repository;
public SimpleWorkdirFactory(Repository repository, CloneProvider<T, C> cloneProvider) {
this(new File(System.getProperty("java.io.tmpdir"), "scmm-work-pool"), repository, cloneProvider);
}
public SimpleWorkdirFactory(File poolDirectory, Repository repository, CloneProvider<T, C> cloneProvider) {
this.poolDirectory = poolDirectory;
this.cloneProvider = cloneProvider;
this.repository = repository;
poolDirectory.mkdirs();
}
public WorkingCopy<T> createWorkingCopy(C context) {
try {
File directory = createNewWorkdir();
T clone = cloneProvider.cloneRepository(context, directory);
return new WorkingCopy<>(clone, this::close, directory);
} catch (IOException e) {
throw new InternalRepositoryException(repository, "could not create temporary directory for clone of repository", e);
}
}
private File createNewWorkdir() throws IOException {
return Files.createTempDirectory(poolDirectory.toPath(),"workdir").toFile();
}
private void close(T repository) {
try {
repository.close();
} catch (Exception e) {
logger.warn("could not close temporary repository clone", e);
}
}
public interface CloneProvider<T, C> {
T cloneRepository(C context, File target) throws IOException;
}
}

View File

@@ -0,0 +1,5 @@
package sonia.scm.repository.util;
public interface WorkdirFactory<T, C> {
WorkingCopy<T> createWorkingCopy(C gitContext);
}

View File

@@ -0,0 +1,31 @@
package sonia.scm.repository.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.util.IOUtil;
import java.io.File;
import java.io.IOException;
import java.util.function.Consumer;
public class WorkingCopy<T> extends CloseableWrapper<T> {
private static final Logger LOG = LoggerFactory.getLogger(WorkingCopy.class);
private final File directory;
public WorkingCopy(T wrapped, Consumer<T> cleanup, File directory) {
super(wrapped, cleanup);
this.directory = directory;
}
@Override
public void close() {
super.close();
try {
IOUtil.delete(directory);
} catch (IOException e) {
LOG.warn("could not delete temporary workdir '{}'", directory, e);
}
}
}