jackrabbit-oak-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Michael Dürig <mdue...@apache.org>
Subject Conflict handling through rebasing branches
Date Thu, 17 Jan 2013 17:15:28 GMT

Hi,

There are various places in Oak where conflicting updates to the content 
tree can occur: committing changes against a non root revision, merging 
changes from a branch into trunk and synchronisation of cluster nodes.

The Microkernel API currently doesn't specify a contract for merging 
conflicting changes but leaves it mostly to the underlying 
implementation. As discussed before [1] this is not satisfactory and I'd 
like to tighten the contract.

As announced earlier, I spent some time implementing various approaches 
for rebasing branches in Oak. Apart from the other problems this solves 
and which have been discussed at length, this also lends itself nicely 
for a central, clean and efficient way of handling conflicts (I briefly 
mentioned this in [2] already).

The core idea is to try to resolve all conflicts in a branch through 
rebasing it on top of the current trunk. After successfully rebasing a 
branch, merging it to trunk is as simple as fast forwarding the head of 
the trunk to the head of the branch.

Here are a naive sample implementations of the relevant methods in 
pseudo code. Note how commit is implemented in terms of branch and 
merge. I has not to be implemented that way but rather the observable 
behaviour should be like this.

/* Rebase branch on top of the head of the trunk. Returns false if
    a conflict occurs, true otherwise. */
boolean rebase(branch) {
     // See https://github.com/mduerig/jackrabbit-oak/commits/OAK-536
     // and https://github.com/mduerig/jackrabbit-oak/commits/OAK-536-2
     // for two possible implementations
}

int merge(branch) {
     while(true) {
         if (!rebase(branch)) {
             throw new MicroKernelException("merge conflict");
         }

         atomic {
             if (branch.baseRevision == trunk.headRevision) {
                 trunk.headRevision = branch.headRevision
                 return trunk.headRevision;
             }
         }
     }
}

int commit(baseRevision, jsop) {
     branch = createBranchFrom(baseRevision)
     branch.apply(jsop)
     if (!rebase(branch)) {
         throw new MicroKernelException("merge conflict");
     }
     return merge(branch)
}

Michael

[1] http://markmail.org/message/4xwfwbax3kpoysbp
[2] http://markmail.org/message/niam2xs2ora5rufi


Mime
View raw message