Skip to content

Commit 25ad016

Browse files
committed
diff BUGFIX always use source ctx in diff nodes
There may be modules missing in the other context preventing even a leaf duplication. Fixes #2502
1 parent e8aa7d4 commit 25ad016

1 file changed

Lines changed: 62 additions & 41 deletions

File tree

src/diff.c

Lines changed: 62 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,67 @@ lyd_diff_insert_sibling(struct lyd_node *sibling, struct lyd_node *node, struct
318318
lyd_insert_node(NULL, first_sibling, node, LYD_INSERT_NODE_LAST_BY_SCHEMA);
319319
}
320320

321+
/**
322+
* @brief Duplicate a node with any parents and connect it to the parent, if any.
323+
*
324+
* @param[in] node Node to duplicate.
325+
* @param[in] op Diff operation.
326+
* @param[in] parent Parent to connect to, if any.
327+
* @param[in,out] first First top-level node.
328+
* @param[out] dup Duplicated @p node.
329+
* @return LY_ERR value.
330+
*/
331+
static LY_ERR
332+
lyd_diff_dup(const struct lyd_node *node, enum lyd_diff_op op, struct lyd_node *parent, struct lyd_node **first,
333+
struct lyd_node **dup)
334+
{
335+
struct lyd_node *dup_parent, *d;
336+
const struct lyd_node *node_parent;
337+
const struct lysc_node *sparent;
338+
uint32_t diff_opts;
339+
340+
diff_opts = LYD_DUP_NO_META | LYD_DUP_WITH_FLAGS;
341+
if (lysc_is_userordered(node->schema)) {
342+
diff_opts |= LYD_DUP_NO_LYDS;
343+
}
344+
if ((op != LYD_DIFF_OP_REPLACE) || !lysc_is_userordered(node->schema) || (node->schema->flags & LYS_CONFIG_R)) {
345+
/* move applies only to the user-ordered list, no descendants */
346+
diff_opts |= LYD_DUP_RECURSIVE;
347+
}
348+
349+
/* duplicate the node */
350+
LY_CHECK_RET(lyd_dup_single(node, NULL, diff_opts, dup));
351+
352+
dup_parent = *dup;
353+
node_parent = node;
354+
sparent = parent ? parent->schema : NULL;
355+
while (lysc_data_parent(dup_parent->schema) &&
356+
!lyd_compare_schema_equal(lysc_data_parent(dup_parent->schema), sparent)) {
357+
node_parent = node_parent->parent;
358+
359+
/* duplicate the next parent */
360+
LY_CHECK_RET(lyd_dup_single(node_parent, NULL, LYD_DUP_NO_META | LYD_DUP_WITH_FLAGS, &d));
361+
362+
/* connect the existing dup tree into the parent */
363+
lyd_insert_node(d, NULL, dup_parent, LYD_INSERT_NODE_DEFAULT);
364+
dup_parent = d;
365+
}
366+
367+
/* connect to the parent/data tree */
368+
if (parent) {
369+
lyd_insert_node(parent, NULL, dup_parent, LYD_INSERT_NODE_DEFAULT);
370+
} else {
371+
lyd_diff_insert_sibling(*first, dup_parent, first);
372+
}
373+
374+
/* add parent operation, if any */
375+
if (dup_parent != *dup) {
376+
LY_CHECK_RET(lyd_new_meta(NULL, dup_parent, NULL, "yang:operation", "none", LYD_NEW_VAL_STORE_ONLY, NULL));
377+
}
378+
379+
return LY_SUCCESS;
380+
}
381+
321382
LY_ERR
322383
lyd_diff_add(const struct lyd_node *node, enum lyd_diff_op op, const char *orig_default, const char *orig_value,
323384
const char *key, const char *value, const char *position, const char *orig_key, const char *orig_position,
@@ -327,7 +388,6 @@ lyd_diff_add(const struct lyd_node *node, enum lyd_diff_op op, const char *orig_
327388
const struct lyd_node *parent = NULL;
328389
enum lyd_diff_op cur_op;
329390
struct lyd_meta *meta;
330-
uint32_t diff_opts;
331391
ly_bool found;
332392

333393
assert(diff);
@@ -406,47 +466,8 @@ lyd_diff_add(const struct lyd_node *node, enum lyd_diff_op op, const char *orig_
406466

407467
dup = diff_parent;
408468
} else {
409-
diff_opts = LYD_DUP_NO_META | LYD_DUP_WITH_PARENTS | LYD_DUP_WITH_FLAGS;
410-
if (lysc_is_userordered(node->schema)) {
411-
diff_opts |= LYD_DUP_NO_LYDS;
412-
}
413-
if ((op != LYD_DIFF_OP_REPLACE) || !lysc_is_userordered(node->schema) || (node->schema->flags & LYS_CONFIG_R)) {
414-
/* move applies only to the user-ordered list, no descendants */
415-
diff_opts |= LYD_DUP_RECURSIVE;
416-
}
417-
418469
/* duplicate the subtree (and connect to the diff if possible) */
419-
if (diff_parent && (LYD_CTX(diff_parent) != LYD_CTX(node))) {
420-
LY_CHECK_RET(lyd_dup_single_to_ctx(node, LYD_CTX(diff_parent), diff_parent, diff_opts, &dup));
421-
} else {
422-
LY_CHECK_RET(lyd_dup_single(node, diff_parent, diff_opts, &dup));
423-
}
424-
425-
/* find the first duplicated parent */
426-
if (!diff_parent) {
427-
diff_parent = dup->parent;
428-
while (diff_parent && diff_parent->parent) {
429-
diff_parent = diff_parent->parent;
430-
}
431-
} else {
432-
diff_parent = dup;
433-
while (diff_parent->parent && (diff_parent->parent->schema == parent->schema)) {
434-
diff_parent = diff_parent->parent;
435-
}
436-
}
437-
438-
/* no parent existed, must be manually connected */
439-
if (!diff_parent) {
440-
/* there actually was no parent to duplicate */
441-
lyd_diff_insert_sibling(*diff, dup, diff);
442-
} else if (!diff_parent->parent) {
443-
lyd_diff_insert_sibling(*diff, diff_parent, diff);
444-
}
445-
446-
/* add parent operation, if any */
447-
if (diff_parent && (diff_parent != dup)) {
448-
LY_CHECK_RET(lyd_new_meta(NULL, diff_parent, NULL, "yang:operation", "none", LYD_NEW_VAL_STORE_ONLY, NULL));
449-
}
470+
LY_CHECK_RET(lyd_diff_dup(node, op, diff_parent, diff, &dup));
450471
}
451472

452473
/* add subtree operation if needed */

0 commit comments

Comments
 (0)