'use strict';
var merge = require('../../merge');
var errors = require('../errors');
var isDeleted = require('./isDeleted');
var parseDoc = require('./parseDoc').parseDoc;
function revExists(metadata, rev) {
var found = false;
merge.traverseRevTree(metadata.rev_tree, function (leaf, pos, id) {
if ((pos + '-' + id) === rev) {
found = true;
}
});
return found;
}
function updateDoc(prev, docInfo, results, i, cb, writeDoc, newEdits) {
if (revExists(prev, docInfo.metadata.rev)) {
results[i] = docInfo;
return cb();
}
// TODO: some of these can be pre-calculated, but it's safer to just
// call merge.winningRev() and isDeleted() all over again
var previousWinningRev = merge.winningRev(prev);
var previouslyDeleted = isDeleted(prev, previousWinningRev);
var deleted = isDeleted(docInfo.metadata);
var isRoot = /^1-/.test(docInfo.metadata.rev);
if (previouslyDeleted && !deleted && newEdits && isRoot) {
var newDoc = docInfo.data;
newDoc._rev = previousWinningRev;
newDoc._id = docInfo.metadata.id;
docInfo = parseDoc(newDoc, newEdits);
}
var merged = merge.merge(prev.rev_tree, docInfo.metadata.rev_tree[0], 1000);
var inConflict = newEdits && (((previouslyDeleted && deleted) ||
(!previouslyDeleted && merged.conflicts !== 'new_leaf') ||
(previouslyDeleted && !deleted && merged.conflicts === 'new_branch')));
if (inConflict) {
var err = errors.error(errors.REV_CONFLICT);
results[i] = err;
return cb();
}
var newRev = docInfo.metadata.rev;
docInfo.metadata.rev_tree = merged.tree;
Eif (prev.rev_map) {
docInfo.metadata.rev_map = prev.rev_map; // used by leveldb
}
// recalculate
var winningRev = merge.winningRev(docInfo.metadata);
var winningRevIsDeleted = isDeleted(docInfo.metadata, winningRev);
// calculate the total number of documents that were added/removed,
// from the perspective of total_rows/doc_count
var delta = (previouslyDeleted === winningRevIsDeleted) ? 0 :
previouslyDeleted < winningRevIsDeleted ? -1 : 1;
var newRevIsDeleted = isDeleted(docInfo.metadata, newRev);
writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,
true, delta, i, cb);
}
module.exports = updateDoc; |