Cleanup worker

This commit is contained in:
Rene Pfeuffer
2019-11-11 13:35:13 +01:00
parent 21d930cbbe
commit 5cff9f8c16

View File

@@ -5,6 +5,7 @@ import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeResult;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.IndexDiff;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Repository;
@@ -23,6 +24,8 @@ import java.io.IOException;
import java.util.Set;
import static org.eclipse.jgit.merge.MergeStrategy.RECURSIVE;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
public class GitMergeCommand extends AbstractGitCommand implements MergeCommand {
@@ -46,8 +49,7 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
@Override
public MergeConflictResult computeConflicts(MergeCommandRequest request) {
WorkingCopyCloser closer = new WorkingCopyCloser();
return inClone(git -> new ConflictWorker(git, request, closer), workdirFactory, request.getTargetBranch());
return inClone(git -> new ConflictWorker(git, request), workdirFactory, request.getTargetBranch());
}
private MergeCommandResult mergeWithStrategy(MergeCommandRequest request) {
@@ -91,68 +93,79 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
}
private class ConflictWorker extends GitCloneWorker<MergeConflictResult> {
private final Git git;
private final MergeCommandRequest request;
private final WorkingCopyCloser closer;
private final String branchToMerge;
private final String targetBranch;
private final CanonicalTreeParser treeParser;
private final ObjectId treeId;
private final ByteArrayOutputStream diffBuffer;
private ConflictWorker(Git git, MergeCommandRequest request, WorkingCopyCloser closer) {
private final MergeConflictResult result = new MergeConflictResult();
private ConflictWorker(Git git, MergeCommandRequest request) {
super(git, context, repository);
this.git = git;
this.request = request;
this.closer = closer;
branchToMerge = request.getBranchToMerge();
targetBranch = request.getTargetBranch();
treeParser = new CanonicalTreeParser();
treeId = git.getRepository().resolve(request.getTargetBranch() + "^{tree}");
diffBuffer = new ByteArrayOutputStream();
try {
treeId = git.getRepository().resolve(request.getTargetBranch() + "^{tree}");
} catch (IOException e) {
throw notFound(entity("branch", request.getTargetBranch()).in(repository));
}
}
@Override
MergeConflictResult run() throws IOException {
MergeResult mergeResult = doTemporaryMerge();
if (mergeResult.getConflicts() == null) {
return new MergeConflictResult();
if (mergeResult.getConflicts() != null) {
getStatus().getConflictingStageState().forEach(this::computeConflict);
}
Status status = getStatus();
MergeConflictResult result = new MergeConflictResult();
status.getConflictingStageState().forEach((path, value) -> {
switch (value) {
case BOTH_MODIFIED:
diffBuffer.reset();
try (ObjectReader reader = git.getRepository().newObjectReader()) {
treeParser.reset(reader, treeId);
git
.diff()
.setOldTree(treeParser)
.setPathFilter(PathFilter.create(path))
.setOutputStream(diffBuffer)
.call();
result.addBothModified(path, diffBuffer.toString());
} catch (GitAPIException | IOException e) {
throw new InternalRepositoryException(repository, "could not calculate diff for path " + path, e);
} finally {
closer.close();
}
break;
case DELETED_BY_THEM:
result.addDeletedByThem(path);
break;
case DELETED_BY_US:
result.addDeletedByUs(path);
break;
default:
throw new InternalRepositoryException(context.getRepository(), "unexpected conflict type: " + value);
}
});
return result;
}
private void computeConflict(String path, IndexDiff.StageState stageState) {
switch (stageState) {
case BOTH_MODIFIED:
diffBuffer.reset();
try (ObjectReader reader = getClone().getRepository().newObjectReader()) {
treeParser.reset(reader, treeId);
getClone()
.diff()
.setOldTree(treeParser)
.setPathFilter(PathFilter.create(path))
.setOutputStream(diffBuffer)
.call();
result.addBothModified(path, diffBuffer.toString());
} catch (GitAPIException | IOException e) {
throw new InternalRepositoryException(repository, "could not calculate diff for path " + path, e);
}
break;
case DELETED_BY_THEM:
result.addDeletedByThem(path);
break;
case DELETED_BY_US:
result.addDeletedByUs(path);
break;
default:
throw new InternalRepositoryException(context.getRepository(), "unexpected conflict type: " + stageState);
}
}
private MergeResult doTemporaryMerge() throws IOException {
ObjectId sourceRevision = resolveRevision(branchToMerge);
try {
return getClone().merge()
.setFastForward(org.eclipse.jgit.api.MergeCommand.FastForwardMode.NO_FF)
.setCommit(false)
.include(branchToMerge, sourceRevision)
.call();
} catch (GitAPIException e) {
throw new InternalRepositoryException(context.getRepository(), "could not merge branch " + branchToMerge + " into " + targetBranch, e);
}
}
private Status getStatus() {
Status status;
try {
@@ -162,20 +175,5 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
}
return status;
}
private MergeResult doTemporaryMerge() throws IOException {
ObjectId sourceRevision = resolveRevision(request.getBranchToMerge());
MergeResult mergeResult;
try {
mergeResult = getClone().merge()
.setFastForward(org.eclipse.jgit.api.MergeCommand.FastForwardMode.NO_FF)
.setCommit(false)
.include(request.getBranchToMerge(), sourceRevision)
.call();
} catch (GitAPIException e) {
throw new InternalRepositoryException(context.getRepository(), "could not merge branch " + request.getBranchToMerge() + " into " + request.getTargetBranch(), e);
}
return mergeResult;
}
}
}