diff BUGFIX recursive delete and leaf default values
diff --git a/src/diff.c b/src/diff.c
index 42b6d10..83acef8 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1221,14 +1221,30 @@
lyd_diff_merge_create(struct lyd_node *diff_match, enum lyd_diff_op cur_op, const struct lyd_node *src_diff)
{
struct lyd_node *child;
+ const struct lysc_node_leaf *sleaf;
const char *str_val;
int dynamic;
LY_ERR ret;
switch (cur_op) {
case LYD_DIFF_OP_DELETE:
- /* delete operation, if any */
- if (!lyd_compare_single(diff_match, src_diff, 0)) {
+ if (diff_match->schema->nodetype == LYS_LEAF) {
+ sleaf = (struct lysc_node_leaf *)diff_match->schema;
+ } else {
+ sleaf = NULL;
+ }
+
+ if (sleaf && sleaf->dflt
+ && !sleaf->dflt->realtype->plugin->compare(sleaf->dflt, &((struct lyd_node_term *)src_diff)->value)) {
+ /* we deleted it, so a default value was in-use, and it matches the created value -> operation NONE */
+ LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_NONE));
+
+ if (diff_match->schema->nodetype & LYD_NODE_TERM) {
+ /* add orig-dflt metadata */
+ LY_CHECK_RET(lyd_new_meta(diff_match, NULL, "yang:orig-default",
+ diff_match->flags & LYD_DEFAULT ? "true" : "false", NULL));
+ }
+ } else if (!lyd_compare_single(diff_match, src_diff, 0)) {
/* deleted + created -> operation NONE */
LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_NONE));
@@ -1238,10 +1254,12 @@
diff_match->flags & LYD_DEFAULT ? "true" : "false", NULL));
}
} else {
- assert(diff_match->schema->nodetype == LYS_LEAF);
+ assert(sleaf);
/* we deleted it, but it was created with a different value -> operation REPLACE */
LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_REPLACE));
+ }
+ if (lyd_compare_single(diff_match, src_diff, 0)) {
/* current value is the previous one (meta) */
str_val = lyd_value2str((struct lyd_node_term *)diff_match, &dynamic);
ret = lyd_new_meta(diff_match, NULL, "yang:orig-value", str_val, NULL);
@@ -1318,9 +1336,11 @@
/* it was not modified, but should be deleted -> set DELETE operation */
LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_DELETE));
- /* all descendants will be deleted even without being in the diff, so remove them */
+ /* all descendants not in the diff will be deleted and redundant in the diff, so remove them */
LY_LIST_FOR_SAFE(LYD_CHILD(diff_match), next, child) {
- lyd_free_tree(child);
+ if (lyd_find_sibling_first(lyd_node_children(src_diff, 0), child, NULL) == LY_ENOTFOUND) {
+ lyd_free_tree(child);
+ }
}
break;
default: