use of org.locationtech.geogig.api.plumbing.merge.Conflict in project GeoGig by boundlessgeo.
the class RevertOp method applyRevertedChanges.
private List<Conflict> applyRevertedChanges(RevCommit commit) {
ObjectId parentCommitId = ObjectId.NULL;
if (commit.getParentIds().size() > 0) {
parentCommitId = commit.getParentIds().get(0);
}
ObjectId parentTreeId = ObjectId.NULL;
Repository repository = repository();
if (repository.commitExists(parentCommitId)) {
parentTreeId = repository.getCommit(parentCommitId).getTreeId();
}
// get changes (in reverse)
Iterator<DiffEntry> reverseDiff = command(DiffTree.class).setNewTree(parentTreeId).setOldTree(commit.getTreeId()).setReportTrees(false).call();
ObjectId headTreeId = repository.getCommit(revertHead).getTreeId();
final RevTree headTree = repository.getTree(headTreeId);
ArrayList<Conflict> conflicts = new ArrayList<Conflict>();
DiffEntry diff;
while (reverseDiff.hasNext()) {
diff = reverseDiff.next();
if (diff.isAdd()) {
// Feature was deleted
Optional<NodeRef> node = command(FindTreeChild.class).setChildPath(diff.newPath()).setIndex(true).setParent(headTree).call();
// make sure it is still deleted
if (node.isPresent()) {
conflicts.add(new Conflict(diff.newPath(), diff.oldObjectId(), node.get().objectId(), diff.newObjectId()));
} else {
index().stage(getProgressListener(), Iterators.singletonIterator(diff), 1);
}
} else {
// Feature was added or modified
Optional<NodeRef> node = command(FindTreeChild.class).setChildPath(diff.oldPath()).setIndex(true).setParent(headTree).call();
ObjectId nodeId = node.get().getNode().getObjectId();
// Make sure it wasn't changed
if (node.isPresent() && nodeId.equals(diff.oldObjectId())) {
index().stage(getProgressListener(), Iterators.singletonIterator(diff), 1);
} else {
// do not mark as conflict if reverting to the same feature currently in HEAD
if (!nodeId.equals(diff.newObjectId())) {
conflicts.add(new Conflict(diff.newPath(), diff.oldObjectId(), node.get().objectId(), diff.newObjectId()));
}
}
}
}
return conflicts;
}
use of org.locationtech.geogig.api.plumbing.merge.Conflict in project GeoGig by boundlessgeo.
the class RevertOp method _call.
/**
* Executes the revert operation.
*
* @return always {@code true}
*/
@Override
protected Boolean _call() {
final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
Preconditions.checkState(currHead.isPresent(), "Repository has no HEAD, can't revert.");
Preconditions.checkState(currHead.get() instanceof SymRef, "Can't revert from detached HEAD");
final SymRef headRef = (SymRef) currHead.get();
Preconditions.checkState(!headRef.getObjectId().equals(ObjectId.NULL), "HEAD has no history.");
currentBranch = headRef.getTarget();
revertHead = currHead.get().getObjectId();
Preconditions.checkArgument(!(continueRevert && abort), "Cannot continue and abort at the same time");
// count staged and unstaged changes
long staged = index().countStaged(null).count();
long unstaged = workingTree().countUnstaged(null).count();
Preconditions.checkState((staged == 0 && unstaged == 0) || abort || continueRevert, "You must have a clean working tree and index to perform a revert.");
getProgressListener().started();
// Revert can only be run in a conflicted situation if the abort option is used
List<Conflict> conflicts = command(ConflictsReadOp.class).call();
Preconditions.checkState(conflicts.isEmpty() || abort, "Cannot run operation while merge conflicts exist.");
Optional<Ref> ref = command(RefParse.class).setName(Ref.ORIG_HEAD).call();
if (abort) {
Preconditions.checkState(ref.isPresent(), "Cannot abort. You are not in the middle of a revert process.");
command(ResetOp.class).setMode(ResetMode.HARD).setCommit(Suppliers.ofInstance(ref.get().getObjectId())).call();
command(UpdateRef.class).setDelete(true).setName(Ref.ORIG_HEAD).call();
return true;
} else if (continueRevert) {
Preconditions.checkState(ref.isPresent(), "Cannot continue. You are not in the middle of a revert process.");
// Commit the manually-merged changes with the info of the commit that caused the
// conflict
applyNextCommit(false);
// Commit files should already be prepared, so we do nothing else
} else {
Preconditions.checkState(!ref.isPresent(), "You are currently in the middle of a merge or rebase operation <ORIG_HEAD is present>.");
getProgressListener().started();
command(UpdateRef.class).setName(Ref.ORIG_HEAD).setNewValue(currHead.get().getObjectId()).call();
// Here we prepare the files with the info about the commits to apply in reverse
List<RevCommit> commitsToRevert = Lists.newArrayList();
Repository repository = repository();
for (ObjectId id : commits) {
Preconditions.checkArgument(repository.commitExists(id), "Commit was not found in the repository: " + id.toString());
RevCommit commit = repository.getCommit(id);
commitsToRevert.add(commit);
}
createRevertCommitsInfoFiles(commitsToRevert);
}
boolean ret;
do {
ret = applyNextCommit(true);
} while (ret);
command(UpdateRef.class).setDelete(true).setName(Ref.ORIG_HEAD).call();
getProgressListener().complete();
return true;
}
use of org.locationtech.geogig.api.plumbing.merge.Conflict in project GeoGig by boundlessgeo.
the class CherryPickOp method _call.
/**
* Executes the cherry pick operation.
*
* @return RevCommit the new commit with the changes from the cherry-picked commit
*/
@Override
protected RevCommit _call() {
final Repository repository = repository();
final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
Preconditions.checkState(currHead.isPresent(), "Repository has no HEAD, can't cherry pick.");
Preconditions.checkState(currHead.get() instanceof SymRef, "Can't cherry pick from detached HEAD");
final SymRef headRef = (SymRef) currHead.get();
Preconditions.checkState(index().isClean() && workingTree().isClean(), "You must have a clean working tree and index to perform a cherry pick.");
getProgressListener().started();
Preconditions.checkArgument(repository.commitExists(commit), "Commit could not be resolved: %s.", commit);
RevCommit commitToApply = repository.getCommit(commit);
ObjectId headId = headRef.getObjectId();
ObjectId parentCommitId = ObjectId.NULL;
if (commitToApply.getParentIds().size() > 0) {
parentCommitId = commitToApply.getParentIds().get(0);
}
ObjectId parentTreeId = ObjectId.NULL;
if (repository.commitExists(parentCommitId)) {
parentTreeId = repository.getCommit(parentCommitId).getTreeId();
}
// get changes
Iterator<DiffEntry> diff = command(DiffTree.class).setOldTree(parentTreeId).setNewTree(commitToApply.getTreeId()).setReportTrees(true).call();
// see if there are conflicts
MergeScenarioReport report = command(ReportCommitConflictsOp.class).setCommit(commitToApply).call();
if (report.getConflicts().isEmpty()) {
// stage changes
index().stage(getProgressListener(), diff, 0);
// write new tree
ObjectId newTreeId = command(WriteTree2.class).call();
RevCommit newCommit = command(CommitOp.class).setCommit(commitToApply).call();
repository.workingTree().updateWorkHead(newTreeId);
repository.index().updateStageHead(newTreeId);
getProgressListener().complete();
return newCommit;
} else {
Iterator<DiffEntry> unconflicted = report.getUnconflicted().iterator();
// stage changes
index().stage(getProgressListener(), unconflicted, 0);
workingTree().updateWorkHead(index().getTree().getId());
command(UpdateRef.class).setName(Ref.CHERRY_PICK_HEAD).setNewValue(commit).call();
command(UpdateRef.class).setName(Ref.ORIG_HEAD).setNewValue(headId).call();
command(ConflictsWriteOp.class).setConflicts(report.getConflicts()).call();
StringBuilder msg = new StringBuilder();
msg.append("error: could not apply ");
msg.append(commitToApply.getId().toString().substring(0, 7));
msg.append(" " + commitToApply.getMessage());
for (Conflict conflict : report.getConflicts()) {
msg.append("\t" + conflict.getPath() + "\n");
}
StringBuilder sb = new StringBuilder();
for (Conflict conflict : report.getConflicts()) {
sb.append("CONFLICT: conflict in " + conflict.getPath() + "\n");
}
sb.append("Fix conflicts and then commit the result using 'geogig commit -c " + commitToApply.getId().toString().substring(0, 7) + "\n");
throw new IllegalStateException(sb.toString());
}
}
use of org.locationtech.geogig.api.plumbing.merge.Conflict in project GeoGig by boundlessgeo.
the class ResetOpTest method testResetFixesConflict.
@Test
public void testResetFixesConflict() throws Exception {
Feature points1Modified = feature(pointsType, idP1, "StringProp1_2", new Integer(1000), "POINT(1 1)");
Feature points1ModifiedB = feature(pointsType, idP1, "StringProp1_3", new Integer(2000), "POINT(1 1)");
insertAndAdd(points1);
RevCommit resetCommit = geogig.command(CommitOp.class).call();
geogig.command(BranchCreateOp.class).setName("TestBranch").call();
insertAndAdd(points1Modified);
geogig.command(CommitOp.class).call();
geogig.command(CheckoutOp.class).setSource("TestBranch").call();
insertAndAdd(points1ModifiedB);
insertAndAdd(points2);
geogig.command(CommitOp.class).call();
geogig.command(CheckoutOp.class).setSource("master").call();
Ref branch = geogig.command(RefParse.class).setName("TestBranch").call().get();
try {
geogig.command(MergeOp.class).addCommit(Suppliers.ofInstance(branch.getObjectId())).call();
fail();
} catch (MergeConflictsException e) {
assertTrue(e.getMessage().contains("conflict"));
}
geogig.command(ResetOp.class).setMode(ResetMode.HARD).setCommit(Suppliers.ofInstance(resetCommit.getId())).call();
List<Conflict> conflicts = geogig.getRepository().stagingDatabase().getConflicts(null, null);
assertTrue(conflicts.isEmpty());
Optional<Ref> ref = geogig.command(RefParse.class).setName(Ref.MERGE_HEAD).call();
assertFalse(ref.isPresent());
}
use of org.locationtech.geogig.api.plumbing.merge.Conflict in project GeoGig by boundlessgeo.
the class RevertOpTest method testRevertModifiedFeatureConflictAndAbort.
@Test
public void testRevertModifiedFeatureConflictAndAbort() throws Exception {
insertAndAdd(points1);
@SuppressWarnings("unused") RevCommit c1 = geogig.command(CommitOp.class).setMessage("commit for " + idP1).call();
insertAndAdd(points1_modified);
RevCommit c2 = geogig.command(CommitOp.class).setMessage("commit for modified " + idP1).call();
Feature points1_modifiedB = feature(pointsType, idP1, "StringProp1_2", new Integer(2000), "POINT(1 1)");
ObjectId oId = insertAndAdd(points1_modifiedB);
RevCommit c3 = geogig.command(CommitOp.class).setMessage("commit for modified " + idP1 + " again").call();
try {
geogig.command(RevertOp.class).addCommit(Suppliers.ofInstance(c2.getId())).call();
fail();
} catch (RevertConflictsException e) {
assertTrue(e.getMessage().contains(idP1));
}
Optional<Ref> ref = geogig.command(RefParse.class).setName(Ref.ORIG_HEAD).call();
assertTrue(ref.isPresent());
assertEquals(c3.getId(), ref.get().getObjectId());
List<Conflict> conflicts = geogig.command(ConflictsReadOp.class).call();
assertEquals(1, conflicts.size());
String path = NodeRef.appendChild(pointsName, idP1);
assertEquals(conflicts.get(0).getPath(), path);
assertEquals(conflicts.get(0).getOurs(), RevFeatureBuilder.build(points1_modifiedB).getId());
assertEquals(conflicts.get(0).getTheirs(), RevFeatureBuilder.build(points1).getId());
geogig.command(RevertOp.class).setAbort(true).call();
final Optional<Ref> currHead = geogig.command(RefParse.class).setName(Ref.HEAD).call();
final Optional<ObjectId> headTreeId = geogig.command(ResolveTreeish.class).setTreeish(currHead.get().getObjectId()).call();
RevTree headTree = repo.getTree(headTreeId.get());
Optional<NodeRef> points1Node = geogig.command(FindTreeChild.class).setChildPath(NodeRef.appendChild(pointsName, idP1)).setParent(headTree).call();
assertTrue(points1Node.isPresent());
assertEquals(oId, points1Node.get().getNode().getObjectId());
}
Aggregations