Search in sources :

Example 21 with Conflict

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;
}
Also used : NodeRef(org.locationtech.geogig.api.NodeRef) Repository(org.locationtech.geogig.repository.Repository) ObjectId(org.locationtech.geogig.api.ObjectId) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) CanRunDuringConflict(org.locationtech.geogig.di.CanRunDuringConflict) ArrayList(java.util.ArrayList) RevTree(org.locationtech.geogig.api.RevTree) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry)

Example 22 with Conflict

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;
}
Also used : ConflictsReadOp(org.locationtech.geogig.api.plumbing.merge.ConflictsReadOp) ObjectId(org.locationtech.geogig.api.ObjectId) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) Ref(org.locationtech.geogig.api.Ref) SymRef(org.locationtech.geogig.api.SymRef) NodeRef(org.locationtech.geogig.api.NodeRef) UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) SymRef(org.locationtech.geogig.api.SymRef) Repository(org.locationtech.geogig.repository.Repository) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) CanRunDuringConflict(org.locationtech.geogig.di.CanRunDuringConflict) ArrayList(java.util.ArrayList) List(java.util.List) RevCommit(org.locationtech.geogig.api.RevCommit)

Example 23 with Conflict

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());
    }
}
Also used : ObjectId(org.locationtech.geogig.api.ObjectId) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) MergeScenarioReport(org.locationtech.geogig.api.plumbing.merge.MergeScenarioReport) Repository(org.locationtech.geogig.repository.Repository) Ref(org.locationtech.geogig.api.Ref) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) SymRef(org.locationtech.geogig.api.SymRef) SymRef(org.locationtech.geogig.api.SymRef) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) WriteTree2(org.locationtech.geogig.api.plumbing.WriteTree2) RevCommit(org.locationtech.geogig.api.RevCommit) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry)

Example 24 with Conflict

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());
}
Also used : Ref(org.locationtech.geogig.api.Ref) MergeConflictsException(org.locationtech.geogig.api.porcelain.MergeConflictsException) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) RefParse(org.locationtech.geogig.api.plumbing.RefParse) CommitOp(org.locationtech.geogig.api.porcelain.CommitOp) ResetOp(org.locationtech.geogig.api.porcelain.ResetOp) Feature(org.opengis.feature.Feature) RevCommit(org.locationtech.geogig.api.RevCommit) Test(org.junit.Test)

Example 25 with Conflict

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());
}
Also used : ConflictsReadOp(org.locationtech.geogig.api.plumbing.merge.ConflictsReadOp) ObjectId(org.locationtech.geogig.api.ObjectId) FindTreeChild(org.locationtech.geogig.api.plumbing.FindTreeChild) Feature(org.opengis.feature.Feature) NodeRef(org.locationtech.geogig.api.NodeRef) Ref(org.locationtech.geogig.api.Ref) NodeRef(org.locationtech.geogig.api.NodeRef) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) RevertConflictsException(org.locationtech.geogig.api.porcelain.RevertConflictsException) RevTree(org.locationtech.geogig.api.RevTree) RevCommit(org.locationtech.geogig.api.RevCommit) Test(org.junit.Test)

Aggregations

Conflict (org.locationtech.geogig.api.plumbing.merge.Conflict)36 Ref (org.locationtech.geogig.api.Ref)17 RevCommit (org.locationtech.geogig.api.RevCommit)17 Test (org.junit.Test)16 NodeRef (org.locationtech.geogig.api.NodeRef)14 ObjectId (org.locationtech.geogig.api.ObjectId)14 ConflictsReadOp (org.locationtech.geogig.api.plumbing.merge.ConflictsReadOp)12 Feature (org.opengis.feature.Feature)12 RefParse (org.locationtech.geogig.api.plumbing.RefParse)11 CommitOp (org.locationtech.geogig.api.porcelain.CommitOp)10 SymRef (org.locationtech.geogig.api.SymRef)8 UpdateRef (org.locationtech.geogig.api.plumbing.UpdateRef)8 AddOp (org.locationtech.geogig.api.porcelain.AddOp)8 CanRunDuringConflict (org.locationtech.geogig.di.CanRunDuringConflict)8 MergeConflictsException (org.locationtech.geogig.api.porcelain.MergeConflictsException)7 File (java.io.File)6 IOException (java.io.IOException)6 UpdateSymRef (org.locationtech.geogig.api.plumbing.UpdateSymRef)6 DiffEntry (org.locationtech.geogig.api.plumbing.diff.DiffEntry)6 Repository (org.locationtech.geogig.repository.Repository)6