use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport 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();
}
});
}
}
use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.
the class PullOp method _call.
/**
* Executes the pull operation.
*
* @return {@code null}
* @see org.locationtech.geogig.api.AbstractGeoGigOp#call()
*/
@Override
protected PullResult _call() {
if (remote == null) {
setRemote("origin");
}
PullResult result = new PullResult();
Optional<Remote> remoteRepo = remote.get();
Preconditions.checkArgument(remoteRepo.isPresent(), "Remote could not be resolved.");
getProgressListener().started();
TransferSummary fetchResult = command(FetchOp.class).addRemote(remote).setDepth(depth.or(0)).setFullDepth(fullDepth).setAll(all).setProgressListener(subProgress(80.f)).call();
result.setFetchResult(fetchResult);
if (refSpecs.size() == 0) {
// pull current branch
final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
Preconditions.checkState(currHead.isPresent(), "Repository has no HEAD, can't pull.");
Preconditions.checkState(currHead.get() instanceof SymRef, "Can't pull from detached HEAD");
final SymRef headRef = (SymRef) currHead.get();
final String currentBranch = Ref.localName(headRef.getTarget());
refSpecs.add(currentBranch + ":" + currentBranch);
}
for (String refspec : refSpecs) {
String[] refs = refspec.split(":");
Preconditions.checkArgument(refs.length < 3, "Invalid refspec, please use [+]<remoteref>[:<localref>].");
boolean force = refspec.length() > 0 && refspec.charAt(0) == '+';
String remoteref = refs[0].substring(force ? 1 : 0);
Optional<Ref> sourceRef = findRemoteRef(remoteref);
if (!sourceRef.isPresent()) {
continue;
}
String destinationref = "";
if (refs.length == 2) {
destinationref = refs[1];
} else {
// pull into current branch
final Optional<Ref> currHead = command(RefParse.class).setName(Ref.HEAD).call();
Preconditions.checkState(currHead.isPresent(), "Repository has no HEAD, can't pull.");
Preconditions.checkState(currHead.get() instanceof SymRef, "Can't pull from detached HEAD");
final SymRef headRef = (SymRef) currHead.get();
destinationref = headRef.getTarget();
}
Optional<Ref> destRef = command(RefParse.class).setName(destinationref).call();
if (destRef.isPresent()) {
if (destRef.get().getObjectId().equals(sourceRef.get().getObjectId()) || sourceRef.get().getObjectId().equals(ObjectId.NULL)) {
// Already up to date.
result.setOldRef(destRef.get());
result.setNewRef(destRef.get());
continue;
}
result.setOldRef(destRef.get());
if (destRef.get().getObjectId().equals(ObjectId.NULL)) {
command(UpdateRef.class).setName(destRef.get().getName()).setNewValue(sourceRef.get().getObjectId()).call();
} else {
command(CheckoutOp.class).setSource(destinationref).call();
if (rebase) {
command(RebaseOp.class).setUpstream(Suppliers.ofInstance(sourceRef.get().getObjectId())).call();
} else {
try {
MergeReport report = command(MergeOp.class).setAuthor(authorName.orNull(), authorEmail.orNull()).addCommit(Suppliers.ofInstance(sourceRef.get().getObjectId())).call();
result.setMergeReport(Optional.of(report));
} catch (NothingToCommitException e) {
// the branch that we are trying to pull has less history than the
// branch we are pulling into
}
}
}
destRef = command(RefParse.class).setName(destinationref).call();
result.setNewRef(destRef.get());
} else {
// make a new branch
Ref newRef = command(BranchCreateOp.class).setAutoCheckout(true).setName(destinationref).setSource(sourceRef.get().getObjectId().toString()).call();
result.setNewRef(newRef);
}
}
getProgressListener().complete();
result.setRemoteName(remote.get().get().getFetchURL());
return result;
}
use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.
the class SparseCloneTest method testPushSparseMergeScenario2.
@Test
public void testPushSparseMergeScenario2() throws Exception {
setupSparseClone();
// create a branch off an early commit
Iterator<RevCommit> logs = localGeogig.geogig.command(LogOp.class).call();
RevCommit initialCommit = logs.next();
while (logs.hasNext()) {
initialCommit = logs.next();
}
localGeogig.geogig.command(BranchCreateOp.class).setName("Branch1").setAutoCheckout(true).setSource(initialCommit.getId().toString()).call();
// Add some commits to the local (sparse) repository
List<Feature> features = Arrays.asList(city1, city1_modified, road3);
LinkedList<RevCommit> expected = new LinkedList<RevCommit>();
Map<Feature, ObjectId> oids = new HashMap<Feature, ObjectId>();
for (Feature f : features) {
ObjectId oId = insertAndAdd(localGeogig.geogig, f);
oids.put(f, oId);
final RevCommit commit = localGeogig.geogig.command(CommitOp.class).setMessage(f.getIdentifier().toString()).call();
expected.addFirst(commit);
Optional<RevObject> childObject = localGeogig.geogig.command(RevObjectParse.class).setObjectId(oId).call();
assertTrue(childObject.isPresent());
}
// Checkout master
localGeogig.geogig.command(CheckoutOp.class).setSource("master").call();
// Merge Branch1 into master
MergeOp merge = localGeogig.geogig.command(MergeOp.class);
MergeReport report = merge.addCommit(Suppliers.ofInstance(expected.get(0).getId())).setMessage("Merge").call();
PushOp push = push();
push.addRefSpec("refs/heads/master").call();
logs = remoteGeogig.geogig.command(LogOp.class).call();
List<RevCommit> logged = new ArrayList<RevCommit>();
for (; logs.hasNext(); ) {
logged.add(logs.next());
}
assertEquals("Merge", logged.get(0).getMessage());
assertFalse(report.getMergeCommit().getId().equals(logged.get(0).getId()));
// Because we merged Branch1 into the "sparse" master, we don't need to swap the parents, so
// the history should look the same.
ObjectId parent1Id = logged.get(0).getParentIds().get(0);
ObjectId parent2Id = logged.get(0).getParentIds().get(1);
RevCommit parent1 = remoteGeogig.geogig.getRepository().getCommit(parent1Id);
assertNotNull(parent1);
assertEquals("Roads.2", parent1.getMessage());
RevCommit parent2 = remoteGeogig.geogig.getRepository().getCommit(parent2Id);
assertNotNull(parent2);
assertEquals("Roads.3", parent2.getMessage());
// Verify they weren't swapped in the original
parent1Id = report.getMergeCommit().getParentIds().get(0);
parent2Id = report.getMergeCommit().getParentIds().get(1);
parent1 = localGeogig.geogig.getRepository().getCommit(parent1Id);
assertNotNull(parent1);
assertEquals("Roads.2", parent1.getMessage());
parent2 = localGeogig.geogig.getRepository().getCommit(parent2Id);
assertNotNull(parent2);
assertEquals("Roads.3", parent2.getMessage());
assertExists(remoteGeogig, oids.get(city1), oids.get(city1_modified), oids.get(road3));
}
use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.
the class LogOpTest method testMerged.
@Test
public void testMerged() throws Exception {
// Create the following revision graph
// o
// |
// o - Points 1 added
// |\
// | o - branch1 - Points 2 added
// |
// o - Points 3 added
// |
// o - master - HEAD - Lines 1 added
insertAndAdd(points1);
final RevCommit c1 = geogig.command(CommitOp.class).setMessage("commit for " + idP1).call();
// create branch1 and checkout
geogig.command(BranchCreateOp.class).setAutoCheckout(true).setName("branch1").call();
insertAndAdd(points2);
final RevCommit c2 = geogig.command(CommitOp.class).setMessage("commit for " + idP2).call();
// checkout master
geogig.command(CheckoutOp.class).setSource("master").call();
insertAndAdd(points3);
final RevCommit c3 = geogig.command(CommitOp.class).setMessage("commit for " + idP3).call();
insertAndAdd(lines1);
final RevCommit c4 = geogig.command(CommitOp.class).setMessage("commit for " + idL1).call();
// Merge branch1 into master to create the following revision graph
// o
// |
// o - Points 1 added
// |\
// | o - branch1 - Points 2 added
// | |
// o | - Points 3 added
// | |
// o | - Lines 1 added
// |/
// o - master - HEAD - Merge commit
Ref branch1 = geogig.command(RefParse.class).setName("branch1").call().get();
MergeReport mergeReport = geogig.command(MergeOp.class).addCommit(Suppliers.ofInstance(branch1.getObjectId())).setMessage("My merge message.").call();
RevCommit mergeCommit = mergeReport.getMergeCommit();
Iterator<RevCommit> iterator = logOp.call();
assertNotNull(iterator);
assertTrue(iterator.hasNext());
assertEquals(mergeCommit, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c4, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c3, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c2, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c1, iterator.next());
// test log using first parent only. It should not contain commit 2)
LogOp op = geogig.command(LogOp.class).setFirstParentOnly(true);
iterator = op.call();
assertNotNull(iterator);
assertTrue(iterator.hasNext());
assertEquals(mergeCommit, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c4, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c3, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c1, iterator.next());
assertFalse(iterator.hasNext());
// Test topological order
op = geogig.command(LogOp.class).setTopoOrder(true);
iterator = op.call();
assertNotNull(iterator);
assertTrue(iterator.hasNext());
assertEquals(mergeCommit, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c4, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c3, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c1, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c2, iterator.next());
assertFalse(iterator.hasNext());
}
use of org.locationtech.geogig.api.porcelain.MergeOp.MergeReport in project GeoGig by boundlessgeo.
the class LogOpTest method testMergedWithPathFilter.
@Test
public void testMergedWithPathFilter() throws Exception {
// Create the following revision graph
// o
// |
// o - Points 1 added
// |\
// | o - branch1 - Points 2 added
// |
// o - Points 3 added
// |
// o - master - HEAD - Lines 1 added
insertAndAdd(points1);
geogig.command(CommitOp.class).setMessage("commit for " + idP1).call();
// create branch1 and checkout
geogig.command(BranchCreateOp.class).setAutoCheckout(true).setName("branch1").call();
insertAndAdd(points2);
final RevCommit c2 = geogig.command(CommitOp.class).setMessage("commit for " + idP2).call();
// checkout master
geogig.command(CheckoutOp.class).setSource("master").call();
insertAndAdd(points3);
geogig.command(CommitOp.class).setMessage("commit for " + idP3).call();
insertAndAdd(lines1);
geogig.command(CommitOp.class).setMessage("commit for " + idL1).call();
// Merge branch1 into master to create the following revision graph
// o
// |
// o - Points 1 added
// |\
// | o - branch1 - Points 2 added
// | |
// o | - Points 3 added
// | |
// o | - Lines 1 added
// |/
// o - master - HEAD - Merge commit
Ref branch1 = geogig.command(RefParse.class).setName("branch1").call().get();
MergeReport mergeReport = geogig.command(MergeOp.class).addCommit(Suppliers.ofInstance(branch1.getObjectId())).setMessage("My merge message.").call();
RevCommit mergeCommit = mergeReport.getMergeCommit();
Iterator<RevCommit> iterator = logOp.addPath(pointsName + "/" + idP2).call();
assertNotNull(iterator);
assertTrue(iterator.hasNext());
assertEquals(mergeCommit, iterator.next());
assertTrue(iterator.hasNext());
assertEquals(c2, iterator.next());
// test log using first parent only. It should not contain commit 2)
LogOp op = geogig.command(LogOp.class).addPath(pointsName + "/" + idP2).setFirstParentOnly(true);
iterator = op.call();
assertNotNull(iterator);
assertTrue(iterator.hasNext());
assertEquals(mergeCommit, iterator.next());
assertFalse(iterator.hasNext());
}
Aggregations