Search in sources :

Example 1 with WriteTree2

use of org.locationtech.geogig.api.plumbing.WriteTree2 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 WriteTree2

use of org.locationtech.geogig.api.plumbing.WriteTree2 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 3 with WriteTree2

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

the class RebaseOp method applyCommit.

/**
     * Applies the passed command.
     * 
     * @param commitToApply the commit to apply
     * @param useCommitChanges if true, applies the command completely, staging its changes before
     *        committing. If false, it commits the currently staged changes, ignoring the changes in
     *        the commit and using just its author and message
     */
private void applyCommit(RevCommit commitToApply, boolean useCommitChanges) {
    Repository repository = repository();
    Platform platform = platform();
    if (useCommitChanges) {
        ObjectId parentTreeId;
        ObjectId parentCommitId = ObjectId.NULL;
        if (commitToApply.getParentIds().size() > 0) {
            parentCommitId = commitToApply.getParentIds().get(0);
        }
        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();
            long timestamp = platform.currentTimeMillis();
            // Create new commit
            CommitBuilder builder = new CommitBuilder(commitToApply);
            builder.setParentIds(Arrays.asList(rebaseHead));
            builder.setTreeId(newTreeId);
            builder.setCommitterTimestamp(timestamp);
            builder.setCommitterTimeZoneOffset(platform.timeZoneOffset(timestamp));
            RevCommit newCommit = builder.build();
            repository.objectDatabase().put(newCommit);
            rebaseHead = newCommit.getId();
            command(UpdateRef.class).setName(currentBranch).setNewValue(rebaseHead).call();
            command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
            workingTree().updateWorkHead(newTreeId);
            index().updateStageHead(newTreeId);
        } else {
            Iterator<DiffEntry> unconflicted = report.getUnconflicted().iterator();
            // stage unconflicted changes
            index().stage(getProgressListener(), unconflicted, 0);
            workingTree().updateWorkHead(index().getTree().getId());
            // mark conflicted elements
            command(ConflictsWriteOp.class).setConflicts(report.getConflicts()).call();
            // created exception message
            StringBuilder msg = new StringBuilder();
            msg.append("error: could not apply ");
            msg.append(commitToApply.getId().toString().substring(0, 7));
            msg.append(" " + commitToApply.getMessage() + "\n");
            for (Conflict conflict : report.getConflicts()) {
                msg.append("CONFLICT: conflict in " + conflict.getPath() + "\n");
            }
            File branchFile = new File(getRebaseFolder(), "branch");
            try {
                Files.write(currentBranch, branchFile, Charsets.UTF_8);
            } catch (IOException e) {
                throw new IllegalStateException("Cannot create current branch info file");
            }
            throw new RebaseConflictsException(msg.toString());
        }
    } else {
        // write new tree
        ObjectId newTreeId = command(WriteTree2.class).call();
        long timestamp = platform.currentTimeMillis();
        // Create new commit
        CommitBuilder builder = new CommitBuilder(commitToApply);
        builder.setParentIds(Arrays.asList(rebaseHead));
        builder.setTreeId(newTreeId);
        builder.setCommitterTimestamp(timestamp);
        builder.setCommitterTimeZoneOffset(platform.timeZoneOffset(timestamp));
        RevCommit newCommit = builder.build();
        repository.objectDatabase().put(newCommit);
        rebaseHead = newCommit.getId();
        command(UpdateRef.class).setName(currentBranch).setNewValue(rebaseHead).call();
        command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
        workingTree().updateWorkHead(newTreeId);
        index().updateStageHead(newTreeId);
    }
}
Also used : Platform(org.locationtech.geogig.api.Platform) ObjectId(org.locationtech.geogig.api.ObjectId) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) IOException(java.io.IOException) MergeScenarioReport(org.locationtech.geogig.api.plumbing.merge.MergeScenarioReport) UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) Repository(org.locationtech.geogig.repository.Repository) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) CanRunDuringConflict(org.locationtech.geogig.di.CanRunDuringConflict) File(java.io.File) WriteTree2(org.locationtech.geogig.api.plumbing.WriteTree2) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry) RevCommit(org.locationtech.geogig.api.RevCommit)

Example 4 with WriteTree2

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

the class RevertOp method createCommit.

private void createCommit(RevCommit commit) {
    // write new tree
    ObjectId newTreeId = command(WriteTree2.class).call();
    long timestamp = platform().currentTimeMillis();
    String committerName = resolveCommitter();
    String committerEmail = resolveCommitterEmail();
    // Create new commit
    CommitBuilder builder = new CommitBuilder();
    builder.setParentIds(Arrays.asList(revertHead));
    builder.setTreeId(newTreeId);
    builder.setCommitterTimestamp(timestamp);
    builder.setMessage("Revert '" + commit.getMessage() + "'\nThis reverts " + commit.getId().toString());
    builder.setCommitter(committerName);
    builder.setCommitterEmail(committerEmail);
    builder.setAuthor(committerName);
    builder.setAuthorEmail(committerEmail);
    RevCommit newCommit = builder.build();
    objectDatabase().put(newCommit);
    revertHead = newCommit.getId();
    command(UpdateRef.class).setName(currentBranch).setNewValue(revertHead).call();
    command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
    workingTree().updateWorkHead(newTreeId);
    index().updateStageHead(newTreeId);
}
Also used : UpdateSymRef(org.locationtech.geogig.api.plumbing.UpdateSymRef) ObjectId(org.locationtech.geogig.api.ObjectId) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) WriteTree2(org.locationtech.geogig.api.plumbing.WriteTree2) RevCommit(org.locationtech.geogig.api.RevCommit)

Example 5 with WriteTree2

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

Aggregations

ObjectId (org.locationtech.geogig.api.ObjectId)5 RevCommit (org.locationtech.geogig.api.RevCommit)5 UpdateRef (org.locationtech.geogig.api.plumbing.UpdateRef)5 WriteTree2 (org.locationtech.geogig.api.plumbing.WriteTree2)5 CommitBuilder (org.locationtech.geogig.api.CommitBuilder)4 Ref (org.locationtech.geogig.api.Ref)3 UpdateSymRef (org.locationtech.geogig.api.plumbing.UpdateSymRef)3 RevTree (org.locationtech.geogig.api.RevTree)2 SymRef (org.locationtech.geogig.api.SymRef)2 DiffEntry (org.locationtech.geogig.api.plumbing.diff.DiffEntry)2 Conflict (org.locationtech.geogig.api.plumbing.merge.Conflict)2 MergeScenarioReport (org.locationtech.geogig.api.plumbing.merge.MergeScenarioReport)2 Repository (org.locationtech.geogig.repository.Repository)2 File (java.io.File)1 IOException (java.io.IOException)1 Test (org.junit.Test)1 NodeRef (org.locationtech.geogig.api.NodeRef)1 Platform (org.locationtech.geogig.api.Platform)1 FindTreeChild (org.locationtech.geogig.api.plumbing.FindTreeChild)1 ResolveTreeish (org.locationtech.geogig.api.plumbing.ResolveTreeish)1