summaryrefslogtreecommitdiff
path: root/src/config_diff.ml
diff options
context:
space:
mode:
authorJohn Estabrook <jestabro@vyos.io>2026-04-10 22:02:50 -0500
committerJohn Estabrook <jestabro@vyos.io>2026-04-16 07:59:50 -0500
commitf6e50f41de5dde75a27426d3d164a8f69f62d34d (patch)
treeba85646294bce5a9507d8ec08f4d562defff341d /src/config_diff.ml
parentb5d79efaa9f1463c6babab48f43667e39dd1bca4 (diff)
downloadvyos1x-config-f6e50f41de5dde75a27426d3d164a8f69f62d34d.tar.gz
vyos1x-config-f6e50f41de5dde75a27426d3d164a8f69f62d34d.zip
T8488: add utility subtree_from_partial
Return the subtree of a configtree indicated by a path that may only be partly defined, lacking some or all intervening tag node value.
Diffstat (limited to 'src/config_diff.ml')
-rw-r--r--src/config_diff.ml70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/config_diff.ml b/src/config_diff.ml
index 88756b6..c00705d 100644
--- a/src/config_diff.ml
+++ b/src/config_diff.ml
@@ -769,6 +769,76 @@ let mask_tree ?(exclusive=false) left right =
let res = eval_diff_result d in
res.left
+(* Convert from a path that may or may not include intervening tag_values,
+ returning a subtree of matches *)
+exception Malformed_path of string
+
+let subtree_from_partial reftree ctree result path =
+ if Util.is_empty path then result
+ else
+ let check_reftree p =
+ match p with
+ | [] -> false
+ | _ ->
+ let rpath =
+ Reference_tree.refpath_from_partial reftree p
+ in
+ match rpath with
+ | [] -> false
+ | _ -> true
+ in
+ let check_ctree p =
+ match p with
+ | [] -> false
+ | _ -> (Vytree.exists[@alert "-exn"]) ctree p
+ in
+ let clone_node tree p =
+ if (Vytree.exists[@alert "-exn"]) tree p then
+ tree
+ else
+ if not ((Vytree.exists[@alert "-exn"]) ctree p) then
+ tree
+ else
+ clone ~recurse:false ctree tree p
+ in
+ let clone_children tree p =
+ let children = Vytree.list_children ((Vytree.get[@alert "-exn"]) ctree p) in
+ let paths = List.map (fun n -> p @ [n]) children in
+ List.fold_left clone_node tree paths
+ in
+ let rec aux acc path_done p =
+ if not (check_reftree (path_done @ p)) then
+ raise (Malformed_path (Util.string_of_list (path_done @ p)))
+ else
+ match path_done, p with
+ | [], h :: tl ->
+ if check_reftree [h] then aux (clone_node acc [h]) [h] tl
+ else
+ raise (Malformed_path (Util.string_of_list p))
+ | _, h :: tl ->
+ let p' = path_done @ [h] in
+ if check_ctree p' then aux (clone_node acc p') p' tl
+ else
+ if (Config_tree.is_tag[@alert "-exn"]) ctree path_done then
+ let children =
+ Vytree.list_children ((Vytree.get[@alert "-exn"]) ctree path_done)
+ in
+ let func accum child =
+ let path = path_done @ [child] @ [h] in
+ if check_ctree path then
+ aux (clone_node accum path) path tl
+ else accum
+ in
+ List.fold_left func acc children
+ else
+ (* [h] is a tag_value not present in the config tree *)
+ raise (Malformed_path (Util.string_of_list p'))
+ | _, [] ->
+ if (Config_tree.is_tag[@alert "-exn"]) ctree path_done then clone_children acc path_done
+ else acc
+ in aux result [] path
+
+
let union_of_values (n : Config_tree.t) (m : Config_tree.t) =
let set_n = ValueS.of_list (data_of n).values in
let set_m = ValueS.of_list (data_of m).values in