Index: src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommandNew.java =================================================================== --- src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommandNew.java (revision 1433907) +++ src/main/java/org/apache/jackrabbit/mongomk/impl/command/CommitCommandNew.java (working copy) @@ -29,6 +29,7 @@ import org.apache.jackrabbit.mongomk.api.model.Commit; import org.apache.jackrabbit.mongomk.impl.MongoNodeStore; import org.apache.jackrabbit.mongomk.impl.action.FetchCommitAction; +import org.apache.jackrabbit.mongomk.impl.action.FetchHeadRevisionIdAction; import org.apache.jackrabbit.mongomk.impl.action.ReadAndIncHeadRevisionAction; import org.apache.jackrabbit.mongomk.impl.action.SaveAndSetHeadRevisionAction; import org.apache.jackrabbit.mongomk.impl.action.SaveCommitAction; @@ -96,8 +97,14 @@ readBranchIdFromBaseCommit(); createMongoNodes(); prepareCommit(); - readExistingNodes(); - mergeNodes(); + // If base revision is older than the head revision, need to read + // and merge nodes at the head revision. + FetchHeadRevisionIdAction action = new FetchHeadRevisionIdAction(nodeStore, branchId); + long headRevisionId = action.execute(); + if (baseRevisionId < headRevisionId) { + readExistingNodes(); + mergeNodes(); + } prepareMongoNodes(); new SaveNodesAction(nodeStore, nodes.values()).execute(); new SaveCommitAction(nodeStore, commit).execute(); Index: src/main/java/org/apache/jackrabbit/mongomk/impl/action/FetchHeadRevisionIdAction.java =================================================================== --- src/main/java/org/apache/jackrabbit/mongomk/impl/action/FetchHeadRevisionIdAction.java (revision 1433907) +++ src/main/java/org/apache/jackrabbit/mongomk/impl/action/FetchHeadRevisionIdAction.java (working copy) @@ -31,13 +31,26 @@ */ public class FetchHeadRevisionIdAction extends BaseAction { + private final String branchId; + /** * Constructs a new {@code FetchHeadRevisionIdAction}. * * @param nodeStore Node store. */ public FetchHeadRevisionIdAction(MongoNodeStore nodeStore) { + this(nodeStore, null); + } + + /** + * Constructs a new {@code FetchHeadRevisionIdAction}. + * + * @param nodeStore Node store. + * @param branchId Branch id. + */ + public FetchHeadRevisionIdAction(MongoNodeStore nodeStore, String branchId) { super(nodeStore); + this.branchId = branchId; } @Override @@ -46,15 +59,19 @@ MongoSync syncMongo = (MongoSync)headCollection.findOne(); long headRevisionId = syncMongo.getHeadRevisionId(); - // Find the first revision id that's not part of a branch. DBCollection collection = nodeStore.getCommitCollection(); - DBObject query = QueryBuilder.start(MongoCommit.KEY_FAILED).notEquals(Boolean.TRUE) - .and(MongoCommit.KEY_REVISION_ID).lessThanEquals(headRevisionId) - .and(new BasicDBObject(MongoNode.KEY_BRANCH_ID, new BasicDBObject("$exists", false))) - .get(); + QueryBuilder qb = QueryBuilder.start(MongoCommit.KEY_FAILED).notEquals(Boolean.TRUE) + .and(MongoCommit.KEY_REVISION_ID).lessThanEquals(headRevisionId); + if (branchId == null) { + qb = qb.and(new BasicDBObject(MongoNode.KEY_BRANCH_ID, new BasicDBObject("$exists", false))); + } else { + qb = qb.and(MongoNode.KEY_BRANCH_ID).is(branchId); + } + + DBObject query = qb.get(); DBObject fields = new BasicDBObject(MongoCommit.KEY_REVISION_ID, 1); DBObject orderBy = new BasicDBObject(MongoCommit.KEY_REVISION_ID, -1); MongoCommit commit = (MongoCommit)collection.findOne(query, fields, orderBy); - return commit.getRevisionId(); + return commit != null? commit.getRevisionId() : 0L; } } Index: src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKCommitAddTest.java =================================================================== --- src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKCommitAddTest.java (revision 1433907) +++ src/test/java/org/apache/jackrabbit/mongomk/impl/MongoMKCommitAddTest.java (working copy) @@ -175,4 +175,21 @@ } if (debug) System.out.println("Final Result:" + commitMonitor); } + + @Test + public void existingNodesMerged() throws Exception { + String rev = mk.commit("/", "+\"a\" : {}", null, null); + mk.commit("/", "+\"a/b\" : {}", null, null); + mk.commit("/", "^\"a/key1\" : \"value1\"", null, null); + + // Commit to rev before key1 and b were added + mk.commit("/", "^\"a/key2\" : \"value2\"", rev, null); + + // Check that key1 and b were merged + String nodes = mk.getNodes("/", null, 1 /*depth*/, 0 /*offset*/, -1 /*maxChildNodes*/, null /*filter*/); + JSONObject obj = parseJSONObject(nodes); + assertPropertyValue(obj, ":childNodeCount", 1L); + assertPropertyValue(obj, "a/key1", "value1"); + assertPropertyValue(obj, "a/key2", "value2"); + } } \ No newline at end of file