diff BUGFIX nested userord created nodes metadata
Fixes sysrepo/sysrepo#2837
diff --git a/src/diff.c b/src/diff.c
index 34ee404..ddbacc8 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -105,12 +105,67 @@
return 0;
}
+/**
+ * @brief Create diff metadata for a nested user-ordered node with the effective operation "create".
+ *
+ * @param[in] node User-rodered node to update.
+ * @return LY_ERR value.
+ */
+static LY_ERR
+lyd_diff_add_create_nested_userord(struct lyd_node *node)
+{
+ LY_ERR rc = LY_SUCCESS;
+ const char *meta_name, *meta_val;
+ size_t buflen = 0, bufused = 0;
+ uint32_t pos;
+ char *dyn = NULL;
+
+ assert(lysc_is_userordered(node->schema));
+
+ /* get correct metadata name and value */
+ if (lysc_is_dup_inst_list(node->schema)) {
+ meta_name = "yang:position";
+
+ pos = lyd_list_pos(node);
+ if (asprintf(&dyn, "%" PRIu32, pos) == -1) {
+ LOGMEM(LYD_CTX(node));
+ rc = LY_EMEM;
+ goto cleanup;
+ }
+ meta_val = dyn;
+ } else if (node->schema->nodetype == LYS_LIST) {
+ meta_name = "yang:key";
+
+ if (node->prev->next && (node->prev->schema == node->schema)) {
+ LY_CHECK_GOTO(rc = lyd_path_list_predicate(node->prev, &dyn, &buflen, &bufused, 0), cleanup);
+ meta_val = dyn;
+ } else {
+ meta_val = "";
+ }
+ } else {
+ meta_name = "yang:value";
+
+ if (node->prev->next && (node->prev->schema == node->schema)) {
+ meta_val = lyd_get_value(node->prev);
+ } else {
+ meta_val = "";
+ }
+ }
+
+ /* create the metadata */
+ LY_CHECK_GOTO(rc = lyd_new_meta(NULL, node, NULL, meta_name, meta_val, 0, NULL), cleanup);
+
+cleanup:
+ free(dyn);
+ return rc;
+}
+
LY_ERR
lyd_diff_add(const struct lyd_node *node, enum lyd_diff_op op, const char *orig_default, const char *orig_value,
const char *key, const char *value, const char *position, const char *orig_key, const char *orig_position,
struct lyd_node **diff)
{
- struct lyd_node *dup, *siblings, *match = NULL, *diff_parent = NULL;
+ struct lyd_node *dup, *siblings, *match = NULL, *diff_parent = NULL, *elem;
const struct lyd_node *parent = NULL;
const struct lys_module *yang_mod;
@@ -194,6 +249,16 @@
/* add subtree operation */
LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "operation", lyd_diff_op2str(op), 0, NULL));
+ if (op == LYD_DIFF_OP_CREATE) {
+ /* all nested user-ordered (leaf-)lists need special metadata for create op */
+ LYD_TREE_DFS_BEGIN(dup, elem) {
+ if ((elem != dup) && lysc_is_userordered(elem->schema)) {
+ LY_CHECK_RET(lyd_diff_add_create_nested_userord(elem));
+ }
+ LYD_TREE_DFS_END(dup, elem);
+ }
+ }
+
/* orig-default */
if (orig_default) {
LY_CHECK_RET(lyd_new_meta(LYD_CTX(node), dup, yang_mod, "orig-default", orig_default, 0, NULL));