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