Search in sources :

Example 11 with CommitBuilder

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

the class CommitBuilderTest method testBuildFull.

public void testBuildFull() throws Exception {
    CommitBuilder b = new CommitBuilder();
    b.setAuthor("groldan");
    b.setAuthorEmail("groldan@boundlessgeo.com");
    b.setCommitter("jdeolive");
    b.setCommitterEmail("jdeolive@boundlessgeo.com");
    b.setMessage("cool this works");
    b.setCommitterTimestamp(1000);
    b.setCommitterTimeZoneOffset(10);
    b.setAuthorTimestamp(500);
    b.setAuthorTimeZoneOffset(-5);
    ObjectId treeId = ObjectId.forString("fake tree content");
    b.setTreeId(treeId);
    ObjectId parentId1 = ObjectId.forString("fake parent content 1");
    ObjectId parentId2 = ObjectId.forString("fake parent content 2");
    List<ObjectId> parentIds = ImmutableList.of(parentId1, parentId2);
    b.setParentIds(parentIds);
    RevCommit build = b.build();
    assertNotNull(build.getId());
    assertFalse(build.getId().isNull());
    assertEquals(treeId, build.getTreeId());
    assertEquals(parentIds, build.getParentIds());
    assertEquals("groldan", build.getAuthor().getName().get());
    assertEquals("groldan@boundlessgeo.com", build.getAuthor().getEmail().get());
    assertEquals("jdeolive", build.getCommitter().getName().get());
    assertEquals("jdeolive@boundlessgeo.com", build.getCommitter().getEmail().get());
    assertEquals("cool this works", build.getMessage());
    assertEquals(1000L, build.getCommitter().getTimestamp());
    assertEquals(10, build.getCommitter().getTimeZoneOffset());
    assertEquals(500L, build.getAuthor().getTimestamp());
    assertEquals(-5, build.getAuthor().getTimeZoneOffset());
}
Also used : ObjectId(org.locationtech.geogig.api.ObjectId) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) RevCommit(org.locationtech.geogig.api.RevCommit)

Example 12 with CommitBuilder

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

the class RevCommitSerializationTest method testCommit.

private CommitBuilder testCommit(ObjectId treeId, String author, String authorEmail, long authorTimestamp, String committer, String committerEmail, long committerTimestamp, String message, ObjectId... parentIds) {
    CommitBuilder b = new CommitBuilder();
    b.setTreeId(treeId);
    b.setAuthor(author);
    b.setAuthorEmail(authorEmail);
    b.setCommitter(committer);
    b.setCommitterEmail(committerEmail);
    b.setMessage(message);
    b.setAuthorTimestamp(authorTimestamp);
    b.setCommitterTimestamp(committerTimestamp);
    if (parentIds != null) {
        b.setParentIds(Lists.newArrayList(parentIds));
    }
    return b;
}
Also used : CommitBuilder(org.locationtech.geogig.api.CommitBuilder)

Example 13 with CommitBuilder

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

the class RebaseOp method _call.

/**
     * Executes the rebase 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 rebase.");
    if (!(continueRebase || skip || abort)) {
        Preconditions.checkState(currHead.get() instanceof SymRef, "Can't rebase from detached HEAD %s", currHead.get());
        Preconditions.checkState(upstream != null, "No upstream target has been specified.");
        Preconditions.checkState(!ObjectId.NULL.equals(upstream.get()), "Upstream did not resolve to a commit.");
    }
    // Rebase can only be run in a conflicted situation if the skip or abort option is used
    List<Conflict> conflicts = command(ConflictsReadOp.class).call();
    Preconditions.checkState(conflicts.isEmpty() || skip || abort, "Cannot run operation while merge conflicts exist.");
    Optional<Ref> ref = command(RefParse.class).setName(Ref.ORIG_HEAD).call();
    File branchFile = new File(getRebaseFolder(), "branch");
    RevCommit squashCommit = readSquashCommit();
    if (abort) {
        Preconditions.checkState(ref.isPresent() && branchFile.exists(), "Cannot abort. You are not in the middle of a rebase process.");
        command(ResetOp.class).setMode(ResetMode.HARD).setCommit(Suppliers.ofInstance(ref.get().getObjectId())).call();
        command(UpdateRef.class).setDelete(true).setName(Ref.ORIG_HEAD).call();
        branchFile.delete();
        return true;
    } else if (continueRebase) {
        Preconditions.checkState(ref.isPresent() && branchFile.exists(), "Cannot continue. You are not in the middle of a rebase process.");
        try {
            currentBranch = Files.readFirstLine(branchFile, Charsets.UTF_8);
        } catch (IOException e) {
            throw new IllegalStateException("Cannot read current branch info file");
        }
        rebaseHead = currHead.get().getObjectId();
        if (squashCommit == null) {
            // 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 {
            applyCommit(squashCommit, false);
        }
    } else if (skip) {
        Preconditions.checkState(ref.isPresent() && branchFile.exists(), "Cannot skip. You are not in the middle of a rebase process.");
        try {
            currentBranch = Files.readFirstLine(branchFile, Charsets.UTF_8);
        } catch (IOException e) {
            throw new IllegalStateException("Cannot read current branch info file");
        }
        rebaseHead = currHead.get().getObjectId();
        command(ResetOp.class).setCommit(Suppliers.ofInstance(rebaseHead)).setMode(ResetMode.HARD).call();
        if (squashCommit == null) {
            skipCurrentCommit();
            applyNextCommit(true);
        } else {
            return true;
        }
    } else {
        Preconditions.checkState(!ref.isPresent(), "You are currently in the middle of a merge or rebase project <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 or, if that's not
        // needed, do a fast-forward
        final SymRef headRef = (SymRef) currHead.get();
        currentBranch = headRef.getTarget();
        if (ObjectId.NULL.equals(headRef.getObjectId())) {
            // Fast-forward
            command(UpdateRef.class).setName(currentBranch).setNewValue(upstream.get()).call();
            command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
            workingTree().updateWorkHead(upstream.get());
            index().updateStageHead(upstream.get());
            getProgressListener().complete();
            return true;
        }
        Repository repository = repository();
        final RevCommit headCommit = repository.getCommit(headRef.getObjectId());
        final RevCommit targetCommit = repository.getCommit(upstream.get());
        command(UpdateRef.class).setName(Ref.ORIG_HEAD).setNewValue(headCommit.getId());
        Optional<ObjectId> ancestorCommit = command(FindCommonAncestor.class).setLeft(headCommit).setRight(targetCommit).setProgressListener(subProgress(10.f)).call();
        Preconditions.checkState(ancestorCommit.isPresent(), "No ancestor commit could be found.");
        if (ancestorCommit.get().equals(headCommit.getId())) {
            // Fast-forward
            command(UpdateRef.class).setName(currentBranch).setNewValue(upstream.get()).call();
            command(UpdateSymRef.class).setName(Ref.HEAD).setNewValue(currentBranch).call();
            workingTree().updateWorkHead(upstream.get());
            index().updateStageHead(upstream.get());
            getProgressListener().complete();
            return true;
        }
        // Get all commits between the head commit and the ancestor.
        Iterator<RevCommit> commitIterator = command(LogOp.class).call();
        List<RevCommit> commitsToRebase = new ArrayList<RevCommit>();
        RevCommit commit = commitIterator.next();
        while (!commit.getId().equals(ancestorCommit.get())) {
            commitsToRebase.add(commit);
            commit = commitIterator.next();
        }
        // rewind the HEAD
        if (onto == null) {
            onto = Suppliers.ofInstance(upstream.get());
        }
        rebaseHead = onto.get();
        command(ResetOp.class).setCommit(Suppliers.ofInstance(rebaseHead)).setMode(ResetMode.HARD).call();
        if (squashMessage != null) {
            CommitBuilder builder = new CommitBuilder(commitsToRebase.get(0));
            builder.setParentIds(Arrays.asList(ancestorCommit.get()));
            builder.setMessage(squashMessage);
            squashCommit = builder.build();
            // save the commit, since it does not exist in the database, and might be needed if
            // there is a conflict
            CharSequence commitString = command(CatObject.class).setObject(Suppliers.ofInstance(squashCommit)).call();
            File squashFile = new File(getRebaseFolder(), "squash");
            try {
                Files.write(commitString, squashFile, Charsets.UTF_8);
            } catch (IOException e) {
                throw new IllegalStateException("Cannot create squash commit info file");
            }
            applyCommit(squashCommit, true);
            return true;
        } else {
            createRebaseCommitsInfoFiles(commitsToRebase);
        }
    // ProgressListener subProgress = subProgress(90.f);
    }
    if (squashCommit == null) {
        boolean ret;
        do {
            ret = applyNextCommit(true);
        } while (ret);
    }
    // clean up
    File squashFile = new File(getRebaseFolder(), "squash");
    if (squashFile.exists()) {
        squashFile.delete();
    }
    command(UpdateRef.class).setDelete(true).setName(Ref.ORIG_HEAD).call();
    branchFile.delete();
    // subProgress.complete();
    getProgressListener().complete();
    return true;
}
Also used : ConflictsReadOp(org.locationtech.geogig.api.plumbing.merge.ConflictsReadOp) ObjectId(org.locationtech.geogig.api.ObjectId) ArrayList(java.util.ArrayList) UpdateRef(org.locationtech.geogig.api.plumbing.UpdateRef) CommitBuilder(org.locationtech.geogig.api.CommitBuilder) IOException(java.io.IOException) 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) Repository(org.locationtech.geogig.repository.Repository) Conflict(org.locationtech.geogig.api.plumbing.merge.Conflict) CanRunDuringConflict(org.locationtech.geogig.di.CanRunDuringConflict) File(java.io.File) RevCommit(org.locationtech.geogig.api.RevCommit)

Example 14 with CommitBuilder

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

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

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