[augeas-devel] augeas: master - defnode: when creating new node, put it in the nodeset

David Lutterkort lutter at fedoraproject.org
Fri Aug 7 00:21:49 UTC 2009


Gitweb:        http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=a7ee31686ec24ef53eb85722c016a8c8902875be
Commit:        a7ee31686ec24ef53eb85722c016a8c8902875be
Parent:        9cc90c45e35fb85b9c1a6af528b93371ebbd7426
Author:        David Lutterkort <lutter at redhat.com>
AuthorDate:    Thu Aug 6 17:09:26 2009 -0700
Committer:     David Lutterkort <lutter at redhat.com>
CommitterDate: Thu Aug 6 17:09:26 2009 -0700

defnode: when creating new node, put it in the nodeset

When a new node is created, e.g. with 'defnode x "/foo[0 = 1]"' we used to
assign an empty nodeset to x. Now x will hold a reference to the newly
created node, even though the initial path expression would never match any
nodes.

  * src/augeas.c (aug_defnode): call pathx_symtab_assign_tree after
    creating a node
  * src/pathx.c (pathx_symtab_assign_tree): new function to assign a single
    tree node to a variable
  * src/internal.h: declare pathx_symtab_assign_tree
  * tests/test-xpath.c (test_defnode_nonexistent): test new behavior
---
 src/augeas.c       |    5 ++-
 src/internal.h     |    2 +
 src/pathx.c        |   71 +++++++++++++++++++++++++++++++++++++++++----------
 tests/test-xpath.c |    7 ++++-
 4 files changed, 68 insertions(+), 17 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 62339c5..b440803 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -410,10 +410,11 @@ int aug_defnode(augeas *aug, const char *name, const char *expr,
         r = tree_set_value(tree, value);
         if (r < 0)
             goto done;
+        result = pathx_symtab_assign_tree(&(aug->symtab), name, tree);
+    } else {
+        result = pathx_symtab_define(&(aug->symtab), name, p);
     }
 
-    result = pathx_symtab_define(&(aug->symtab), name, p);
-
  done:
     free_pathx(p);
     return result;
diff --git a/src/internal.h b/src/internal.h
index cc636ef..7f266b5 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -414,6 +414,8 @@ void free_pathx(struct pathx *path);
 int pathx_symtab_init(struct pathx_symtab **symtab);
 int pathx_symtab_define(struct pathx_symtab **symtab,
                         const char *name, struct pathx *px);
+int pathx_symtab_assign_tree(struct pathx_symtab **symtab, const char *name,
+                             struct tree *tree);
 int pathx_symtab_undefine(struct pathx_symtab **symtab, const char *name);
 void pathx_symtab_remove_descendants(struct pathx *pathx,
                                      const struct tree *tree);
diff --git a/src/pathx.c b/src/pathx.c
index d44aeb7..32d4aad 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -2248,9 +2248,36 @@ int pathx_symtab_init(struct pathx_symtab **symtab) {
     return -1;
 }
 
+static int pathx_symtab_set(struct pathx_symtab **symtab,
+                            const char *name, struct value *v) {
+    int found = 0;
+
+    list_for_each(tab, *symtab) {
+        if (STREQ(tab->name, name)) {
+            release_value(tab->value);
+            free(tab->value);
+            tab->value = v;
+            found = 1;
+            break;
+        }
+    }
+
+    if (!found) {
+        struct pathx_symtab *new = NULL;
+
+        new = make_symtab(*symtab, name, v);
+        if (new == NULL)
+            goto error;
+        *symtab = new;
+    }
+    return 0;
+ error:
+    return -1;
+}
+
 int pathx_symtab_define(struct pathx_symtab **symtab,
                         const char *name, struct pathx *px) {
-    struct pathx_symtab *new;
+    int r;
     struct value *value = NULL, *v = NULL;
 
     value = pathx_eval(px);
@@ -2262,21 +2289,10 @@ int pathx_symtab_define(struct pathx_symtab **symtab,
     *v = *value;
     value->tag = T_BOOLEAN;
 
-    list_for_each(tab, *symtab) {
-        if (STREQ(tab->name, name)) {
-            release_value(tab->value);
-            free(tab->value);
-            tab->value = v;
-            goto done;
-        }
-    }
-
-    new = make_symtab(*symtab, name, v);
-    if (new == NULL)
+    r = pathx_symtab_set(symtab, name, v);
+    if (r < 0)
         goto error;
 
-    *symtab = new;
- done:
     if (v->tag == T_NODESET)
         return v->nodeset->used;
     else
@@ -2302,6 +2318,33 @@ int pathx_symtab_undefine(struct pathx_symtab **symtab, const char *name) {
     return 0;
 }
 
+int pathx_symtab_assign_tree(struct pathx_symtab **symtab,
+                             const char *name, struct tree *tree) {
+    struct value *v = NULL;
+    int r;
+
+    if (ALLOC(v) < 0)
+        goto error;
+
+    v->tag = T_NODESET;
+    if (ALLOC(v->nodeset) < 0)
+        goto error;
+    if (ALLOC_N(v->nodeset->nodes, 1) < 0)
+        goto error;
+    v->nodeset->used = 1;
+    v->nodeset->size = 1;
+    v->nodeset->nodes[0] = tree;
+
+    r = pathx_symtab_set(symtab, name, v);
+    if (r < 0)
+        goto error;
+    return 1;
+ error:
+    release_value(v);
+    free(v);
+    return -1;
+}
+
 void pathx_symtab_remove_descendants(struct pathx *pathx,
                                      const struct tree *tree) {
     struct pathx_symtab *symtab = pathx->state->symtab;
diff --git a/tests/test-xpath.c b/tests/test-xpath.c
index 9a77e98..831e529 100644
--- a/tests/test-xpath.c
+++ b/tests/test-xpath.c
@@ -248,13 +248,18 @@ 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);
+    r = aug_defnode(aug, "x", "/defnode/bar[0 = 1]", "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_match(aug, "$x", NULL);
+    if (r != 1) {
+        fprintf(stderr, "$x must have exactly one entry, but has %d\n", r);
+        goto fail;
+    }
 
     r = aug_defnode(aug, "x", "/defnode/bar", NULL, &created);
     if (r != 1)




More information about the augeas-devel mailing list