Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Implementation of MetaMergeStrategy
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : */
9 :
10 : #include <helper/keyhelper.hpp>
11 : #include <merging/metamergestrategy.hpp>
12 : #include <string>
13 :
14 : using namespace std;
15 : using namespace kdb::tools::helper;
16 :
17 : namespace kdb
18 : {
19 :
20 : namespace tools
21 : {
22 :
23 : namespace merging
24 : {
25 :
26 990 : KeySet MetaMergeStrategy::getMetaKeys (Key & key)
27 : {
28 990 : KeySet result;
29 :
30 990 : if (key)
31 : {
32 487 : key.rewindMeta ();
33 487 : Key currentMeta;
34 3888 : while ((currentMeta = key.nextMeta ()))
35 : {
36 1164 : string resultName = "user/" + currentMeta.getName ();
37 1940 : Key resultMeta = Key (resultName.c_str (), KEY_VALUE, currentMeta.getString ().c_str (), KEY_END);
38 388 : result.append (resultMeta);
39 : }
40 : }
41 :
42 990 : return result;
43 : }
44 :
45 330 : void MetaMergeStrategy::resolveConflict (const MergeTask & task, Key & conflictKey, MergeResult & result)
46 : {
47 330 : conflictKey.rewindMeta ();
48 660 : Key currentMeta;
49 :
50 660 : string baseLookup = rebasePath (conflictKey, task.mergeRoot, task.baseParent);
51 660 : string ourLookup = rebasePath (conflictKey, task.mergeRoot, task.ourParent);
52 660 : string theirLookup = rebasePath (conflictKey, task.mergeRoot, task.theirParent);
53 :
54 990 : Key baseKey = task.base.lookup (baseLookup);
55 990 : Key ourKey = task.ours.lookup (ourLookup);
56 990 : Key theirKey = task.theirs.lookup (theirLookup);
57 :
58 660 : Key root ("user/", KEY_END);
59 660 : KeySet baseMeta = getMetaKeys (baseKey);
60 660 : KeySet ourMeta = getMetaKeys (ourKey);
61 660 : KeySet theirMeta = getMetaKeys (theirKey);
62 :
63 2310 : MergeTask metaTask (BaseMergeKeys (baseMeta, root), OurMergeKeys (ourMeta, root), TheirMergeKeys (theirMeta, root), root);
64 :
65 660 : MergeResult metaResult = innerMerger.mergeKeySet (metaTask);
66 :
67 660 : KeySet mergedMeta = metaResult.getMergedKeys ();
68 660 : Key current;
69 : mergedMeta.rewind ();
70 2330 : while ((current = mergedMeta.next ()))
71 : {
72 1212 : string metaName = current.getName ().substr (string ("user/").length ());
73 404 : conflictKey.setMeta (metaName, current.getString ());
74 : }
75 :
76 330 : ConflictOperation ourOperation = getOurConflictOperation (conflictKey);
77 330 : ConflictOperation theirOperation = getTheirConflictOperation (conflictKey);
78 :
79 330 : if (!metaResult.hasConflicts ())
80 : {
81 330 : if (ourOperation == CONFLICT_META && theirOperation == CONFLICT_META)
82 : {
83 : // TODO: addConflict deletes the key content
84 : // without this strategy restoring the value the value would be lost
85 : // this happens only for CONFLICT_META <--> CONFLICT_META conflicts
86 : // add a test for this behaviour
87 2 : copyKeyValue (ourKey, conflictKey);
88 2 : result.resolveConflict (conflictKey);
89 2 : result.addMergeKey (conflictKey);
90 : }
91 : }
92 330 : }
93 : } // namespace merging
94 : } // namespace tools
95 : } // namespace kdb
|