diff BUGFIX delete merge lost changes

Fixes sysrepo/sysrepo#2624
diff --git a/src/diff.c b/src/diff.c
index 6680338..cd442fd 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -1438,7 +1438,7 @@
 static LY_ERR
 lyd_diff_merge_delete(struct lyd_node *diff_match, enum lyd_diff_op cur_op, const struct lyd_node *src_diff)
 {
-    struct lyd_node *next, *child;
+    struct lyd_node *child;
     struct lyd_meta *meta;
     const char *meta_name;
 
@@ -1462,7 +1462,7 @@
         } /* else key-less list, for which all the descendants act as keys */
         break;
     case LYD_DIFF_OP_REPLACE:
-        /* similar to none operation but also remove the redundant metadata */
+        /* remove the redundant metadata */
         if (lysc_is_userordered(diff_match->schema)) {
             if (lysc_is_dup_inst_list(diff_match->schema)) {
                 meta_name = "position";
@@ -1494,17 +1494,12 @@
         }
         lyd_diff_del_meta(diff_match, meta_name);
 
-    /* fall through */
+        /* it was being changed, but should be deleted instead -> set DELETE operation */
+        LY_CHECK_RET(lyd_diff_change_op(diff_match, LYD_DIFF_OP_DELETE));
+        break;
     case LYD_DIFF_OP_NONE:
         /* 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 not in the diff will be deleted and redundant in the diff, so remove them */
-        LY_LIST_FOR_SAFE(lyd_child_no_keys(diff_match), next, child) {
-            if (lyd_find_sibling_first(lyd_child(src_diff), child, NULL) == LY_ENOTFOUND) {
-                lyd_free_tree(child);
-            }
-        }
         break;
     default:
         /* delete operation is not valid */
diff --git a/tests/utests/data/test_diff.c b/tests/utests/data/test_diff.c
index 7fee736..50954d7 100644
--- a/tests/utests/data/test_diff.c
+++ b/tests/utests/data/test_diff.c
@@ -60,7 +60,7 @@
                     lyd_free_all(diff2);\
                 }
 
-const char *schema =
+const char *schema1 =
         "module defaults {\n"
         "    yang-version 1.1;\n"
         "    namespace \"urn:libyang:tests:defaults\";\n"
@@ -137,8 +137,17 @@
         "                type int32;\n"
         "                default \"42\";\n"
         "            }\n"
-        "        }\n"
-        ""
+        "            list list2 {\n"
+        "                key \"name2\";\n"
+        "                leaf name2 {\n"
+        "                    type string;\n"
+        "                }\n"
+        "                leaf value2 {\n"
+        "                    type int32;\n"
+        "                }\n"
+        "            }\n"
+        "        }\n";
+const char *schema2 =
         "        choice select {\n"
         "            default \"a\";\n"
         "            case a {\n"
@@ -276,8 +285,17 @@
 static int
 setup(void **state)
 {
+    char *schema;
+
     UTEST_SETUP;
+
+    /* create one schema, longer than 4095 chars */
+    schema = malloc(strlen(schema1) + strlen(schema2) + 1);
+    strcpy(schema, schema1);
+    strcat(schema, schema2);
+
     UTEST_ADD_MODULE(schema, LYS_IN_YANG, NULL, NULL);
+    free(schema);
 
     return 0;
 }
@@ -450,6 +468,46 @@
 }
 
 static void
+test_delete_merge(void **state)
+{
+    (void) state;
+    struct lyd_node *diff1, *diff2;
+    const char *xml1 =
+            "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+            "  <list>\n"
+            "    <name>a</name>\n"
+            "    <list2 yang:operation=\"delete\">\n"
+            "      <name2>a</name2>\n"
+            "    </list2>\n"
+            "  </list>\n"
+            "</df>\n";
+    const char *xml2 =
+            "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+            "  <list yang:operation=\"delete\">\n"
+            "    <name>a</name>\n"
+            "  </list>\n"
+            "</df>\n";
+    const char *xml_merge =
+            "<df xmlns=\"urn:libyang:tests:defaults\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
+            "  <list yang:operation=\"delete\">\n"
+            "    <name>a</name>\n"
+            "    <list2 yang:operation=\"delete\">\n"
+            "      <name2>a</name2>\n"
+            "    </list2>\n"
+            "  </list>\n"
+            "</df>\n";
+
+    CHECK_PARSE_LYD(xml1, diff1);
+    CHECK_PARSE_LYD(xml2, diff2);
+
+    assert_int_equal(lyd_diff_merge_all(&diff1, diff2, 0), LY_SUCCESS);
+    CHECK_LYD_STRING(diff1, xml_merge);
+
+    lyd_free_all(diff1);
+    lyd_free_all(diff2);
+}
+
+static void
 test_leaf(void **state)
 {
     (void) state;
@@ -1068,6 +1126,7 @@
         UTEST(test_empty1, setup),
         UTEST(test_empty2, setup),
         UTEST(test_empty_nested, setup),
+        UTEST(test_delete_merge, setup),
         UTEST(test_leaf, setup),
         UTEST(test_list, setup),
         UTEST(test_userord_llist, setup),