Search in sources :

Example 1 with CommitBuilder

use of org.locationtech.geogig.api.CommitBuilder in project GeoGig by boundlessgeo.

the class IndexTest method testWriteTree.

@Test
public void testWriteTree() throws Exception {
    insertAndAdd(points1);
    insertAndAdd(lines1);
    // this new root tree must exist on the repo db, but is not set as the current head. In
    // fact, it is headless, as there's no commit pointing to it. CommitOp does that.
    ObjectId newRootTreeId = geogig.command(WriteTree.class).setOldRoot(tree(repo.getHead().get().getObjectId())).call();
    assertNotNull(newRootTreeId);
    assertFalse(repo.getRootTreeId().equals(newRootTreeId));
    // but the index staged root shall be pointing to it
    // assertEquals(newRootTreeId, index.getStaged().getId());
    RevTree tree = repo.getTree(newRootTreeId);
    // assertEquals(2, tree.size().intValue());
    String path = appendChild(pointsName, points1.getIdentifier().getID());
    assertTrue(repo.command(FindTreeChild.class).setParent(tree).setChildPath(path).call().isPresent());
    path = appendChild(linesName, lines1.getIdentifier().getID());
    assertTrue(repo.command(FindTreeChild.class).setParent(tree).setChildPath(path).call().isPresent());
    // simulate a commit so the repo head points to this new tree
    ObjectInserter objectInserter = repo.newObjectInserter();
    List<ObjectId> parents = ImmutableList.of();
    RevCommit commit = new CommitBuilder(geogig.getPlatform()).setTreeId(newRootTreeId).setParentIds(parents).build();
    ObjectId commitId = commit.getId();
    objectInserter.insert(commit);
    Optional<Ref> newHead = geogig.command(UpdateRef.class).setName("refs/heads/master").setNewValue(commitId).call();
    assertTrue(newHead.isPresent());
    WorkingTree workTree = repo.workingTree();
    workTree.delete(linesName, lines1.getIdentifier().getID());
    geogig.command(AddOp.class).call();
    // newRootTreeId
    newRootTreeId = geogig.command(WriteTree2.class).setOldRoot(tree(newRootTreeId)).call();
    // =
    // index.writeTree(newRootTreeId,
    // new
    // NullProgressListener());
    assertNotNull(newRootTreeId);
    assertFalse(repo.getRootTreeId().equals(newRootTreeId));
    tree = repo.getTree(newRootTreeId);
    path = appendChild(pointsName, points1.getIdentifier().getID());
    assertTrue(repo.command(FindTreeChild.class).setParent(tree).setChildPath(path).call().isPresent());
    path = appendChild(linesName, lines1.getIdentifier().getID());
    assertFalse(repo.command(FindTreeChild.class).setParent(tree).setChildPath(path).call().isPresent());
}
Also used : AddOp(org.locationtech.geogig.api.porcelain.AddOp) ObjectId(org.locationtech.geogig.api.ObjectId) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) FindTreeChild(org.locationtech.geogig.api.plumbing.FindTreeChild) WorkingTree(org.locationtech.geogig.repository.WorkingTree) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) Ref(org.locationtech.geogig.api.Ref) NodeRef(org.locationtech.geogig.api.NodeRef) ObjectInserter(org.locationtech.geogig.storage.ObjectInserter) RevTree(org.locationtech.geogig.api.RevTree) WriteTree2(org.locationtech.geogig.api.plumbing.WriteTree2) RevCommit(org.locationtech.geogig.api.RevCommit) Test(org.junit.Test)

Example 2 with CommitBuilder

use of org.locationtech.geogig.api.CommitBuilder in project GeoGig by boundlessgeo.

the class RevCommitSerializationTest method testCommitRoundTrippin.

@Test
public void testCommitRoundTrippin() throws Exception {
    long currentTime = System.currentTimeMillis();
    int timeZoneOffset = TimeZone.getDefault().getOffset(currentTime);
    CommitBuilder builder = new CommitBuilder();
    String author = "groldan";
    builder.setAuthor(author);
    String authorEmail = "groldan@boundlessgeo.com";
    builder.setAuthorEmail(authorEmail);
    builder.setAuthorTimestamp(currentTime);
    builder.setAuthorTimeZoneOffset(timeZoneOffset);
    String committer = "mleslie";
    builder.setCommitter(committer);
    String committerEmail = "mleslie@boundlessgeo.com";
    builder.setCommitterEmail(committerEmail);
    builder.setCommitterTimestamp(currentTime);
    builder.setCommitterTimeZoneOffset(timeZoneOffset);
    ObjectId treeId = ObjectId.forString("Fake tree");
    builder.setTreeId(treeId);
    ObjectId parent1 = ObjectId.forString("Parent 1 of fake commit");
    ObjectId parent2 = ObjectId.forString("Parent 2 of fake commit");
    List<ObjectId> parents = Arrays.asList(parent1, parent2);
    builder.setParentIds(parents);
    RevCommit cmtIn = builder.build();
    assertNotNull(cmtIn);
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    ObjectWriter<RevCommit> write = factory.createObjectWriter(TYPE.COMMIT);
    write.write(cmtIn, bout);
    // System.err.println(bout);
    byte[] bytes = bout.toByteArray();
    assertTrue(bytes.length > 0);
    ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
    ObjectReader<RevCommit> read = factory.createCommitReader();
    RevCommit cmtOut = read.read(cmtIn.getId(), bin);
    assertEquals(treeId, cmtOut.getTreeId());
    assertEquals(parents, cmtOut.getParentIds());
    assertEquals(author, cmtOut.getAuthor().getName().get());
    assertEquals(authorEmail, cmtOut.getAuthor().getEmail().get());
    assertEquals(committer, cmtOut.getCommitter().getName().get());
    assertEquals(committerEmail, cmtOut.getCommitter().getEmail().get());
    assertEquals(currentTime, cmtOut.getCommitter().getTimestamp());
    assertEquals(timeZoneOffset, cmtOut.getCommitter().getTimeZoneOffset());
    assertEquals(currentTime, cmtOut.getAuthor().getTimestamp());
    assertEquals(timeZoneOffset, cmtOut.getAuthor().getTimeZoneOffset());
}
Also used : ObjectId(org.locationtech.geogig.api.ObjectId) ByteArrayInputStream(java.io.ByteArrayInputStream) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) ByteArrayOutputStream(java.io.ByteArrayOutputStream) RevCommit(org.locationtech.geogig.api.RevCommit) Test(org.junit.Test)

Example 3 with CommitBuilder

use of org.locationtech.geogig.api.CommitBuilder in project GeoGig by boundlessgeo.

the class WriteTree2Test method createHeadTree.

private RevTree createHeadTree(NodeRef... treeRefs) {
    RevTree root = createFromRefs(objectDb, treeRefs);
    objectDb.put(root);
    CommitBuilder cb = new CommitBuilder(geogig.getPlatform());
    ObjectId treeId = root.getId();
    RevCommit commit = cb.setTreeId(treeId).setCommitter("Gabriel Roldan").setAuthor("Gabriel Roldan").build();
    objectDb.put(commit);
    SymRef head = (SymRef) geogig.command(RefParse.class).setName(Ref.HEAD).call().get();
    final String currentBranch = head.getTarget();
    geogig.command(UpdateRef.class).setName(currentBranch).setNewValue(commit.getId()).call();
    verifyRepositoryTree(NodeRef.ROOT, treeId);
    verifyTreeStructure(treeId, treeRefs);
    return root;
}
Also used : SymRef(org.locationtech.geogig.api.SymRef) ObjectId(org.locationtech.geogig.api.ObjectId) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) RevTree(org.locationtech.geogig.api.RevTree) RevCommit(org.locationtech.geogig.api.RevCommit)

Example 4 with CommitBuilder

use of org.locationtech.geogig.api.CommitBuilder in project GeoGig by boundlessgeo.

the class CommitOp method _call.

/**
     * Executes the commit operation.
     * 
     * @return the commit just applied, or {@code null} if
     *         {@code getProgressListener().isCanceled()}
     * @see org.locationtech.geogig.api.AbstractGeoGigOp#call()
     * @throws NothingToCommitException if there are no staged changes by comparing the index
     *         staging tree and the repository HEAD tree.
     */
@Override
protected RevCommit _call() throws RuntimeException {
    final String committer = resolveCommitter();
    final String committerEmail = resolveCommitterEmail();
    final String author = resolveAuthor();
    final String authorEmail = resolveAuthorEmail();
    final Long authorTime = getAuthorTimeStamp();
    final Long committerTime = getCommitterTimeStamp();
    final Integer authorTimeZoneOffset = getAuthorTimeZoneOffset();
    final Integer committerTimeZoneOffset = getCommitterTimeZoneOffset();
    getProgressListener().started();
    float writeTreeProgress = 99f;
    if (all) {
        writeTreeProgress = 50f;
        AddOp op = command(AddOp.class);
        for (String st : pathFilters) {
            op.addPattern(st);
        }
        op.setUpdateOnly(true).setProgressListener(subProgress(49f)).call();
    }
    if (getProgressListener().isCanceled()) {
        return null;
    }
    final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
    checkState(currHead.isPresent(), "Repository has no HEAD, can't commit");
    final Ref headRef = currHead.get();
    checkState(//
    headRef instanceof SymRef, "HEAD is in a dettached state, cannot commit. Create a branch from it before committing");
    final String currentBranch = ((SymRef) headRef).getTarget();
    final ObjectId currHeadCommitId = headRef.getObjectId();
    Supplier<RevTree> oldRoot = resolveOldRoot();
    if (!currHeadCommitId.isNull()) {
        if (amend) {
            RevCommit headCommit = command(RevObjectParse.class).setObjectId(currHeadCommitId).call(RevCommit.class).get();
            parents.addAll(headCommit.getParentIds());
            if (message == null || message.isEmpty()) {
                message = headCommit.getMessage();
            }
            RevTree commitTree = command(RevObjectParse.class).setObjectId(headCommit.getTreeId()).call(RevTree.class).get();
            oldRoot = Suppliers.ofInstance(commitTree);
        } else {
            parents.add(0, currHeadCommitId);
        }
    } else {
        Preconditions.checkArgument(!amend, "Cannot amend. There is no previous commit to amend");
    }
    // additional operations in case we are committing after a conflicted merge
    final Optional<Ref> mergeHead = command(RefParse.class).setName(Ref.MERGE_HEAD).call();
    if (mergeHead.isPresent()) {
        ObjectId mergeCommitId = mergeHead.get().getObjectId();
        if (!mergeCommitId.isNull()) {
            parents.add(mergeCommitId);
        }
        if (message == null) {
            message = command(ReadMergeCommitMessageOp.class).call();
        }
    }
    ObjectId newTreeId;
    {
        WriteTree2 writeTree = command(WriteTree2.class);
        writeTree.setOldRoot(oldRoot).setProgressListener(subProgress(writeTreeProgress));
        if (!pathFilters.isEmpty()) {
            writeTree.setPathFilter(pathFilters);
        }
        newTreeId = writeTree.call();
    }
    if (getProgressListener().isCanceled()) {
        return null;
    }
    final ObjectId currentRootTreeId = command(ResolveTreeish.class).setTreeish(currHeadCommitId).call().or(RevTree.EMPTY_TREE_ID);
    if (currentRootTreeId.equals(newTreeId)) {
        if (!allowEmpty) {
            throw new NothingToCommitException("Nothing to commit after " + currHeadCommitId);
        }
    }
    final RevCommit commit;
    if (this.commit == null) {
        CommitBuilder cb = new CommitBuilder();
        cb.setAuthor(author);
        cb.setAuthorEmail(authorEmail);
        cb.setCommitter(committer);
        cb.setCommitterEmail(committerEmail);
        cb.setMessage(message);
        cb.setParentIds(parents);
        cb.setTreeId(newTreeId);
        cb.setCommitterTimestamp(committerTime);
        cb.setAuthorTimestamp(authorTime);
        cb.setCommitterTimeZoneOffset(committerTimeZoneOffset);
        cb.setAuthorTimeZoneOffset(authorTimeZoneOffset);
        commit = cb.build();
    } else {
        CommitBuilder cb = new CommitBuilder(this.commit);
        cb.setParentIds(parents);
        cb.setTreeId(newTreeId);
        cb.setCommitterTimestamp(committerTime);
        cb.setCommitterTimeZoneOffset(committerTimeZoneOffset);
        if (message != null) {
            cb.setMessage(message);
        }
        commit = cb.build();
    }
    if (getProgressListener().isCanceled()) {
        return null;
    }
    final ObjectDatabase objectDb = objectDatabase();
    objectDb.put(commit);
    // set the HEAD pointing to the new commit
    final Optional<Ref> branchHead = command(UpdateRef.class).setName(currentBranch).setNewValue(commit.getId()).call();
    checkState(commit.getId().equals(branchHead.get().getObjectId()));
    final Optional<Ref> newHead = command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
    checkState(currentBranch.equals(((SymRef) newHead.get()).getTarget()));
    Optional<ObjectId> treeId = command(ResolveTreeish.class).setTreeish(branchHead.get().getObjectId()).call();
    checkState(treeId.isPresent());
    checkState(newTreeId.equals(treeId.get()));
    getProgressListener().setProgress(100f);
    getProgressListener().complete();
    // TODO: maybe all this "heads cleaning" should be put in an independent operation
    if (mergeHead.isPresent()) {
        command(UpdateRef.class).setDelete(true).setName(Ref.MERGE_HEAD).call();
        command(UpdateRef.class).setDelete(true).setName(Ref.ORIG_HEAD).call();
    }
    final Optional<Ref> cherrypickHead = command(RefParse.class).setName(Ref.CHERRY_PICK_HEAD).call();
    if (cherrypickHead.isPresent()) {
        command(UpdateRef.class).setDelete(true).setName(Ref.CHERRY_PICK_HEAD).call();
        command(UpdateRef.class).setDelete(true).setName(Ref.ORIG_HEAD).call();
    }
    return commit;
}
Also used : ObjectId(org.locationtech.geogig.api.ObjectId) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) 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) UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) SymRef(org.locationtech.geogig.api.SymRef) ObjectDatabase(org.locationtech.geogig.storage.ObjectDatabase) ResolveTreeish(org.locationtech.geogig.api.plumbing.ResolveTreeish) RevObjectParse(org.locationtech.geogig.api.plumbing.RevObjectParse) RevTree(org.locationtech.geogig.api.RevTree) WriteTree2(org.locationtech.geogig.api.plumbing.WriteTree2) RevCommit(org.locationtech.geogig.api.RevCommit)

Example 5 with CommitBuilder

use of org.locationtech.geogig.api.CommitBuilder 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)

Aggregations

CommitBuilder (org.locationtech.geogig.api.CommitBuilder)22 ObjectId (org.locationtech.geogig.api.ObjectId)18 RevCommit (org.locationtech.geogig.api.RevCommit)16 UpdateRef (org.locationtech.geogig.api.plumbing.UpdateRef)8 Test (org.junit.Test)7 RevTree (org.locationtech.geogig.api.RevTree)7 Ref (org.locationtech.geogig.api.Ref)6 UpdateSymRef (org.locationtech.geogig.api.plumbing.UpdateSymRef)6 SymRef (org.locationtech.geogig.api.SymRef)4 WriteTree2 (org.locationtech.geogig.api.plumbing.WriteTree2)4 Repository (org.locationtech.geogig.repository.Repository)4 Platform (org.locationtech.geogig.api.Platform)3 DiffEntry (org.locationtech.geogig.api.plumbing.diff.DiffEntry)3 Optional (com.google.common.base.Optional)2 ImmutableList (com.google.common.collect.ImmutableList)2 File (java.io.File)2 IOException (java.io.IOException)2 LinkedList (java.util.LinkedList)2 List (java.util.List)2 Context (org.locationtech.geogig.api.Context)2