mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 00:15:44 +01:00
Move conflict computation to merge command
Therefore revert changes to diff command and introduce new MergeConflictResult instead of streaming result.
This commit is contained in:
@@ -7,4 +7,6 @@ public interface MergeCommand {
|
|||||||
MergeCommandResult merge(MergeCommandRequest request);
|
MergeCommandResult merge(MergeCommandRequest request);
|
||||||
|
|
||||||
MergeDryRunCommandResult dryRun(MergeCommandRequest request);
|
MergeDryRunCommandResult dryRun(MergeCommandRequest request);
|
||||||
|
|
||||||
|
MergeConflictResult computeConflicts(MergeCommandRequest request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package sonia.scm.repository.spi;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static sonia.scm.repository.spi.MergeConflictResult.ConflictTypes.BOTH_MODIFIED;
|
||||||
|
import static sonia.scm.repository.spi.MergeConflictResult.ConflictTypes.DELETED_BY_THEM;
|
||||||
|
import static sonia.scm.repository.spi.MergeConflictResult.ConflictTypes.DELETED_BY_US;
|
||||||
|
|
||||||
|
public class MergeConflictResult {
|
||||||
|
|
||||||
|
private final List<SingleMergeConflict> conflicts = new LinkedList<>();
|
||||||
|
|
||||||
|
public List<SingleMergeConflict> getConflicts() {
|
||||||
|
return Collections.unmodifiableList(conflicts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addBothModified(String path, String diff) {
|
||||||
|
conflicts.add(new SingleMergeConflict(BOTH_MODIFIED, path, diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDeletedByThem(String path) {
|
||||||
|
conflicts.add(new SingleMergeConflict(DELETED_BY_THEM, path, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDeletedByUs(String path) {
|
||||||
|
conflicts.add(new SingleMergeConflict(DELETED_BY_US, path, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SingleMergeConflict {
|
||||||
|
private final ConflictTypes type;
|
||||||
|
private final String path;
|
||||||
|
private final String diff;
|
||||||
|
|
||||||
|
private SingleMergeConflict(ConflictTypes type, String path, String diff) {
|
||||||
|
this.type = type;
|
||||||
|
this.path = path;
|
||||||
|
this.diff = diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConflictTypes getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDiff() {
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ConflictTypes {
|
||||||
|
BOTH_MODIFIED, DELETED_BY_THEM, DELETED_BY_US
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import org.eclipse.jgit.revwalk.RevCommit;
|
|||||||
import org.eclipse.jgit.revwalk.RevTree;
|
import org.eclipse.jgit.revwalk.RevTree;
|
||||||
import org.eclipse.jgit.revwalk.RevWalk;
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
|
import org.eclipse.jgit.treewalk.EmptyTreeIterator;
|
||||||
import org.eclipse.jgit.treewalk.FileTreeIterator;
|
|
||||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||||
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
||||||
import sonia.scm.repository.GitUtil;
|
import sonia.scm.repository.GitUtil;
|
||||||
@@ -38,17 +37,6 @@ final class Differ implements AutoCloseable {
|
|||||||
private static Differ create(Repository repository, DiffCommandRequest request) throws IOException {
|
private static Differ create(Repository repository, DiffCommandRequest request) throws IOException {
|
||||||
RevWalk walk = new RevWalk(repository);
|
RevWalk walk = new RevWalk(repository);
|
||||||
|
|
||||||
if (!Strings.isNullOrEmpty(request.getMergeChangeset()))
|
|
||||||
{
|
|
||||||
ObjectId otherRevision = repository.resolve(request.getMergeChangeset());
|
|
||||||
RevTree tree = walk.parseCommit(otherRevision).getTree();
|
|
||||||
TreeWalk treeWalk = new TreeWalk(repository);
|
|
||||||
treeWalk.addTree(tree);
|
|
||||||
treeWalk.addTree(new FileTreeIterator( repository ));
|
|
||||||
return new Differ(null, walk, treeWalk);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
|
|
||||||
ObjectId revision = repository.resolve(request.getRevision());
|
ObjectId revision = repository.resolve(request.getRevision());
|
||||||
RevCommit commit = walk.parseCommit(revision);
|
RevCommit commit = walk.parseCommit(revision);
|
||||||
|
|
||||||
@@ -58,25 +46,34 @@ final class Differ implements AutoCloseable {
|
|||||||
treeWalk.reset();
|
treeWalk.reset();
|
||||||
treeWalk.setRecursive(true);
|
treeWalk.setRecursive(true);
|
||||||
|
|
||||||
if (Util.isNotEmpty(request.getPath())) {
|
if (Util.isNotEmpty(request.getPath()))
|
||||||
|
{
|
||||||
treeWalk.setFilter(PathFilter.create(request.getPath()));
|
treeWalk.setFilter(PathFilter.create(request.getPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!Strings.isNullOrEmpty(request.getAncestorChangeset())) {
|
if (!Strings.isNullOrEmpty(request.getAncestorChangeset()))
|
||||||
|
{
|
||||||
ObjectId otherRevision = repository.resolve(request.getAncestorChangeset());
|
ObjectId otherRevision = repository.resolve(request.getAncestorChangeset());
|
||||||
ObjectId ancestorId = GitUtil.computeCommonAncestor(repository, revision, otherRevision);
|
ObjectId ancestorId = GitUtil.computeCommonAncestor(repository, revision, otherRevision);
|
||||||
RevTree tree = walk.parseCommit(ancestorId).getTree();
|
RevTree tree = walk.parseCommit(ancestorId).getTree();
|
||||||
treeWalk.addTree(tree);
|
treeWalk.addTree(tree);
|
||||||
} else if (commit.getParentCount() > 0) {
|
}
|
||||||
|
else if (commit.getParentCount() > 0)
|
||||||
|
{
|
||||||
RevTree tree = commit.getParent(0).getTree();
|
RevTree tree = commit.getParent(0).getTree();
|
||||||
|
|
||||||
if (tree != null) {
|
if (tree != null)
|
||||||
|
{
|
||||||
treeWalk.addTree(tree);
|
treeWalk.addTree(tree);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
treeWalk.addTree(new EmptyTreeIterator());
|
treeWalk.addTree(new EmptyTreeIterator());
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
treeWalk.addTree(new EmptyTreeIterator());
|
treeWalk.addTree(new EmptyTreeIterator());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +81,6 @@ final class Differ implements AutoCloseable {
|
|||||||
|
|
||||||
return new Differ(commit, walk, treeWalk);
|
return new Differ(commit, walk, treeWalk);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private Diff diff() throws IOException {
|
private Diff diff() throws IOException {
|
||||||
List<DiffEntry> entries = DiffEntry.scan(treeWalk);
|
List<DiffEntry> entries = DiffEntry.scan(treeWalk);
|
||||||
|
|||||||
@@ -31,21 +31,12 @@
|
|||||||
|
|
||||||
package sonia.scm.repository.spi;
|
package sonia.scm.repository.spi;
|
||||||
|
|
||||||
import com.google.common.base.Strings;
|
|
||||||
import org.eclipse.jgit.api.MergeCommand;
|
|
||||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
|
||||||
import org.eclipse.jgit.diff.DiffEntry;
|
import org.eclipse.jgit.diff.DiffEntry;
|
||||||
import org.eclipse.jgit.diff.DiffFormatter;
|
import org.eclipse.jgit.diff.DiffFormatter;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
|
||||||
import org.eclipse.jgit.lib.ObjectReader;
|
|
||||||
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
|
|
||||||
import sonia.scm.repository.GitWorkdirFactory;
|
|
||||||
import sonia.scm.repository.InternalRepositoryException;
|
|
||||||
import sonia.scm.repository.Repository;
|
import sonia.scm.repository.Repository;
|
||||||
import sonia.scm.repository.api.DiffCommandBuilder;
|
import sonia.scm.repository.api.DiffCommandBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -53,64 +44,22 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public class GitDiffCommand extends AbstractGitCommand implements DiffCommand {
|
public class GitDiffCommand extends AbstractGitCommand implements DiffCommand {
|
||||||
|
|
||||||
private final GitWorkdirFactory workdirFactory;
|
GitDiffCommand(GitContext context, Repository repository) {
|
||||||
|
|
||||||
GitDiffCommand(GitContext context, Repository repository, GitWorkdirFactory workdirFactory) {
|
|
||||||
super(context, repository);
|
super(context, repository);
|
||||||
this.workdirFactory = workdirFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DiffCommandBuilder.OutputStreamConsumer getDiffResult(DiffCommandRequest request) throws IOException {
|
public DiffCommandBuilder.OutputStreamConsumer getDiffResult(DiffCommandRequest request) throws IOException {
|
||||||
if (Strings.isNullOrEmpty(request.getMergeChangeset())) {
|
@SuppressWarnings("squid:S2095") // repository will be closed with the RepositoryService
|
||||||
Differ.Diff diff = Differ.diff(open(), request);
|
org.eclipse.jgit.lib.Repository repository = open();
|
||||||
return computeDiff(diff.getEntries(), open());
|
|
||||||
} else {
|
|
||||||
WorkingCopyCloser closer = new WorkingCopyCloser();
|
|
||||||
return inCloneWithPostponedClose(git -> new GitCloneWorker<DiffCommandBuilder.OutputStreamConsumer>(git) {
|
|
||||||
@Override
|
|
||||||
DiffCommandBuilder.OutputStreamConsumer run() throws IOException {
|
|
||||||
ObjectId sourceRevision = resolveRevision(request.getRevision());
|
|
||||||
try {
|
|
||||||
getClone().merge()
|
|
||||||
.setFastForward(MergeCommand.FastForwardMode.NO_FF)
|
|
||||||
.setCommit(false) // we want to set the author manually
|
|
||||||
.include(request.getRevision(), sourceRevision)
|
|
||||||
.call();
|
|
||||||
} catch (GitAPIException e) {
|
|
||||||
throw new InternalRepositoryException(context.getRepository(), "could not merge branch " + request.getRevision() + " into " + request.getMergeChangeset(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return outputStream -> {
|
Differ.Diff diff = Differ.diff(repository, request);
|
||||||
CanonicalTreeParser treeParser = new CanonicalTreeParser();
|
|
||||||
ObjectId treeId = git.getRepository().resolve(request.getMergeChangeset() + "^{tree}");
|
|
||||||
try (ObjectReader reader = git.getRepository().newObjectReader()) {
|
|
||||||
treeParser.reset(reader, treeId);
|
|
||||||
git
|
|
||||||
.diff()
|
|
||||||
.setOldTree(treeParser)
|
|
||||||
.setOutputStream(outputStream)
|
|
||||||
.call();
|
|
||||||
DiffCommandRequest clone = request.clone();
|
|
||||||
clone.setRevision(sourceRevision.name());
|
|
||||||
} catch (GitAPIException e) {
|
|
||||||
throw new InternalRepositoryException(repository, "could not calculate diff", e);
|
|
||||||
} finally {
|
|
||||||
closer.close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, workdirFactory, request.getMergeChangeset(), closer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private DiffCommandBuilder.OutputStreamConsumer computeDiff(List<DiffEntry> entries, org.eclipse.jgit.lib.Repository repository) throws IOException {
|
|
||||||
|
|
||||||
return output -> {
|
return output -> {
|
||||||
try (DiffFormatter formatter = new DiffFormatter(output)) {
|
try (DiffFormatter formatter = new DiffFormatter(output)) {
|
||||||
formatter.setRepository(repository);
|
formatter.setRepository(repository);
|
||||||
|
|
||||||
for (DiffEntry e : entries) {
|
for (DiffEntry e : diff.getEntries()) {
|
||||||
if (!e.getOldId().equals(e.getNewId())) {
|
if (!e.getOldId().equals(e.getNewId())) {
|
||||||
formatter.format(e);
|
formatter.format(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,15 @@ import com.google.common.base.Strings;
|
|||||||
import org.eclipse.jgit.api.Git;
|
import org.eclipse.jgit.api.Git;
|
||||||
import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
|
import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
|
||||||
import org.eclipse.jgit.api.MergeResult;
|
import org.eclipse.jgit.api.MergeResult;
|
||||||
|
import org.eclipse.jgit.api.Status;
|
||||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||||
import org.eclipse.jgit.lib.ObjectId;
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.ObjectReader;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.eclipse.jgit.merge.MergeStrategy;
|
import org.eclipse.jgit.merge.MergeStrategy;
|
||||||
import org.eclipse.jgit.merge.ResolveMerger;
|
import org.eclipse.jgit.merge.ResolveMerger;
|
||||||
|
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
|
||||||
|
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import sonia.scm.repository.GitWorkdirFactory;
|
import sonia.scm.repository.GitWorkdirFactory;
|
||||||
@@ -17,6 +21,7 @@ import sonia.scm.repository.Person;
|
|||||||
import sonia.scm.repository.api.MergeCommandResult;
|
import sonia.scm.repository.api.MergeCommandResult;
|
||||||
import sonia.scm.repository.api.MergeDryRunCommandResult;
|
import sonia.scm.repository.api.MergeDryRunCommandResult;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
@@ -55,6 +60,12 @@ 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());
|
||||||
|
}
|
||||||
|
|
||||||
private class MergeWorker extends GitCloneWorker<MergeCommandResult> {
|
private class MergeWorker extends GitCloneWorker<MergeCommandResult> {
|
||||||
|
|
||||||
private final String target;
|
private final String target;
|
||||||
@@ -115,4 +126,82 @@ public class GitMergeCommand extends AbstractGitCommand implements MergeCommand
|
|||||||
return MergeCommandResult.failure(result.getConflicts().keySet());
|
return MergeCommandResult.failure(result.getConflicts().keySet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class ConflictWorker extends GitCloneWorker<MergeConflictResult> {
|
||||||
|
private final Git git;
|
||||||
|
private final MergeCommandRequest request;
|
||||||
|
private final WorkingCopyCloser closer;
|
||||||
|
|
||||||
|
private ConflictWorker(Git git, MergeCommandRequest request, WorkingCopyCloser closer) {
|
||||||
|
super(git);
|
||||||
|
this.git = git;
|
||||||
|
this.request = request;
|
||||||
|
this.closer = closer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
MergeConflictResult run() throws IOException {
|
||||||
|
ObjectId sourceRevision = resolveRevision(request.getBranchToMerge());
|
||||||
|
MergeResult mergeResult;
|
||||||
|
try {
|
||||||
|
mergeResult = getClone().merge()
|
||||||
|
.setFastForward(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mergeResult.getConflicts() == null) {
|
||||||
|
return new MergeConflictResult();
|
||||||
|
}
|
||||||
|
Status status;
|
||||||
|
try {
|
||||||
|
status = getClone().status().call();
|
||||||
|
} catch (GitAPIException e) {
|
||||||
|
throw new InternalRepositoryException(context.getRepository(), "could not get status", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
MergeConflictResult result = new MergeConflictResult();
|
||||||
|
|
||||||
|
CanonicalTreeParser treeParser = new CanonicalTreeParser();
|
||||||
|
ObjectId treeId = git.getRepository().resolve(request.getTargetBranch() + "^{tree}");
|
||||||
|
|
||||||
|
ByteArrayOutputStream diffBuffer = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
status.getConflictingStageState().entrySet().forEach(conflictEntry -> {
|
||||||
|
|
||||||
|
String path = conflictEntry.getKey();
|
||||||
|
switch (conflictEntry.getValue()) {
|
||||||
|
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: " + conflictEntry.getValue());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ public class GitRepositoryServiceProvider extends RepositoryServiceProvider
|
|||||||
@Override
|
@Override
|
||||||
public DiffCommand getDiffCommand()
|
public DiffCommand getDiffCommand()
|
||||||
{
|
{
|
||||||
return new GitDiffCommand(context, repository, handler.getWorkdirFactory());
|
return new GitDiffCommand(context, repository);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void diffForOneRevisionShouldCreateDiff() throws IOException {
|
public void diffForOneRevisionShouldCreateDiff() throws IOException {
|
||||||
GitDiffCommand gitDiffCommand = createDiffCommand();
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4");
|
diffCommandRequest.setRevision("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4");
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
@@ -50,7 +50,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void diffForOneBranchShouldCreateDiff() throws IOException {
|
public void diffForOneBranchShouldCreateDiff() throws IOException {
|
||||||
GitDiffCommand gitDiffCommand = createDiffCommand();
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
diffCommandRequest.setRevision("test-branch");
|
diffCommandRequest.setRevision("test-branch");
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||||
@@ -60,7 +60,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void diffForPathShouldCreateLimitedDiff() throws IOException {
|
public void diffForPathShouldCreateLimitedDiff() throws IOException {
|
||||||
GitDiffCommand gitDiffCommand = createDiffCommand();
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
diffCommandRequest.setRevision("test-branch");
|
diffCommandRequest.setRevision("test-branch");
|
||||||
diffCommandRequest.setPath("a.txt");
|
diffCommandRequest.setPath("a.txt");
|
||||||
@@ -71,7 +71,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void diffBetweenTwoBranchesShouldCreateDiff() throws IOException {
|
public void diffBetweenTwoBranchesShouldCreateDiff() throws IOException {
|
||||||
GitDiffCommand gitDiffCommand = createDiffCommand();
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
diffCommandRequest.setRevision("master");
|
diffCommandRequest.setRevision("master");
|
||||||
diffCommandRequest.setAncestorChangeset("test-branch");
|
diffCommandRequest.setAncestorChangeset("test-branch");
|
||||||
@@ -82,7 +82,7 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void diffBetweenTwoBranchesForPathShouldCreateLimitedDiff() throws IOException {
|
public void diffBetweenTwoBranchesForPathShouldCreateLimitedDiff() throws IOException {
|
||||||
GitDiffCommand gitDiffCommand = createDiffCommand();
|
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository);
|
||||||
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
||||||
diffCommandRequest.setRevision("master");
|
diffCommandRequest.setRevision("master");
|
||||||
diffCommandRequest.setAncestorChangeset("test-branch");
|
diffCommandRequest.setAncestorChangeset("test-branch");
|
||||||
@@ -91,8 +91,4 @@ public class GitDiffCommandTest extends AbstractGitCommandTestBase {
|
|||||||
gitDiffCommand.getDiffResult(diffCommandRequest).accept(output);
|
gitDiffCommand.getDiffResult(diffCommandRequest).accept(output);
|
||||||
assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS, output.toString());
|
assertEquals(DIFF_FILE_A_MULTIPLE_REVISIONS, output.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private GitDiffCommand createDiffCommand() {
|
|
||||||
return new GitDiffCommand(createContext(), repository, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
package sonia.scm.repository.spi;
|
|
||||||
|
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
import sonia.scm.repository.util.WorkdirProvider;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
public class GitDiffCommand_Merge_Test extends AbstractGitCommandTestBase {
|
|
||||||
|
|
||||||
static final String DIFF_HEADER = "diff --git a/Main.java b/Main.java";
|
|
||||||
static final String DIFF_FILE_NO_CONFLICT = "--- a/Main.java\n" +
|
|
||||||
"+++ b/Main.java\n" +
|
|
||||||
"@@ -1,5 +1,5 @@\n" +
|
|
||||||
" class Main {\n" +
|
|
||||||
"- public static void main(String[] args) {\n" +
|
|
||||||
"+ public static void main(String[] arguments) {\n" +
|
|
||||||
" System.out.println(\"Expect nothing more to happen.\");\n" +
|
|
||||||
" System.out.println(\"This is for demonstration, only.\");\n" +
|
|
||||||
" }\n";
|
|
||||||
static final String DIFF_FILE_CONFLICT = "--- a/Main.java\n" +
|
|
||||||
"+++ b/Main.java\n" +
|
|
||||||
"@@ -1,6 +1,13 @@\n" +
|
|
||||||
"+import java.util.Arrays;\n" +
|
|
||||||
"+\n" +
|
|
||||||
" class Main {\n" +
|
|
||||||
" public static void main(String[] args) {\n" +
|
|
||||||
" System.out.println(\"Expect nothing more to happen.\");\n" +
|
|
||||||
"+<<<<<<< HEAD\n" +
|
|
||||||
" System.out.println(\"This is for demonstration, only.\");\n" +
|
|
||||||
"+=======\n" +
|
|
||||||
"+ System.out.println(\"Parameters:\");\n" +
|
|
||||||
"+ Arrays.stream(args).map(arg -> \"- \" + arg).forEach(System.out::println);\n" +
|
|
||||||
"+>>>>>>> feature/print_args\n" +
|
|
||||||
" }\n" +
|
|
||||||
" }\n";
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule();
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void diffBetweenTwoBranchesWithoutConflict() throws IOException {
|
|
||||||
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider()));
|
|
||||||
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
|
||||||
diffCommandRequest.setRevision("feature/rename_variable");
|
|
||||||
diffCommandRequest.setConflictBranch("integration");
|
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
||||||
gitDiffCommand.getDiffResult(diffCommandRequest).accept(output);
|
|
||||||
assertThat(output.toString())
|
|
||||||
.contains(DIFF_HEADER)
|
|
||||||
.contains(DIFF_FILE_NO_CONFLICT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void diffBetweenTwoBranchesWithSimpleConflict() throws IOException {
|
|
||||||
GitDiffCommand gitDiffCommand = new GitDiffCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider()));
|
|
||||||
DiffCommandRequest diffCommandRequest = new DiffCommandRequest();
|
|
||||||
diffCommandRequest.setRevision("feature/print_args");
|
|
||||||
diffCommandRequest.setConflictBranch("integration");
|
|
||||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
||||||
gitDiffCommand.getDiffResult(diffCommandRequest).accept(output);
|
|
||||||
assertThat(output.toString())
|
|
||||||
.contains(DIFF_HEADER)
|
|
||||||
.contains(DIFF_FILE_CONFLICT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getZippedRepositoryResource() {
|
|
||||||
return "sonia/scm/repository/spi/scm-git-spi-merge-diff-test.zip";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package sonia.scm.repository.spi;
|
||||||
|
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import sonia.scm.repository.spi.MergeConflictResult.SingleMergeConflict;
|
||||||
|
import sonia.scm.repository.util.WorkdirProvider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static sonia.scm.repository.spi.MergeConflictResult.ConflictTypes.BOTH_MODIFIED;
|
||||||
|
import static sonia.scm.repository.spi.MergeConflictResult.ConflictTypes.DELETED_BY_THEM;
|
||||||
|
import static sonia.scm.repository.spi.MergeConflictResult.ConflictTypes.DELETED_BY_US;
|
||||||
|
|
||||||
|
public class GitMergeCommand_Conflict_Test extends AbstractGitCommandTestBase {
|
||||||
|
|
||||||
|
static final String DIFF_HEADER = "diff --git a/Main.java b/Main.java";
|
||||||
|
static final String DIFF_FILE_CONFLICT = "--- a/Main.java\n" +
|
||||||
|
"+++ b/Main.java\n" +
|
||||||
|
"@@ -1,6 +1,13 @@\n" +
|
||||||
|
"+import java.util.Arrays;\n" +
|
||||||
|
"+\n" +
|
||||||
|
" class Main {\n" +
|
||||||
|
" public static void main(String[] args) {\n" +
|
||||||
|
" System.out.println(\"Expect nothing more to happen.\");\n" +
|
||||||
|
"+<<<<<<< HEAD\n" +
|
||||||
|
" System.out.println(\"This is for demonstration, only.\");\n" +
|
||||||
|
"+=======\n" +
|
||||||
|
"+ System.out.println(\"Parameters:\");\n" +
|
||||||
|
"+ Arrays.stream(args).map(arg -> \"- \" + arg).forEach(System.out::println);\n" +
|
||||||
|
"+>>>>>>> feature/print_args\n" +
|
||||||
|
" }\n" +
|
||||||
|
" }\n";
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public BindTransportProtocolRule transportProtocolRule = new BindTransportProtocolRule();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffBetweenTwoBranchesWithoutConflict() throws IOException {
|
||||||
|
MergeConflictResult result = computeMergeConflictResult("feature/rename_variable", "integration");
|
||||||
|
assertThat(result.getConflicts()).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffBetweenTwoBranchesWithSimpleConflict() throws IOException {
|
||||||
|
MergeConflictResult result = computeMergeConflictResult("feature/print_args", "integration");
|
||||||
|
SingleMergeConflict conflict = result.getConflicts().get(0);
|
||||||
|
assertThat(conflict.getType()).isEqualTo(BOTH_MODIFIED);
|
||||||
|
assertThat(conflict.getPath()).isEqualTo("Main.java");
|
||||||
|
assertThat(conflict.getDiff()).contains(DIFF_HEADER, DIFF_FILE_CONFLICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffBetweenTwoBranchesWithDeletedByThem() throws IOException {
|
||||||
|
MergeConflictResult result = computeMergeConflictResult("feature/remove_class", "integration");
|
||||||
|
SingleMergeConflict conflict = result.getConflicts().get(0);
|
||||||
|
assertThat(conflict.getType()).isEqualTo(DELETED_BY_THEM);
|
||||||
|
assertThat(conflict.getPath()).isEqualTo("Main.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void diffBetweenTwoBranchesWithDeletedByUs() throws IOException {
|
||||||
|
MergeConflictResult result = computeMergeConflictResult("integration", "feature/remove_class");
|
||||||
|
SingleMergeConflict conflict = result.getConflicts().get(0);
|
||||||
|
assertThat(conflict.getType()).isEqualTo(DELETED_BY_US);
|
||||||
|
assertThat(conflict.getPath()).isEqualTo("Main.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
private MergeConflictResult computeMergeConflictResult(String branchToMerge, String targetBranch) {
|
||||||
|
GitMergeCommand gitMergeCommand = new GitMergeCommand(createContext(), repository, new SimpleGitWorkdirFactory(new WorkdirProvider()));
|
||||||
|
MergeCommandRequest mergeCommandRequest = new MergeCommandRequest();
|
||||||
|
mergeCommandRequest.setBranchToMerge(branchToMerge);
|
||||||
|
mergeCommandRequest.setTargetBranch(targetBranch);
|
||||||
|
return gitMergeCommand.computeConflicts(mergeCommandRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getZippedRepositoryResource() {
|
||||||
|
return "sonia/scm/repository/spi/scm-git-spi-merge-diff-test.zip";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user