-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18 from cujojs/add-rebase
Add rebase and unit test
- Loading branch information
Showing
4 changed files
with
87 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,24 +1,54 @@ | ||
var patches = require('./patches'); | ||
|
||
module.exports = function commute(left, right) { | ||
return right.reduce(function(pair, p2) { | ||
return left.reduceRight(function(pair, p1) { | ||
return commuteOne(pair, p1, p2); | ||
}, pair); | ||
}, { left: [], right: [] }) | ||
}; | ||
|
||
function commuteOne (pair, p1, p2) { | ||
var patch = patches[p2.op]; | ||
var commuted; | ||
module.exports = commute; | ||
|
||
commute.rtl = commuteRtL; | ||
|
||
/** | ||
* Given adjacent patch pair p1,p2, commute them to create a new | ||
* adjacent pair p2',p1' | ||
* @param {array} p1 JSON Patch | ||
* @param {array} p2 JSON Patch | ||
* @returns {array<array>} pair [commutedRight, commutedLeft] | ||
*/ | ||
function commute(p1, p2) { | ||
return runCommute(keepBoth, [[], []], p1, p2); | ||
} | ||
/** | ||
* Commute left and right and return only the newly commuted left, throwing | ||
* away the newly commuted right. | ||
* @param p1 | ||
* @param p2 | ||
* @returns {*} | ||
*/ | ||
function commuteRtL(p1, p2) { | ||
return runCommute(keepLeft, [], p1, p2); | ||
} | ||
|
||
function runCommute(f, accum, p1, p2) { | ||
return p2.reduce(function(accum, p2) { | ||
return p1.reduceRight(function(accum, p1) { | ||
return commuteOne(f, accum, p1, p2); | ||
}, accum); | ||
}, accum) | ||
} | ||
|
||
function commuteOne (f, accum, p1, p2) { | ||
var patch = patches[p2.op]; | ||
if (patch === void 0 || typeof patch.commute !== 'function') { | ||
throw new TypeError('patches cannot be commuted'); | ||
} | ||
|
||
commuted = patch.commute(p1, p2); | ||
pair.left.push(commuted[0]); | ||
pair.right.push(commuted[1]); | ||
return f(accum, patch.commute(p1, p2)); | ||
} | ||
|
||
function keepBoth(pair, commuted) { | ||
pair[0].push(commuted[0]); | ||
pair[1].push(commuted[1]); | ||
return pair; | ||
} | ||
|
||
function keepLeft(left, commuted) { | ||
left.push(commuted[0]); | ||
return left; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
var commuteRtL = require('./commute').rtl; | ||
var inverse = require('./inverse'); | ||
|
||
/** | ||
* Given a patch history (array of patches) and a single patch, rooted | ||
* at the same starting document context d1, rebase patch onto history | ||
* so that d1 + history -> d2, d2 + patch -> d3 | ||
* @param {array<array>} history array of JSON Patch | ||
* @param {array} patch JSON Patch | ||
* @returns {array} rebased patch which can be applied after history | ||
*/ | ||
module.exports = function rebase(history, patch) { | ||
return history.reduce(function(commuted, patchFromHistory) { | ||
return commuteRtL(inverse(patchFromHistory), commuted); | ||
}, patch); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
var buster = require('buster'); | ||
var assert = buster.referee.assert; | ||
|
||
var rebase = require('../lib/rebase'); | ||
var jiff = require('../jiff'); | ||
var deepEquals = require('../lib/deepEquals'); | ||
|
||
buster.testCase('rebase', { | ||
'should allow parallel patches': function() { | ||
var d1 = [1,2,3,4,5]; | ||
var d2a = [1,2,4,5]; | ||
var d2b = [1,2,3,6,4,5]; | ||
var d3 = [1,2,6,4,5]; | ||
|
||
// Two parallel patches created from d1 | ||
var d1pd2a = jiff.diff(d1, d2a); | ||
var d1pd2b = jiff.diff(d1, d2b); | ||
|
||
// Rebase d1pd2b onto d1pd2a | ||
var d2apd2b = rebase([d1pd2a], d1pd2b); | ||
|
||
var d3a = jiff.patch(d2apd2b, jiff.patch(d1pd2a, d1)); | ||
assert(deepEquals(d3, d3a)); | ||
} | ||
|
||
}); |