yaml: keep original value when anchor and target node both defines the same key

When merging an anchor into a target yaml node, and both the target
node and the anchor defines the same key(s), keep the value from the
target node.

Closes #286
This commit is contained in:
Daniel Eklöf 2023-04-09 09:27:31 +02:00
parent 5e3859f218
commit 971361b046
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
2 changed files with 19 additions and 10 deletions

View file

@ -50,12 +50,15 @@
* i3/sway: regression; persistent workspaces shown twice * i3/sway: regression; persistent workspaces shown twice
([#253][253]). ([#253][253]).
* pipewire: use roundf instead of ceilf for more accuracy ([#262][262]) * pipewire: use roundf instead of ceilf for more accuracy ([#262][262])
* Crash when a yaml anchor has a value to already exists in the target
yaml node ([#286][286]).
[239]: https://codeberg.org/dnkl/yambar/issues/239 [239]: https://codeberg.org/dnkl/yambar/issues/239
[241]: https://codeberg.org/dnkl/yambar/issues/241 [241]: https://codeberg.org/dnkl/yambar/issues/241
[251]: https://codeberg.org/dnkl/yambar/pulls/251 [251]: https://codeberg.org/dnkl/yambar/pulls/251
[253]: https://codeberg.org/dnkl/yambar/issues/253 [253]: https://codeberg.org/dnkl/yambar/issues/253
[262]: https://codeberg.org/dnkl/yambar/issues/262 [262]: https://codeberg.org/dnkl/yambar/issues/262
[286]: https://codeberg.org/dnkl/yambar/issues/286
### Security ### Security

22
yml.c
View file

@ -237,13 +237,16 @@ post_process(struct yml_node *node, char **error)
.key = vv_it->item.key, .key = vv_it->item.key,
.value = vv_it->item.value, .value = vv_it->item.value,
}; };
/* TODO: handle this. Is it an error? Or
* should we replace the existing key/value
* pair */
assert(!dict_has_key(node, vv_it->item.key));
if (dict_has_key(node, vv_it->item.key)) {
/* Prefer value in target dictionary, over the
* value from the anchor */
yml_destroy(vv_it->item.key);
yml_destroy(vv_it->item.value);
} else {
tll_push_back(node->dict.pairs, p); tll_push_back(node->dict.pairs, p);
} }
}
/* Destroy list, but don't free (since its nodes /* Destroy list, but don't free (since its nodes
* have been moved to this node), *before* * have been moved to this node), *before*
@ -274,12 +277,15 @@ post_process(struct yml_node *node, char **error)
.value = v_it->item.value, .value = v_it->item.value,
}; };
/* TODO: handle this. Is it an error? Or should we if (dict_has_key(node, v_it->item.key)) {
* replace the existing key/value pair */ /* Prefer value in target dictionary, over the
assert(!dict_has_key(node, v_it->item.key)); * value from the anchor */
yml_destroy(v_it->item.key);
yml_destroy(v_it->item.value);
} else {
tll_push_back(node->dict.pairs, p); tll_push_back(node->dict.pairs, p);
} }
}
/* Destroy list here, *without* freeing nodes (since /* Destroy list here, *without* freeing nodes (since
* nodes have been moved to this node), *before* * nodes have been moved to this node), *before*