[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[augeas-devel] [PATCH] New API call aug_defnode and augtool command defnode



It's common that we want to define a variable to reference /foo/bar, and
create that node if it does not exist yet. aug_defnode bundles that
together into one convenient.
---
 src/augeas.c           |   23 +++++++++++++++++++++--
 src/augeas.h           |   15 +++++++++++++++
 src/augeas_sym.version |    1 +
 src/augtool.c          |   17 +++++++++++++++++
 src/internal.h         |    3 ++-
 tests/test-xpath.c     |   28 ++++++++++++++++++++++++++++
 6 files changed, 84 insertions(+), 3 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 8006883..83517d1 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -365,22 +365,41 @@ int aug_get(const struct augeas *aug, const char *path, const char **value) {
     return r;
 }
 
-int aug_defvar(augeas *aug, const char *name, const char *expr) {
+static int symtab_define(struct augeas *aug, const char *name,
+                         const char *expr, bool expand_tree) {
     struct pathx *p;
     int r;
 
     if (expr == NULL) {
         r = pathx_symtab_undefine(&(aug->symtab), name);
     } else {
+        struct tree *dummy;
+
         p = parse_user_pathx((struct augeas *) aug, false, expr);
         if (p == NULL)
-            return -1;
+            goto done;
+        if (expand_tree) {
+            r = pathx_expand_tree(p, &dummy);
+            if (r < 0)
+                goto done;
+        }
         r = pathx_symtab_define(&(aug->symtab), name, p);
     }
+ done:
     free_pathx(p);
     return (r < 0) ? -1 : 0;
 }
 
+int aug_defvar(augeas *aug, const char *name, const char *expr) {
+    return symtab_define(aug, name, expr, false);
+}
+
+int aug_defnode(augeas *aug, const char *name, const char *expr) {
+    if (expr == NULL)
+        return -1;
+    return symtab_define(aug, name, expr, true);
+}
+
 struct tree *tree_set(struct pathx *p, const char *value) {
     struct tree *tree;
     int r;
diff --git a/src/augeas.h b/src/augeas.h
index be1ad65..67c0e27 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -83,6 +83,21 @@ augeas *aug_init(const char *root, const char *loadpath, unsigned int flags);
  */
 int aug_defvar(augeas *aug, const char *name, const char *expr);
 
+/* Function: aug_defnode
+ *
+ * Define a variable NAME whose value is the result of evaluating EXPR,
+ * which must be non-NULL and evaluate to a nodeset. If a variable NAME
+ * already exists, its name will be replaced with the result of evaluating
+ * EXPR.
+ *
+ * If EXPR evaluates to an empty nodeset, a node is created, equivalent to
+ * calling AUG_SET(AUG, EXPR, NULL) and NAME will be the nodeset containing
+ * that single node.
+ *
+ * Returns 0 on success, -1 on error
+ */
+int aug_defnode(augeas *aug, const char *name, const char *expr);
+
 /* Function: aug_get
  *
  * Lookup the value associated with PATH. VALUE can be NULL, in which case
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index f0c887e..0fdc03d 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -2,6 +2,7 @@
     global:
       aug_init;
       aug_defvar;
+      aug_defnode;
       aug_close;
       aug_get;
       aug_set;
diff --git a/src/augtool.c b/src/augtool.c
index 9b1d772..9d7365b 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -205,6 +205,17 @@ static int cmd_defvar(char *args[]) {
     return r;
 }
 
+static int cmd_defnode(char *args[]) {
+    const char *name = args[0];
+    const char *path = cleanpath(args[1]);
+    int r;
+
+    r = aug_defnode(aug, name, path);
+    if (r == -1)
+        printf ("Failed\n");
+    return r;
+}
+
 static int cmd_clear(char *args[]) {
     const char *path = cleanpath(args[0]);
     int r;
@@ -408,6 +419,12 @@ static const struct command const commands[] = {
       "        variable can be used in path expressions as $NAME. Note that EXPR\n"
       "        is evaluated when the variable is defined, not when it is used."
     },
+    { "defnode", 2, 2, cmd_defnode, "defnode <NAME> <EXPR>",
+      "Define the variable NAME to the result of evalutating EXPR, which\n"
+      "        must be a nodeset. If no node matching EXPR exists yet, one\n"
+      "        is created in the same way 'clear EXPR' would and NAME refers\n"
+      "        to that node."
+    },
     { "help", 0, 0, cmd_help, "help",
       "Print this help text"
     },
diff --git a/src/internal.h b/src/internal.h
index 76d9c6d..060c95f 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -385,7 +385,8 @@ typedef enum {
     PATHX_EINTERNAL,
     PATHX_ETYPE,
     PATHX_ENOVAR,
-    PATHX_EEND
+    PATHX_EEND,
+    PATHX_ENONODES
 } pathx_errcode_t;
 
 struct pathx;
diff --git a/tests/test-xpath.c b/tests/test-xpath.c
index 9cfb8ab..710b875 100644
--- a/tests/test-xpath.c
+++ b/tests/test-xpath.c
@@ -244,6 +244,31 @@ static int test_defvar_nonexistent(struct augeas *aug) {
     return -1;
 }
 
+static int test_defnode_nonexistent(struct augeas *aug) {
+    int r;
+
+    printf("%-30s ... ", "defnode_nonexistent");
+    r = aug_defnode(aug, "x", "/defnode/bar");
+    if (r < 0)
+        die("aug_defnode failed");
+
+    r = aug_set(aug, "$x", "baz");
+    printf("\nset %d\n", r);
+    if (r != 0)
+        goto fail;
+
+    r = aug_match(aug, "$x", NULL);
+    printf("match %d\n", r);
+    if (r != 1)
+        goto fail;
+
+    printf("PASS\n");
+    return 0;
+ fail:
+    printf("FAIL\n");
+    return -1;
+}
+
 static int run_tests(struct test *tests) {
     char *lensdir;
     struct augeas *aug = NULL;
@@ -273,6 +298,9 @@ static int run_tests(struct test *tests) {
     if (test_defvar_nonexistent(aug) < 0)
         result = EXIT_FAILURE;
 
+    if (test_defnode_nonexistent(aug) < 0)
+        result = EXIT_FAILURE;
+
     aug_close(aug);
 
     return result;
-- 
1.6.0.6



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]