Line data Source code
1 :
2 : #include "kdbmerge.h"
3 : #include "kdb.h"
4 : #include "kdbassert.h"
5 : #include "kdblogger.h"
6 : #include "kdbprivate.h"
7 : #include <ctype.h>
8 : #include <stdbool.h>
9 : #include <stdio.h>
10 : #include <stdlib.h>
11 : #include <string.h>
12 :
13 : #define INT_BUF_SIZE 11 // Avoid math.h. int has at most 10 digits, +1 for \0
14 :
15 : /**
16 : * @brief Get a statistical value from an information key
17 : * @param informationKey contains the statistics in its meta information
18 : * @param metaName which statistic to get
19 : * @param retval the statistical value
20 : * @param retval -1 on error
21 : */
22 668 : static int getStatisticalValue (Key * informationKey, char * metaName)
23 : {
24 668 : const Key * metaKey = keyGetMeta (informationKey, metaName);
25 668 : if (metaKey == NULL)
26 : {
27 : return 0;
28 : }
29 108 : char * test = elektraMalloc (keyGetValueSize (metaKey));
30 108 : if (keyGetString (metaKey, test, keyGetValueSize (metaKey)) < 0)
31 : {
32 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not get statistical value.");
33 0 : return -1;
34 : }
35 108 : int asInt = atoi (test);
36 108 : elektraFree (test);
37 108 : return asInt;
38 : }
39 :
40 : /**
41 : * @brief Set a statistical value in an information key.
42 : * @param informationKey contains the statistics in its meta information
43 : * @param metaName which statistic to set
44 : * @param value which value to set it to, must be a number
45 : *
46 : * This enforces that a number is set.
47 : */
48 108 : static void setStatisticalValue (Key * informationKey, char * metaName, int value)
49 : {
50 : char stringy[INT_BUF_SIZE];
51 108 : int printsize = snprintf (stringy, INT_BUF_SIZE, "%d", value);
52 108 : if (printsize < INT_BUF_SIZE)
53 : {
54 108 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Statistical value was too large for its buffer.");
55 : }
56 108 : ssize_t size = keySetMeta (informationKey, metaName, stringy);
57 108 : if (size <= 0)
58 : {
59 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not set statistical value.");
60 : }
61 108 : }
62 :
63 : /**
64 : * @brief Increase a statistical value in an information key by one
65 : * @param informationKey contains the statistics in its meta information
66 : * @param metaName which statistic to increase
67 : * @retval new value
68 : */
69 108 : static int increaseStatisticalValue (Key * informationKey, char * metaName)
70 : {
71 108 : int value = getStatisticalValue (informationKey, metaName);
72 108 : value++;
73 108 : setStatisticalValue (informationKey, metaName, value);
74 108 : return value;
75 : }
76 :
77 : /**
78 : * @param informationKey contains the statistics in its meta information
79 : * @retval the number of non-overlap conflicts where only base exists
80 : */
81 : static int getNonOverlapOnlyBaseConflicts (Key * informationKey)
82 : {
83 112 : return getStatisticalValue (informationKey, "nonOverlapOnlyBaseCounter");
84 : }
85 :
86 : /**
87 : * @param informationKey contains the statistics in its meta information
88 : * @retval the number of non-overlap conflicts where all keys existed
89 : */
90 112 : static int getNonOverlapAllExistConflicts (Key * informationKey)
91 : {
92 112 : int nonOverlapAllExistCounter = getStatisticalValue (informationKey, "nonOverlapAllExistCounter");
93 112 : if (nonOverlapAllExistCounter % 3 != 0)
94 : {
95 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Parameter input must not be null.");
96 : }
97 112 : return nonOverlapAllExistCounter / 3;
98 : }
99 :
100 : /**
101 : * @param informationKey contains the statistics in its meta information
102 : * @retval the number of non-overlap conflicts where the key in the base set was empty
103 : */
104 112 : static int getNonOverlapBaseEmptyConflicts (Key * informationKey)
105 : {
106 112 : int nonOverlapBaseEmptyCounter = getStatisticalValue (informationKey, "nonOverlapBaseEmptyCounter");
107 112 : if (nonOverlapBaseEmptyCounter % 2 != 0)
108 : {
109 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Parameter input must not be null.");
110 : }
111 112 : return nonOverlapBaseEmptyCounter / 2;
112 : }
113 :
114 : /**
115 : * @param informationKey contains the statistics in its meta information
116 : * @retval the number of overlaps where all 3 keys were different
117 : */
118 112 : static int getOverlap3different (Key * informationKey)
119 : {
120 112 : int overlap3different = getStatisticalValue (informationKey, "overlap3different");
121 112 : if (overlap3different % 3 != 0)
122 : {
123 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Parameter input must not be null.");
124 : }
125 112 : return overlap3different / 3;
126 : }
127 :
128 : /**
129 : * @param informationKey contains the statistics in its meta information
130 : * @retval the number of overlaps where one key was empty, thus the other two keys had different values
131 : */
132 112 : static int getOverlap1empty (Key * informationKey)
133 : {
134 112 : int overlap1empty = getStatisticalValue (informationKey, "overlap1empty");
135 112 : if (overlap1empty % 2 != 0)
136 : {
137 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Parameter input must not be null.");
138 : }
139 112 : return overlap1empty / 2;
140 : }
141 :
142 : /**
143 : * @param informationKey contains the statistics in its meta information
144 : * @retval the number of overlaps that happened
145 : */
146 : static int getTotalOverlaps (Key * informationKey)
147 : {
148 112 : return getOverlap1empty (informationKey) + getOverlap3different (informationKey);
149 : }
150 :
151 : /**
152 : * @param informationKey contains the statistics in its meta information
153 : * @retval the number of non-overlaps that happened
154 : */
155 112 : static int getTotalNonOverlaps (Key * informationKey)
156 : {
157 224 : return getNonOverlapBaseEmptyConflicts (informationKey) + getNonOverlapAllExistConflicts (informationKey) +
158 112 : getNonOverlapOnlyBaseConflicts (informationKey);
159 : }
160 :
161 : /**
162 : * @param informationKey contains the statistics in its meta information
163 : * @retval the number of overlaps and non-overlaps that happened
164 : */
165 112 : static int getTotalConflicts (Key * informationKey)
166 : {
167 224 : return getTotalNonOverlaps (informationKey) + getTotalOverlaps (informationKey);
168 : }
169 :
170 : /**
171 : * @brief Removes one string from the other
172 : * @param sub this will be removed from string
173 : * @param string sub is removed from this char *
174 : * @returns the resulting string
175 : */
176 246 : static char * strremove (char * string, const char * sub)
177 : {
178 246 : size_t length = strlen (sub);
179 246 : if (length > 0)
180 : {
181 : char * p = string;
182 492 : while ((p = strstr (p, sub)) != NULL)
183 : {
184 246 : memmove (p, p + length, strlen (p + length) + 1);
185 : }
186 : }
187 246 : return string;
188 : }
189 :
190 : /**
191 : * @brief This is the counterpart to the removeRoot function
192 : * @param input keys are from here
193 : * @param result all keys with extended name will be appended here
194 : * @param informationKey errors will be set here
195 : * @retval -1 on error
196 : * @retval 0 on success
197 : */
198 96 : static int prependStringToAllKeyNames (KeySet * result, KeySet * input, const char * string, Key * informationKey)
199 : {
200 96 : if (input == NULL)
201 : {
202 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Parameter input must not be null.");
203 0 : return -1;
204 : }
205 96 : if (result == NULL)
206 : {
207 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Parameter result must not be null.");
208 0 : return -1;
209 : }
210 96 : if (string == NULL)
211 : {
212 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Parameter string must not be null.");
213 0 : return -1;
214 : }
215 : Key * key;
216 96 : ksRewind (input);
217 262 : while ((key = ksNext (input)) != NULL)
218 : {
219 70 : char * newName = elektraMalloc (keyGetNameSize (key) + strlen (string));
220 70 : strcpy (newName, string);
221 70 : strcat (newName, keyName (key));
222 70 : Key * duplicateKey = keyDup (key); // keySetName returns -1 if key was inserted to a keyset before
223 70 : int status = keySetName (duplicateKey, newName);
224 70 : elektraFree (newName);
225 70 : if (status < 0)
226 : {
227 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not set key name.");
228 : }
229 70 : status = ksAppendKey (result, duplicateKey);
230 70 : if (status < 0)
231 : {
232 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
233 : }
234 : }
235 : return 0;
236 : }
237 :
238 : /**
239 : * @brief Remove the root from each key of a set
240 : * @param original the key set from which root will be rmeoved
241 : * @param root remove this from all the keys
242 : * @param informationKey will contain information if an error occurs
243 : * @returns a new key set without the root
244 : *
245 : * Example: If root is user/example and the KeySet contains a key with the name user/example/something then
246 : * the returned KeySet will contain the key /something.
247 : */
248 336 : static KeySet * removeRoot (KeySet * original, Key * root, Key * informationKey)
249 : {
250 336 : ksRewind (original);
251 336 : KeySet * result = ksNew (0, KS_END);
252 336 : const char * rootKeyNameString = keyName (root);
253 : Key * currentKey;
254 918 : while ((currentKey = ksNext (original)) != NULL)
255 : {
256 246 : char * currentKeyNameString = elektraMalloc (keyGetNameSize (currentKey));
257 246 : if (keyGetName (currentKey, currentKeyNameString, keyGetNameSize (currentKey)) < 0)
258 : {
259 0 : ELEKTRA_ASSERT (false, "ERROR: This should not happen");
260 : elektraFree (currentKeyNameString);
261 : ksDel (result);
262 : return NULL;
263 : };
264 246 : if (keyIsBelow (root, currentKey) || keyCmp (currentKey, root) == 0)
265 246 : {
266 246 : Key * keyCopy = keyDup (currentKey);
267 : int retVal;
268 246 : if (keyIsBelow (root, currentKey))
269 : {
270 246 : currentKeyNameString = strremove (currentKeyNameString, rootKeyNameString);
271 246 : retVal = keySetName (keyCopy, currentKeyNameString);
272 : }
273 : else
274 : {
275 : // If the root itself is in the keyset then create a special name for it as it would be empty otherwise
276 0 : retVal = keySetName (keyCopy, "/root");
277 : }
278 246 : if (retVal < 0)
279 : {
280 0 : elektraFree (currentKeyNameString);
281 0 : ksDel (result);
282 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Setting new key name was not possible.");
283 : }
284 246 : ksAppendKey (result, keyCopy);
285 246 : elektraFree (currentKeyNameString);
286 : }
287 : else
288 : {
289 0 : elektraFree (currentKeyNameString);
290 0 : ksDel (result);
291 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Setting new key name was not possible.");
292 : }
293 : }
294 : return result;
295 : }
296 :
297 : /**
298 : * @brief Compares two keys
299 : * @retval true if two keys are equal
300 : * @retval false otherwise
301 : */
302 636 : static bool keysAreEqual (Key * a, Key * b)
303 : {
304 : // Two nothings are not keys and thus false too
305 636 : if (a == NULL || b == NULL)
306 : {
307 : return false;
308 : }
309 600 : if (keyGetValueSize (a) != keyGetValueSize (b))
310 : {
311 : return false;
312 : }
313 600 : if (0 != memcmp (keyValue (a), keyValue (b), keyGetValueSize (a)))
314 : {
315 : return false;
316 : }
317 276 : return true;
318 : }
319 :
320 : /**
321 : * @brief Helper function for checkSingleSet for when the key (name is relevant) is only in two of the three key sets
322 : * @retval -1 on error
323 : * @retval 0 on success
324 : */
325 72 : static int twoOfThreeExistHelper (Key * checkedKey, Key * keyInFirst, Key * keyInSecond, KeySet * result, bool checkedIsDominant,
326 : int baseIndicator, Key * informationKey)
327 : {
328 : Key * existingKey;
329 72 : bool thisConflict = false;
330 : /** This if or the else if happen when our and their set have a key that
331 : * base does not have. This is a conflict case.
332 : * This place is hit twice, thus overlap1empty gets double the amount of errors.
333 : */
334 72 : if (keyInFirst != NULL)
335 : {
336 : existingKey = keyInFirst;
337 : }
338 36 : else if (keyInSecond != NULL)
339 : {
340 : existingKey = keyInSecond;
341 : }
342 : else
343 : {
344 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
345 0 : return -1;
346 : }
347 : if (thisConflict)
348 : {
349 : increaseStatisticalValue (informationKey, "nonOverlapBaseEmptyCounter");
350 : }
351 72 : if (!keysAreEqual (checkedKey, existingKey))
352 : {
353 : // overlap with single empty
354 : // This spot is hit twice for a single overlap conflict. Thus calculate half later on.
355 36 : increaseStatisticalValue (informationKey, "overlap1empty");
356 36 : if (checkedIsDominant) // TODO This also happens when there is no conflict
357 : {
358 8 : if (ksAppendKey (result, checkedKey) < 0)
359 : {
360 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
361 0 : return -1;
362 : }
363 : }
364 : }
365 : else
366 : {
367 : // uses the NULL properties of keysAreEqual
368 36 : if (keysAreEqual (checkedKey, keyInFirst) && baseIndicator == 2)
369 : {
370 6 : thisConflict = true;
371 : }
372 36 : if (keysAreEqual (checkedKey, keyInSecond) && baseIndicator == 1)
373 : {
374 6 : thisConflict = true;
375 : }
376 36 : if (thisConflict)
377 : {
378 : // base is empty and other and their have the same (non-empty) value
379 : // this is a conflict
380 12 : increaseStatisticalValue (informationKey, "nonOverlapBaseEmptyCounter");
381 12 : if (checkedIsDominant)
382 : {
383 4 : if (ksAppendKey (result, checkedKey) < 0)
384 : {
385 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
386 0 : return -1;
387 : }
388 : }
389 : }
390 : }
391 : return 0;
392 : }
393 :
394 : /**
395 : * @brief Helper function for allExistHelper checking if two of the three keys are equal and acting accordingly (side effects!)
396 : * @retval true if exactly two of the three keys have the same value
397 : * @retval false otherwise
398 : */
399 126 : static bool twoOfThoseKeysAreEqual (Key * checkedKey, Key * keyInFirst, Key * keyInSecond, KeySet * result, bool checkedIsDominant,
400 : int baseIndicator, Key * informationKey)
401 : {
402 : /**
403 : * One example for the next 3 ifs
404 : *
405 : * Cell contents are the values of the keys (/#0, /#1, ...)
406 : * in the different key sets
407 : * base our their
408 : * /#0 one previous previous
409 : * /#1 two one one
410 : * /#2 three two two
411 : * /#3 four three three
412 : * /#4 five four four
413 : * /#5 five five
414 : * In the area from top down to line /#4 (inclusive) each cell triggers
415 : * the nonOverlapAllExistCounter. However, we must not count one conflict
416 : * multiple times, thus divide by 3 as there are three key sets (=columns).
417 : */
418 126 : if (keysAreEqual (keyInFirst, keyInSecond))
419 : {
420 36 : if (baseIndicator == 0)
421 : {
422 : /** This is a non-overlap conflict
423 : * Base is currently checked and has value A, their and our have a different value B
424 : */
425 12 : increaseStatisticalValue (informationKey, "nonOverlapAllExistCounter");
426 12 : if (checkedIsDominant)
427 : {
428 : // If base is also dominant then append it's key
429 0 : if (ksAppendKey (result, checkedKey) < 0)
430 : {
431 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
432 : }
433 : }
434 : }
435 : return true;
436 : }
437 90 : else if (keysAreEqual (checkedKey, keyInFirst))
438 : {
439 36 : if (baseIndicator == 0)
440 : {
441 12 : if (ksAppendKey (result, keyInSecond) < 0)
442 : {
443 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
444 : }
445 : }
446 : else
447 : {
448 24 : if (baseIndicator == 2)
449 : {
450 : /** This is a non-overlap conflict
451 : * Base is currently secondCompare and has value A, their and our have a different
452 : * value B
453 : */
454 12 : increaseStatisticalValue (informationKey, "nonOverlapAllExistCounter");
455 12 : if (checkedIsDominant)
456 : {
457 : // If base is also dominant then append it's key
458 4 : if (ksAppendKey (result, checkedKey) < 0)
459 : {
460 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
461 : }
462 : }
463 : }
464 : }
465 : return true;
466 : }
467 54 : else if (keysAreEqual (checkedKey, keyInSecond))
468 : {
469 :
470 36 : if (baseIndicator == 0)
471 : {
472 12 : if (ksAppendKey (result, keyInFirst) < 0)
473 : {
474 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
475 : }
476 : }
477 : else
478 : {
479 24 : if (baseIndicator == 1)
480 : {
481 : /** This is a non-overlap conflict
482 : * Base is currently firstCompare and has value A, their and our have a different
483 : * value B
484 : */
485 12 : increaseStatisticalValue (informationKey, "nonOverlapAllExistCounter");
486 12 : if (checkedIsDominant)
487 : {
488 : // If base is also dominant then append it's key
489 4 : if (ksAppendKey (result, checkedKey) < 0)
490 : {
491 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
492 : }
493 : }
494 : }
495 : }
496 : return true;
497 : }
498 : else
499 : {
500 : return false;
501 : }
502 : }
503 :
504 : /**
505 : * @brief Helper function for checkSingleSet for when a key exists in all key sets.
506 : * @retval -1 on error
507 : * @retval 0 on success
508 : */
509 156 : static int allExistHelper (Key * checkedKey, Key * keyInFirst, Key * keyInSecond, KeySet * result, bool checkedIsDominant,
510 : int baseIndicator, Key * informationKey)
511 : {
512 156 : if (keysAreEqual (checkedKey, keyInFirst) && keysAreEqual (checkedKey, keyInSecond))
513 : {
514 : /**
515 : * append any of the three keys
516 : * will be appended multiple times, but that doesn't matter for the result
517 : */
518 30 : if (ksAppendKey (result, checkedKey) < 0)
519 : {
520 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
521 0 : return -1;
522 : }
523 : }
524 : else
525 : {
526 126 : if (!twoOfThoseKeysAreEqual (checkedKey, keyInFirst, keyInSecond, result, checkedIsDominant, baseIndicator, informationKey))
527 : {
528 : /**
529 : * Overlap conflict case
530 : *
531 : * The same overlap conflict gets detected three times, once for each of the three invocations of
532 : * checkSingleSet. However, only one of those three times is required. Thus use a getter function
533 : * that calculates a third.
534 : */
535 18 : increaseStatisticalValue (informationKey, "overlap3different");
536 18 : if (checkedIsDominant)
537 : {
538 4 : if (ksAppendKey (result, checkedKey) < 0)
539 : {
540 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
541 0 : return -1;
542 : }
543 : }
544 : }
545 : }
546 : return 0;
547 : }
548 :
549 :
550 : /**
551 : * and the element is not already in the result key set.
552 : * It should be called 3 times, each time with a different of our key set, their key set and base key set as checkedSet parameter.
553 : * Which of the remaining two key sets is firstCompared or secondCompared is irrelevant.
554 : *
555 : * @param checkedIsDominant parameter is for the merge strategy. If a conflict occurs and checkedIsDominant is true then the current element
556 : * of checkedSet is inserted. Consequently, it has to be set to true for exactly one of the three calls of this function.
557 : *
558 : * @param baseIndicator indicates which of the three key sets is the base key set. 0 is checkedSet, 1 firstcompared, 2 secondCompared
559 : * @param informationKey will contain information if an error ocurred
560 : *
561 : * @retval -1 on error
562 : * @retval 0 on success
563 : *
564 : */
565 336 : static int checkSingleSet (KeySet * checkedSet, KeySet * firstCompared, KeySet * secondCompared, KeySet * result, bool checkedIsDominant,
566 : int baseIndicator, Key * informationKey)
567 : {
568 336 : ksRewind (checkedSet);
569 336 : ksRewind (firstCompared);
570 336 : ksRewind (secondCompared);
571 : Key * checkedKey;
572 918 : while ((checkedKey = ksNext (checkedSet)) != NULL)
573 : {
574 : /**
575 : * Check if a key with the same name exists
576 : * Nothing about values is said yet
577 : */
578 246 : Key * keyInFirst = ksLookup (firstCompared, checkedKey, 0);
579 246 : Key * keyInSecond = ksLookup (secondCompared, checkedKey, 0);
580 246 : if (keyInFirst != NULL && keyInSecond != NULL)
581 : {
582 156 : allExistHelper (checkedKey, keyInFirst, keyInSecond, result, checkedIsDominant, baseIndicator, informationKey);
583 : }
584 90 : else if (keyInFirst == NULL && keyInSecond == NULL)
585 : {
586 18 : if (baseIndicator == 0)
587 : {
588 : /**
589 : * Non-overlap conflict https://www.gnu.org/software/diffutils/manual/html_node/diff3-Merging.html
590 : *
591 : * Here keys from base could be appended. But doing so is not useful.
592 : */
593 6 : increaseStatisticalValue (informationKey, "nonOverlapOnlyBaseCounter");
594 : }
595 : else
596 : {
597 12 : if (ksAppendKey (result, checkedKey) < 0)
598 : {
599 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not append key.");
600 : }
601 : }
602 : }
603 : else
604 : {
605 72 : twoOfThreeExistHelper (checkedKey, keyInFirst, keyInSecond, result, checkedIsDominant, baseIndicator,
606 : informationKey);
607 : }
608 : }
609 336 : return 0;
610 : }
611 :
612 :
613 : /**
614 : *
615 : * This function can incorporate changes from two modified versions (our and their) into a common preceding version (base) of a key set.
616 : * This lets you merge the sets of changes represented by the two newer key sets. This is called a three-way merge between key sets.
617 : *
618 : * @brief Join three key sets together
619 : * @param our our key set
620 : * @param ourRoot key that has the root of our as name
621 : * @param their their key set
622 : * @param theirRoot key that has the root of their as name
623 : * @param base base key set
624 : * @param baseRoot key that has the root of base as name
625 : * @param resultRoot the name of this key determines where the resulting key set will be stored
626 : * @param strategy specify which merge strategy to choose in case of a conflict
627 : * @param informationKey stores errors as well as statistics
628 : * @returns the merged key set and NULL on error
629 : */
630 112 : KeySet * elektraMerge (KeySet * our, Key * ourRoot, KeySet * their, Key * theirRoot, KeySet * base, Key * baseRoot, Key * resultRoot,
631 : int strategy, Key * informationKey)
632 : {
633 : ELEKTRA_LOG ("cmerge starts with strategy %d", strategy);
634 112 : KeySet * result = ksNew (0, KS_END);
635 112 : KeySet * ourCropped = removeRoot (our, ourRoot, informationKey);
636 112 : KeySet * theirCropped = removeRoot (their, theirRoot, informationKey);
637 112 : KeySet * baseCropped = removeRoot (base, baseRoot, informationKey);
638 112 : ksRewind (ourCropped);
639 112 : ksRewind (theirCropped);
640 112 : ksRewind (baseCropped);
641 112 : bool ourDominant = false;
642 112 : bool theirDominant = false;
643 112 : switch (strategy)
644 : {
645 : case MERGE_STRATEGY_OUR:
646 36 : ourDominant = true;
647 36 : break;
648 : case MERGE_STRATEGY_THEIR:
649 36 : theirDominant = true;
650 36 : break;
651 : }
652 :
653 112 : checkSingleSet (baseCropped, ourCropped, theirCropped, result, false, 0, informationKey); // base is never dominant
654 112 : checkSingleSet (theirCropped, baseCropped, ourCropped, result, theirDominant, 1, informationKey);
655 112 : checkSingleSet (ourCropped, theirCropped, baseCropped, result, ourDominant, 2, informationKey);
656 112 : if (ksDel (ourCropped) != 0 || ksDel (theirCropped) != 0 || ksDel (baseCropped) != 0)
657 : {
658 0 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Could not delete a key set.");
659 0 : return NULL;
660 : }
661 112 : if (getTotalConflicts (informationKey) > 0)
662 : {
663 48 : if (strategy == MERGE_STRATEGY_ABORT)
664 : {
665 16 : ksDel (result);
666 16 : ELEKTRA_SET_INTERNAL_ERROR (informationKey, "Abort strategy was set and at least one conflict occured.");
667 16 : return NULL;
668 : }
669 : }
670 96 : KeySet * resultWithRoot = ksNew (0, KS_END);
671 96 : prependStringToAllKeyNames (resultWithRoot, result, keyName (resultRoot), informationKey);
672 96 : ksDel (result);
673 96 : return resultWithRoot;
674 : }
|