void NewKeyStrategy::resolveConflict (const MergeTask & task, Key & conflictKey, MergeResult & result) { ConflictOperation ourOperation = getOurConflictOperation (conflictKey); ConflictOperation theirOperation = getTheirConflictOperation (conflictKey); string ourLookup = rebasePath (conflictKey, task.mergeRoot, task.ourParent); string theirLookup = rebasePath (conflictKey, task.mergeRoot, task.theirParent); // TODO: this is a subset of the automergestrategy // the automergestrategy could be split up into several smaller strategies switch (ourOperation) { case CONFLICT_SAME: if (theirOperation == CONFLICT_ADD) { Key source = task.theirs.lookup (theirLookup); copyKeyValue (source, conflictKey); result.resolveConflict (conflictKey); result.addMergeKey (conflictKey); } break; case CONFLICT_ADD: if (theirOperation == CONFLICT_SAME) { Key source = task.ours.lookup (ourLookup); copyKeyValue (source, conflictKey); result.resolveConflict (conflictKey); result.addMergeKey (conflictKey); } break; default: break; } }
void MetaMergeStrategy::resolveConflict(const MergeTask& task, Key& conflictKey, MergeResult& result) { conflictKey.rewindMeta(); Key currentMeta; string baseLookup = rebasePath (conflictKey, task.mergeRoot, task.baseParent); string ourLookup = rebasePath (conflictKey, task.mergeRoot, task.ourParent); string theirLookup = rebasePath (conflictKey, task.mergeRoot, task.theirParent); Key baseKey = task.base.lookup(baseLookup); Key ourKey = task.ours.lookup(ourLookup); Key theirKey = task.theirs.lookup(theirLookup); Key root ("user/", KEY_END); KeySet baseMeta = getMetaKeys (baseKey); KeySet ourMeta = getMetaKeys (ourKey); KeySet theirMeta = getMetaKeys (theirKey); MergeTask metaTask(BaseMergeKeys (baseMeta, root), OurMergeKeys (ourMeta, root), TheirMergeKeys (theirMeta, root), root); MergeResult metaResult = innerMerger.mergeKeySet(metaTask); KeySet mergedMeta = metaResult.getMergedKeys(); Key current; mergedMeta.rewind(); while ((current = mergedMeta.next())) { string metaName = current.getName().substr(string("user/").length()); conflictKey.setMeta(metaName, current.getString()); } ConflictOperation ourOperation = getOurConflictOperation(conflictKey); ConflictOperation theirOperation = getTheirConflictOperation(conflictKey); if (!metaResult.hasConflicts ()) { if (ourOperation == CONFLICT_META && theirOperation == CONFLICT_META) { // TODO: addConflict deletes the key content // without this strategy restoring the value the value would be lost // this happens only for CONFLICT_META <--> CONFLICT_META conflicts // add a test for this behaviour copyKeyValue(ourKey, conflictKey); result.resolveConflict (conflictKey); result.addMergeKey (conflictKey); } } }
void AutoMergeStrategy::resolveConflict(const MergeTask& task, Key& conflictKey, MergeResult& result) { ConflictOperation ourOperation = getOurConflictOperation(conflictKey); ConflictOperation theirOperation = getTheirConflictOperation(conflictKey); string ourLookup = rebasePath (conflictKey, task.mergeRoot, task.ourParent); string theirLookup = rebasePath (conflictKey, task.mergeRoot, task.theirParent); switch (ourOperation) { case SAME: if (theirOperation == MODIFY || theirOperation == ADD) { Key source = task.theirs.lookup(theirLookup); conflictKey.setString(source.getString()); result.resolveConflict(conflictKey); result.addMergeKey(conflictKey); } if (theirOperation == DELETE) { result.resolveConflict(conflictKey); } break; case MODIFY: case ADD: if (theirOperation == SAME) { Key source = task.ours.lookup(ourLookup); conflictKey.setString(source.getString()); result.resolveConflict(conflictKey); result.addMergeKey(conflictKey); } break; case DELETE: if (theirOperation == SAME) { result.resolveConflict(conflictKey); } break; case META: break; } }
void OneSideValueStrategy::resolveConflict(const MergeTask& task, Key& conflictKey, MergeResult& result) { ConflictOperation ourOperation = getOurConflictOperation (conflictKey); ConflictOperation theirOperation = getTheirConflictOperation (conflictKey); string ourLookup = rebasePath (conflictKey, task.mergeRoot, task.ourParent); string theirLookup = rebasePath (conflictKey, task.mergeRoot, task.theirParent); // TODO: this is a subset of the onesidestrategy // the onesidestrategy could be split up into several smaller strategies if ((ourOperation == CONFLICT_SAME && theirOperation == CONFLICT_MODIFY) || (ourOperation == CONFLICT_MODIFY && theirOperation == CONFLICT_SAME)) { string lookupPath; Key winningKey; switch (winningSide) { case BASE: lookupPath = rebasePath (conflictKey, task.mergeRoot, task.baseParent); winningKey = task.base.lookup (lookupPath); break; case OURS: lookupPath = rebasePath (conflictKey, task.mergeRoot, task.ourParent); winningKey = task.ours.lookup (lookupPath); break; case THEIRS: lookupPath = rebasePath (conflictKey, task.mergeRoot, task.theirParent); winningKey = task.theirs.lookup (lookupPath); break; } if (winningKey) { conflictKey.setString (winningKey.getString ()); result.resolveConflict (conflictKey); result.addMergeKey (conflictKey); } } }
void InteractiveMergeStrategy::resolveConflict (const MergeTask & task, Key & conflictKey, MergeResult & result) { ConflictOperation ours = getOurConflictOperation (conflictKey); ConflictOperation theirs = getTheirConflictOperation (conflictKey); outputStream << "merging key " << conflictKey.getName () << endl; outputStream << endl; outputStream << "======== CONFLICT ========" << endl; outputStream << "our operation: " << MergeConflictOperation::getFromTag (ours) << endl; outputStream << "their operation: " << MergeConflictOperation::getFromTag (theirs) << endl; outputStream << endl; Key baseKey = task.base.lookup (rebasePath (conflictKey, task.mergeRoot, task.baseParent)); Key ourKey = task.ours.lookup (rebasePath (conflictKey, task.mergeRoot, task.ourParent)); Key theirKey = task.theirs.lookup (rebasePath (conflictKey, task.mergeRoot, task.theirParent)); outputStream << "======== KEY VALUES ========" << endl; outputKeyInfo ("base", baseKey, outputStream); outputKeyInfo ("ours", ourKey, outputStream); outputKeyInfo ("theirs", theirKey, outputStream); outputStream << endl; char choice; ConflictResolutionSide side; bool repeat; string input; do { outputStream << "What do you want to do?" << endl; outputStream << "Take [o]urs, [t]eirs, [b]ase, [m]erge meta: "; repeat = false; getline (inputStream, input); if (input.size () == 0 || input.size () > 1) { repeat = true; continue; } choice = input.at (0); switch (choice) { case 'o': side = OURS; outputStream << "Choose our key" << endl; break; case 't': side = THEIRS; outputStream << "Choose their key" << endl; break; case 'b': side = BASE; outputStream << "Choose base key" << endl; break; default: repeat = true; } } while (repeat); outputStream << endl; OneSideStrategy strategy (side); strategy.resolveConflict (task, conflictKey, result); outputStream << "Key merged..." << endl; }