From 6d09e6dac992b8d73d6f85da3e4b73bb7d517ebf Mon Sep 17 00:00:00 2001 From: Brian Cavalier Date: Mon, 19 May 2014 19:53:46 -0400 Subject: [PATCH 1/2] Add rebase and unit test --- lib/commute.js | 58 ++++++++++++++++++++++++++++++++++----------- lib/rebase.js | 16 +++++++++++++ test/rebase-test.js | 26 ++++++++++++++++++++ 3 files changed, 86 insertions(+), 14 deletions(-) create mode 100644 lib/rebase.js create mode 100644 test/rebase-test.js diff --git a/lib/commute.js b/lib/commute.js index fea6031..ab47f35 100644 --- a/lib/commute.js +++ b/lib/commute.js @@ -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} 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; +} diff --git a/lib/rebase.js b/lib/rebase.js new file mode 100644 index 0000000..8a350e5 --- /dev/null +++ b/lib/rebase.js @@ -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} 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); +}; diff --git a/test/rebase-test.js b/test/rebase-test.js new file mode 100644 index 0000000..7386815 --- /dev/null +++ b/test/rebase-test.js @@ -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)); + } + +}); \ No newline at end of file From c85b6f04b5a89a79607a64d3235e844accd60a20 Mon Sep 17 00:00:00 2001 From: Brian Cavalier Date: Mon, 19 May 2014 22:26:42 -0400 Subject: [PATCH 2/2] Remove focus rocket --- test/jsonPatch-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jsonPatch-test.js b/test/jsonPatch-test.js index 46649c7..e069305 100644 --- a/test/jsonPatch-test.js +++ b/test/jsonPatch-test.js @@ -112,7 +112,7 @@ buster.testCase('jsonPatch', { refute.defined(result.x); }, - '=>should not allow moving to ancestor path': function() { + 'should not allow moving to ancestor path': function() { var from = '/a/b/c'; var to = '/a/b'; assert.exception(function() {