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

David Lutterkort lutter at fedoraproject.org
Tue Mar 24 23:08:00 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=f7c35b0333ad3401395e9cd6254d059c4ec1dffe
Commit:        f7c35b0333ad3401395e9cd6254d059c4ec1dffe
Parent:        a6461b12d63144fe42d6108d2d8b802fdebbd472
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Mon Mar 23 18:42:37 2009 -0700
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Tue Mar 24 16:04:24 2009 -0700

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 call.
---
 src/augeas.c           |   34 ++++++++++++++++++++++++++++++++++
 src/augeas.h           |   20 ++++++++++++++++++++
 src/augeas_sym.version |    1 +
 src/augtool.c          |   24 ++++++++++++++++++++++++
 src/internal.h         |    3 ++-
 tests/test-xpath.c     |   44 ++++++++++++++++++++++++++++++++++++++++++--
 6 files changed, 123 insertions(+), 3 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 348184c..f239bfa 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -382,6 +382,40 @@ int aug_defvar(augeas *aug, const char *name, const char *expr) {
     return result;
 }
 
+int aug_defnode(augeas *aug, const char *name, const char *expr,
+                const char *value, int *created) {
+    struct pathx *p;
+    int result = -1;
+    int r, cr;
+    struct tree *tree;
+
+    if (expr == NULL)
+        return -1;
+    if (created == NULL)
+        created = &cr;
+
+    p = parse_user_pathx((struct augeas *) aug, false, expr);
+    if (p == NULL)
+        goto done;
+
+    r = pathx_expand_tree(p, &tree);
+    if (r < 0)
+        goto done;
+
+    *created = r > 0;
+    if (*created) {
+        r = tree_set_value(tree, value);
+        if (r < 0)
+            goto done;
+    }
+
+    result = pathx_symtab_define(&(aug->symtab), name, p);
+
+ done:
+    free_pathx(p);
+    return result;
+}
+
 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 6b75a22..5a146f1 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -85,6 +85,26 @@ 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, VALUE) and NAME will be the nodeset containing
+ * that single node.
+ *
+ * If CREATED is non-NULL, it is set to 1 if a node was created, and 0 if
+ * it already existed.
+ *
+ * Returns -1 on error; on success, returns the number of nodes in the
+ * nodeset
+ */
+int aug_defnode(augeas *aug, const char *name, const char *expr,
+                const char *value, int *created);
+
 /* 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..c4e90af 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -205,6 +205,22 @@ 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]);
+    const char *value = args[2];
+    int r;
+
+    /* Our simple minded line parser treats non-existant and empty values
+     * the same. We choose to take the empty string to mean NULL */
+    if (value != NULL && strlen(value) == 0)
+        value = NULL;
+    r = aug_defnode(aug, name, path, value, NULL);
+    if (r == -1)
+        printf ("Failed\n");
+    return r;
+}
+
 static int cmd_clear(char *args[]) {
     const char *path = cleanpath(args[0]);
     int r;
@@ -408,6 +424,14 @@ 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, 3, cmd_defnode, "defnode <NAME> <EXPR> [<VALUE>]",
+      "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 and NAME will refer to it. If VALUE is given, this\n"
+      "        is the same as 'set EXPR VALUE'; if VALUE is not given, the\n"
+      "        node is created as if with '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..9a77e98 100644
--- a/tests/test-xpath.c
+++ b/tests/test-xpath.c
@@ -244,6 +244,43 @@ static int test_defvar_nonexistent(struct augeas *aug) {
     return -1;
 }
 
+static int test_defnode_nonexistent(struct augeas *aug) {
+    int r, created;
+
+    printf("%-30s ... ", "defnode_nonexistent");
+    r = aug_defnode(aug, "x", "/defnode/bar[. = 'foo']", "foo", &created);
+    if (r != 1)
+        die("aug_defnode failed");
+    if (created != 1) {
+        fprintf(stderr, "defnode did not create a node\n");
+        goto fail;
+    }
+
+    r = aug_defnode(aug, "x", "/defnode/bar", NULL, &created);
+    if (r != 1)
+        die("aug_defnode failed");
+    if (created != 0) {
+        fprintf(stderr, "defnode created node again\n");
+        goto fail;
+    }
+
+    // FIXME: get values and compare them, too
+
+    r = aug_set(aug, "$x", "baz");
+    if (r != 0)
+        goto fail;
+
+    r = aug_match(aug, "$x", NULL);
+    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;
@@ -256,10 +293,10 @@ static int run_tests(struct test *tests) {
     if (aug == NULL)
         die("aug_init");
     r = aug_defvar(aug, "hosts", "/files/etc/hosts/*");
-    if (r < 0)
+    if (r != 6)
         die("aug_defvar $hosts");
     r = aug_defvar(aug, "localhost", "'127.0.0.1'");
-    if (r < 0)
+    if (r != 0)
         die("aug_defvar $localhost");
 
     list_for_each(t, tests) {
@@ -273,6 +310,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;




More information about the augeas-devel mailing list