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());
}
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;
}
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;
}
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);
}
}
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);
}
Aggregations