Search in sources :

Example 11 with MergeReport

use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.

the class RevertFeatureWebOp method run.

/**
     * Runs the command and builds the appropriate response
     * 
     * @param context - the context to use for this command
     * 
     * @throws CommandSpecException
     */
@Override
public void run(CommandContext context) {
    if (this.getTransactionId() == null) {
        throw new CommandSpecException("No transaction was specified, revert feature requires a transaction to preserve the stability of the repository.");
    }
    final Context geogig = this.getCommandLocator(context);
    Optional<RevTree> newTree = Optional.absent();
    Optional<RevTree> oldTree = Optional.absent();
    // get tree from new commit
    Optional<ObjectId> treeId = geogig.command(ResolveTreeish.class).setTreeish(newCommitId).call();
    Preconditions.checkState(treeId.isPresent(), "New commit id did not resolve to a valid tree.");
    newTree = geogig.command(RevObjectParse.class).setRefSpec(treeId.get().toString()).call(RevTree.class);
    Preconditions.checkState(newTree.isPresent(), "Unable to read the new commit tree.");
    // get tree from old commit
    treeId = geogig.command(ResolveTreeish.class).setTreeish(oldCommitId).call();
    Preconditions.checkState(treeId.isPresent(), "Old commit id did not resolve to a valid tree.");
    oldTree = geogig.command(RevObjectParse.class).setRefSpec(treeId.get().toString()).call(RevTree.class);
    Preconditions.checkState(newTree.isPresent(), "Unable to read the old commit tree.");
    // get feature from old tree
    Optional<NodeRef> node = geogig.command(FindTreeChild.class).setParent(oldTree.get()).setIndex(true).setChildPath(featurePath).call();
    boolean delete = false;
    if (!node.isPresent()) {
        delete = true;
        node = geogig.command(FindTreeChild.class).setParent(newTree.get()).setIndex(true).setChildPath(featurePath).call();
        Preconditions.checkState(node.isPresent(), "The feature was not found in either commit tree.");
    }
    // get the new parent tree
    ObjectId metadataId = ObjectId.NULL;
    Optional<NodeRef> parentNode = geogig.command(FindTreeChild.class).setParent(newTree.get()).setChildPath(node.get().getParentPath()).setIndex(true).call();
    RevTreeBuilder treeBuilder = null;
    if (parentNode.isPresent()) {
        metadataId = parentNode.get().getMetadataId();
        Optional<RevTree> parsed = geogig.command(RevObjectParse.class).setObjectId(parentNode.get().getNode().getObjectId()).call(RevTree.class);
        checkState(parsed.isPresent(), "Parent tree couldn't be found in the repository.");
        treeBuilder = new RevTreeBuilder(geogig.stagingDatabase(), parsed.get());
        treeBuilder.remove(node.get().getNode().getName());
    } else {
        treeBuilder = new RevTreeBuilder(geogig.stagingDatabase());
    }
    // put the old feature into the new tree
    if (!delete) {
        treeBuilder.put(node.get().getNode());
    }
    ObjectId newTreeId = geogig.command(WriteBack.class).setAncestor(newTree.get().builder(geogig.stagingDatabase())).setChildPath(node.get().getParentPath()).setToIndex(true).setTree(treeBuilder.build()).setMetadataId(metadataId).call();
    // build new commit with parent of new commit and the newly built tree
    CommitBuilder builder = new CommitBuilder();
    builder.setParentIds(Lists.newArrayList(newCommitId));
    builder.setTreeId(newTreeId);
    builder.setAuthor(authorName.orNull());
    builder.setAuthorEmail(authorEmail.orNull());
    builder.setMessage(commitMessage.or("Reverted changes made to " + featurePath + " at " + newCommitId.toString()));
    RevCommit mapped = builder.build();
    context.getGeoGIG().getRepository().objectDatabase().put(mapped);
    // merge commit into current branch
    final Optional<Ref> currHead = geogig.command(RefParse.class).setName(Ref.HEAD).call();
    if (!currHead.isPresent()) {
        throw new CommandSpecException("Repository has no HEAD, can't merge.");
    }
    MergeOp merge = geogig.command(MergeOp.class);
    merge.setAuthor(authorName.orNull(), authorEmail.orNull());
    merge.addCommit(Suppliers.ofInstance(mapped.getId()));
    merge.setMessage(mergeMessage.or("Merged revert of " + featurePath));
    try {
        final MergeReport report = merge.call();
        context.setResponseContent(new CommandResponse() {

            @Override
            public void write(ResponseWriter out) throws Exception {
                out.start();
                out.writeMergeResponse(Optional.fromNullable(report.getMergeCommit()), report.getReport().get(), geogig, report.getOurs(), report.getPairs().get(0).getTheirs(), report.getPairs().get(0).getAncestor());
                out.finish();
            }
        });
    } catch (Exception e) {
        final RevCommit ours = context.getGeoGIG().getRepository().getCommit(currHead.get().getObjectId());
        final RevCommit theirs = context.getGeoGIG().getRepository().getCommit(mapped.getId());
        final Optional<ObjectId> ancestor = geogig.command(FindCommonAncestor.class).setLeft(ours).setRight(theirs).call();
        context.setResponseContent(new CommandResponse() {

            final MergeScenarioReport report = geogig.command(ReportMergeScenarioOp.class).setMergeIntoCommit(ours).setToMergeCommit(theirs).call();

            @Override
            public void write(ResponseWriter out) throws Exception {
                out.start();
                Optional<RevCommit> mergeCommit = Optional.absent();
                out.writeMergeResponse(mergeCommit, report, geogig, ours.getId(), theirs.getId(), ancestor.get());
                out.finish();
            }
        });
    }
}
Also used : CommitBuilder(org.locationtech.geogig.api.CommitBuilder) MergeOp(org.locationtech.geogig.api.porcelain.MergeOp) CommandResponse(org.locationtech.geogig.web.api.CommandResponse) MergeScenarioReport(org.locationtech.geogig.api.plumbing.merge.MergeScenarioReport) NodeRef(org.locationtech.geogig.api.NodeRef) ResolveTreeish(org.locationtech.geogig.api.plumbing.ResolveTreeish) CommandSpecException(org.locationtech.geogig.web.api.CommandSpecException) RevCommit(org.locationtech.geogig.api.RevCommit) Context(org.locationtech.geogig.api.Context) CommandContext(org.locationtech.geogig.web.api.CommandContext) Optional(com.google.common.base.Optional) ObjectId(org.locationtech.geogig.api.ObjectId) FindTreeChild(org.locationtech.geogig.api.plumbing.FindTreeChild) RevTreeBuilder(org.locationtech.geogig.api.RevTreeBuilder) CommandSpecException(org.locationtech.geogig.web.api.CommandSpecException) MergeReport(org.locationtech.geogig.api.porcelain.MergeOp.MergeReport) Ref(org.locationtech.geogig.api.Ref) NodeRef(org.locationtech.geogig.api.NodeRef) ResponseWriter(org.locationtech.geogig.web.api.ResponseWriter) RevObjectParse(org.locationtech.geogig.api.plumbing.RevObjectParse) RevTree(org.locationtech.geogig.api.RevTree)

Example 12 with MergeReport

use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.

the class PullOp method _call.

/**
     * Executes the pull operation.
     * 
     * @return {@code null}
     * @see org.locationtech.geogig.api.AbstractGeoGigOp#call()
     */
@Override
protected PullResult _call() {
    if (remote == null) {
        setRemote("origin");
    }
    PullResult result = new PullResult();
    Optional<Remote> remoteRepo = remote.get();
    Preconditions.checkArgument(remoteRepo.isPresent(), "Remote could not be resolved.");
    getProgressListener().started();
    TransferSummary fetchResult = command(FetchOp.class).addRemote(remote).setDepth(depth.or(0)).setFullDepth(fullDepth).setAll(all).setProgressListener(subProgress(80.f)).call();
    result.setFetchResult(fetchResult);
    if (refSpecs.size() == 0) {
        // pull current branch
        final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
        Preconditions.checkState(currHead.isPresent(), "Repository has no HEAD, can't pull.");
        Preconditions.checkState(currHead.get() instanceof SymRef, "Can't pull from detached HEAD");
        final SymRef headRef = (SymRef) currHead.get();
        final String currentBranch = Ref.localName(headRef.getTarget());
        refSpecs.add(currentBranch + ":" + currentBranch);
    }
    for (String refspec : refSpecs) {
        String[] refs = refspec.split(":");
        Preconditions.checkArgument(refs.length < 3, "Invalid refspec, please use [+]<remoteref>[:<localref>].");
        boolean force = refspec.length() > 0 && refspec.charAt(0) == '+';
        String remoteref = refs[0].substring(force ? 1 : 0);
        Optional<Ref> sourceRef = findRemoteRef(remoteref);
        if (!sourceRef.isPresent()) {
            continue;
        }
        String destinationref = "";
        if (refs.length == 2) {
            destinationref = refs[1];
        } else {
            // pull into current branch
            final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
            Preconditions.checkState(currHead.isPresent(), "Repository has no HEAD, can't pull.");
            Preconditions.checkState(currHead.get() instanceof SymRef, "Can't pull from detached HEAD");
            final SymRef headRef = (SymRef) currHead.get();
            destinationref = headRef.getTarget();
        }
        Optional<Ref> destRef = command(RefParse.class).setName(destinationref).call();
        if (destRef.isPresent()) {
            if (destRef.get().getObjectId().equals(sourceRef.get().getObjectId()) || sourceRef.get().getObjectId().equals(ObjectId.NULL)) {
                // Already up to date.
                result.setOldRef(destRef.get());
                result.setNewRef(destRef.get());
                continue;
            }
            result.setOldRef(destRef.get());
            if (destRef.get().getObjectId().equals(ObjectId.NULL)) {
                command(UpdateRef.class).setName(destRef.get().getName()).setNewValue(sourceRef.get().getObjectId()).call();
            } else {
                command(CheckoutOp.class).setSource(destinationref).call();
                if (rebase) {
                    command(RebaseOp.class).setUpstream(Suppliers.ofInstance(sourceRef.get().getObjectId())).call();
                } else {
                    try {
                        MergeReport report = command(MergeOp.class).setAuthor(authorName.orNull(), authorEmail.orNull()).addCommit(Suppliers.ofInstance(sourceRef.get().getObjectId())).call();
                        result.setMergeReport(Optional.of(report));
                    } catch (NothingToCommitException e) {
                    // the branch that we are trying to pull has less history than the
                    // branch we are pulling into
                    }
                }
            }
            destRef = command(RefParse.class).setName(destinationref).call();
            result.setNewRef(destRef.get());
        } else {
            // make a new branch
            Ref newRef = command(BranchCreateOp.class).setAutoCheckout(true).setName(destinationref).setSource(sourceRef.get().getObjectId().toString()).call();
            result.setNewRef(newRef);
        }
    }
    getProgressListener().complete();
    result.setRemoteName(remote.get().get().getFetchURL());
    return result;
}
Also used : Remote(org.locationtech.geogig.api.Remote) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) MergeReport(org.locationtech.geogig.api.porcelain.MergeOp.MergeReport) 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) RefParse(org.locationtech.geogig.api.plumbing.RefParse)

Example 13 with MergeReport

use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.

the class SparseCloneTest method testPushSparseMergeScenario2.

@Test
public void testPushSparseMergeScenario2() throws Exception {
    setupSparseClone();
    // create a branch off an early commit
    Iterator<RevCommit> logs = localGeogig.geogig.command(LogOp.class).call();
    RevCommit initialCommit = logs.next();
    while (logs.hasNext()) {
        initialCommit = logs.next();
    }
    localGeogig.geogig.command(BranchCreateOp.class).setName("Branch1").setAutoCheckout(true).setSource(initialCommit.getId().toString()).call();
    // Add some commits to the local (sparse) repository
    List<Feature> features = Arrays.asList(city1, city1_modified, road3);
    LinkedList<RevCommit> expected = new LinkedList<RevCommit>();
    Map<Feature, ObjectId> oids = new HashMap<Feature, ObjectId>();
    for (Feature f : features) {
        ObjectId oId = insertAndAdd(localGeogig.geogig, f);
        oids.put(f, oId);
        final RevCommit commit = localGeogig.geogig.command(CommitOp.class).setMessage(f.getIdentifier().toString()).call();
        expected.addFirst(commit);
        Optional<RevObject> childObject = localGeogig.geogig.command(RevObjectParse.class).setObjectId(oId).call();
        assertTrue(childObject.isPresent());
    }
    // Checkout master
    localGeogig.geogig.command(CheckoutOp.class).setSource("master").call();
    // Merge Branch1 into master
    MergeOp merge = localGeogig.geogig.command(MergeOp.class);
    MergeReport report = merge.addCommit(Suppliers.ofInstance(expected.get(0).getId())).setMessage("Merge").call();
    PushOp push = push();
    push.addRefSpec("refs/heads/master").call();
    logs = remoteGeogig.geogig.command(LogOp.class).call();
    List<RevCommit> logged = new ArrayList<RevCommit>();
    for (; logs.hasNext(); ) {
        logged.add(logs.next());
    }
    assertEquals("Merge", logged.get(0).getMessage());
    assertFalse(report.getMergeCommit().getId().equals(logged.get(0).getId()));
    // Because we merged Branch1 into the "sparse" master, we don't need to swap the parents, so
    // the history should look the same.
    ObjectId parent1Id = logged.get(0).getParentIds().get(0);
    ObjectId parent2Id = logged.get(0).getParentIds().get(1);
    RevCommit parent1 = remoteGeogig.geogig.getRepository().getCommit(parent1Id);
    assertNotNull(parent1);
    assertEquals("Roads.2", parent1.getMessage());
    RevCommit parent2 = remoteGeogig.geogig.getRepository().getCommit(parent2Id);
    assertNotNull(parent2);
    assertEquals("Roads.3", parent2.getMessage());
    // Verify they weren't swapped in the original
    parent1Id = report.getMergeCommit().getParentIds().get(0);
    parent2Id = report.getMergeCommit().getParentIds().get(1);
    parent1 = localGeogig.geogig.getRepository().getCommit(parent1Id);
    assertNotNull(parent1);
    assertEquals("Roads.2", parent1.getMessage());
    parent2 = localGeogig.geogig.getRepository().getCommit(parent2Id);
    assertNotNull(parent2);
    assertEquals("Roads.3", parent2.getMessage());
    assertExists(remoteGeogig, oids.get(city1), oids.get(city1_modified), oids.get(road3));
}
Also used : HashMap(java.util.HashMap) ObjectId(org.locationtech.geogig.api.ObjectId) RevObject(org.locationtech.geogig.api.RevObject) LogOp(org.locationtech.geogig.api.porcelain.LogOp) ArrayList(java.util.ArrayList) MergeOp(org.locationtech.geogig.api.porcelain.MergeOp) Feature(org.opengis.feature.Feature) LinkedList(java.util.LinkedList) MergeReport(org.locationtech.geogig.api.porcelain.MergeOp.MergeReport) PushOp(org.locationtech.geogig.api.porcelain.PushOp) RevCommit(org.locationtech.geogig.api.RevCommit) Test(org.junit.Test)

Example 14 with MergeReport

use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.

the class LogOpTest method testMerged.

@Test
public void testMerged() throws Exception {
    // Create the following revision graph
    // o
    // |
    // o - Points 1 added
    // |\
    // | o - branch1 - Points 2 added
    // |
    // o - Points 3 added
    // |
    // o - master - HEAD - Lines 1 added
    insertAndAdd(points1);
    final RevCommit c1 = geogig.command(CommitOp.class).setMessage("commit for " + idP1).call();
    // create branch1 and checkout
    geogig.command(BranchCreateOp.class).setAutoCheckout(true).setName("branch1").call();
    insertAndAdd(points2);
    final RevCommit c2 = geogig.command(CommitOp.class).setMessage("commit for " + idP2).call();
    // checkout master
    geogig.command(CheckoutOp.class).setSource("master").call();
    insertAndAdd(points3);
    final RevCommit c3 = geogig.command(CommitOp.class).setMessage("commit for " + idP3).call();
    insertAndAdd(lines1);
    final RevCommit c4 = geogig.command(CommitOp.class).setMessage("commit for " + idL1).call();
    // Merge branch1 into master to create the following revision graph
    // o
    // |
    // o - Points 1 added
    // |\
    // | o - branch1 - Points 2 added
    // | |
    // o | - Points 3 added
    // | |
    // o | - Lines 1 added
    // |/
    // o - master - HEAD - Merge commit
    Ref branch1 = geogig.command(RefParse.class).setName("branch1").call().get();
    MergeReport mergeReport = geogig.command(MergeOp.class).addCommit(Suppliers.ofInstance(branch1.getObjectId())).setMessage("My merge message.").call();
    RevCommit mergeCommit = mergeReport.getMergeCommit();
    Iterator<RevCommit> iterator = logOp.call();
    assertNotNull(iterator);
    assertTrue(iterator.hasNext());
    assertEquals(mergeCommit, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c4, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c3, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c2, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c1, iterator.next());
    // test log using first parent only. It should not contain commit 2)
    LogOp op = geogig.command(LogOp.class).setFirstParentOnly(true);
    iterator = op.call();
    assertNotNull(iterator);
    assertTrue(iterator.hasNext());
    assertEquals(mergeCommit, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c4, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c3, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c1, iterator.next());
    assertFalse(iterator.hasNext());
    // Test topological order
    op = geogig.command(LogOp.class).setTopoOrder(true);
    iterator = op.call();
    assertNotNull(iterator);
    assertTrue(iterator.hasNext());
    assertEquals(mergeCommit, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c4, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c3, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c1, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c2, iterator.next());
    assertFalse(iterator.hasNext());
}
Also used : MergeReport(org.locationtech.geogig.api.porcelain.MergeOp.MergeReport) Ref(org.locationtech.geogig.api.Ref) NodeRef(org.locationtech.geogig.api.NodeRef) BranchCreateOp(org.locationtech.geogig.api.porcelain.BranchCreateOp) LogOp(org.locationtech.geogig.api.porcelain.LogOp) RefParse(org.locationtech.geogig.api.plumbing.RefParse) MergeOp(org.locationtech.geogig.api.porcelain.MergeOp) RevCommit(org.locationtech.geogig.api.RevCommit) Test(org.junit.Test)

Example 15 with MergeReport

use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.

the class LogOpTest method testMergedWithPathFilter.

@Test
public void testMergedWithPathFilter() throws Exception {
    // Create the following revision graph
    // o
    // |
    // o - Points 1 added
    // |\
    // | o - branch1 - Points 2 added
    // |
    // o - Points 3 added
    // |
    // o - master - HEAD - Lines 1 added
    insertAndAdd(points1);
    geogig.command(CommitOp.class).setMessage("commit for " + idP1).call();
    // create branch1 and checkout
    geogig.command(BranchCreateOp.class).setAutoCheckout(true).setName("branch1").call();
    insertAndAdd(points2);
    final RevCommit c2 = geogig.command(CommitOp.class).setMessage("commit for " + idP2).call();
    // checkout master
    geogig.command(CheckoutOp.class).setSource("master").call();
    insertAndAdd(points3);
    geogig.command(CommitOp.class).setMessage("commit for " + idP3).call();
    insertAndAdd(lines1);
    geogig.command(CommitOp.class).setMessage("commit for " + idL1).call();
    // Merge branch1 into master to create the following revision graph
    // o
    // |
    // o - Points 1 added
    // |\
    // | o - branch1 - Points 2 added
    // | |
    // o | - Points 3 added
    // | |
    // o | - Lines 1 added
    // |/
    // o - master - HEAD - Merge commit
    Ref branch1 = geogig.command(RefParse.class).setName("branch1").call().get();
    MergeReport mergeReport = geogig.command(MergeOp.class).addCommit(Suppliers.ofInstance(branch1.getObjectId())).setMessage("My merge message.").call();
    RevCommit mergeCommit = mergeReport.getMergeCommit();
    Iterator<RevCommit> iterator = logOp.addPath(pointsName + "/" + idP2).call();
    assertNotNull(iterator);
    assertTrue(iterator.hasNext());
    assertEquals(mergeCommit, iterator.next());
    assertTrue(iterator.hasNext());
    assertEquals(c2, iterator.next());
    // test log using first parent only. It should not contain commit 2)
    LogOp op = geogig.command(LogOp.class).addPath(pointsName + "/" + idP2).setFirstParentOnly(true);
    iterator = op.call();
    assertNotNull(iterator);
    assertTrue(iterator.hasNext());
    assertEquals(mergeCommit, iterator.next());
    assertFalse(iterator.hasNext());
}
Also used : MergeReport(org.locationtech.geogig.api.porcelain.MergeOp.MergeReport) Ref(org.locationtech.geogig.api.Ref) NodeRef(org.locationtech.geogig.api.NodeRef) BranchCreateOp(org.locationtech.geogig.api.porcelain.BranchCreateOp) LogOp(org.locationtech.geogig.api.porcelain.LogOp) RefParse(org.locationtech.geogig.api.plumbing.RefParse) MergeOp(org.locationtech.geogig.api.porcelain.MergeOp) RevCommit(org.locationtech.geogig.api.RevCommit) Test(org.junit.Test)

Aggregations

MergeReport (org.locationtech.geogig.api.porcelain.MergeOp.MergeReport)21 RevCommit (org.locationtech.geogig.api.RevCommit)19 Test (org.junit.Test)16 Ref (org.locationtech.geogig.api.Ref)14 BranchCreateOp (org.locationtech.geogig.api.porcelain.BranchCreateOp)13 MergeOp (org.locationtech.geogig.api.porcelain.MergeOp)13 RefParse (org.locationtech.geogig.api.plumbing.RefParse)11 ObjectId (org.locationtech.geogig.api.ObjectId)9 LogOp (org.locationtech.geogig.api.porcelain.LogOp)9 NodeRef (org.locationtech.geogig.api.NodeRef)8 UpdateRef (org.locationtech.geogig.api.plumbing.UpdateRef)7 RevTree (org.locationtech.geogig.api.RevTree)6 FindTreeChild (org.locationtech.geogig.api.plumbing.FindTreeChild)6 UpdateSymRef (org.locationtech.geogig.api.plumbing.UpdateSymRef)5 ArrayList (java.util.ArrayList)3 LinkedList (java.util.LinkedList)3 FindCommonAncestor (org.locationtech.geogig.api.plumbing.FindCommonAncestor)3 Optional (com.google.common.base.Optional)2 HashMap (java.util.HashMap)2 RevObject (org.locationtech.geogig.api.RevObject)2