[augeas-devel] [PATCH] Fix behavior of aug_defnode

lutter at redhat.com lutter at redhat.com
Fri Aug 6 22:03:21 UTC 2010


From: David Lutterkort <lutter at redhat.com>

  (1) Make sure that the definition of the variable is recorded under
      /augeas/variables
  (2) Do not report an error if the expression evaluates to a non-empty
      nodeset

  * src/augeas.c (aug_defvar): split creating metadata under
    /augeas/variables into record_var_meta; (aug_defnode): do not return an
    error when expr evaluates to nonempty node set; record variable
    definition
  * tests/test-api.c: add tests for defvar and defnode behavior
---
 src/augeas.c     |   51 ++++++++++++++++++--------
 tests/test-api.c |  103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+), 16 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index d10966d..d2ef353 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -597,6 +597,24 @@ int aug_get(const struct augeas *aug, const char *path, const char **value) {
     return -1;
 }
 
+static void record_var_meta(struct augeas *aug, const char *name,
+                            const char *expr) {
+    /* Record the definition of the variable */
+    struct tree *tree = tree_path_cr(aug->origin, 2, s_augeas, s_vars);
+    ERR_NOMEM(tree == NULL, aug);
+    if (expr == NULL) {
+        tree = tree_child(tree, name);
+        if (tree != NULL)
+            tree_unlink(tree);
+    } else {
+        tree = tree_child_cr(tree, name);
+        ERR_NOMEM(tree == NULL, aug);
+        tree_set_value(tree, expr);
+    }
+ error:
+    return;
+}
+
 int aug_defvar(augeas *aug, const char *name, const char *expr) {
     struct pathx *p = NULL;
     int result = -1;
@@ -612,18 +630,8 @@ int aug_defvar(augeas *aug, const char *name, const char *expr) {
     }
     ERR_BAIL(aug);
 
-    /* Record the definition of the variable */
-    struct tree *tree = tree_path_cr(aug->origin, 2, s_augeas, s_vars);
-    ERR_NOMEM(tree == NULL, aug);
-    if (expr == NULL) {
-        tree = tree_child(tree, name);
-        if (tree != NULL)
-            tree_unlink(tree);
-    } else {
-        tree = tree_child_cr(tree, name);
-        ERR_NOMEM(tree == NULL, aug);
-        tree_set_value(tree, expr);
-    }
+    record_var_meta(aug, name, expr);
+    ERR_BAIL(aug);
  error:
     free_pathx(p);
     api_exit(aug);
@@ -647,18 +655,29 @@ int aug_defnode(augeas *aug, const char *name, const char *expr,
     p = pathx_aug_parse(aug, aug->origin, expr, false);
     ERR_BAIL(aug);
 
-    r = pathx_expand_tree(p, &tree);
-    if (r < 0)
-        goto done;
+    if (pathx_first(p) == NULL) {
+        r = pathx_expand_tree(p, &tree);
+        if (r < 0)
+            goto done;
+        *created = 1;
+    } else {
+        *created = 0;
+    }
 
-    *created = r > 0;
     if (*created) {
         r = tree_set_value(tree, value);
         if (r < 0)
             goto done;
         result = pathx_symtab_assign_tree(&(aug->symtab), name, tree);
+        char *e = path_of_tree(tree);
+        ERR_NOMEM(e == NULL, aug)
+        record_var_meta(aug, name, e);
+        free(e);
+        ERR_BAIL(aug);
     } else {
         result = pathx_symtab_define(&(aug->symtab), name, p);
+        record_var_meta(aug, name, expr);
+        ERR_BAIL(aug);
     }
 
  done:
diff --git a/tests/test-api.c b/tests/test-api.c
index eba109c..322f4a9 100644
--- a/tests/test-api.c
+++ b/tests/test-api.c
@@ -120,6 +120,106 @@ static void testSetM(CuTest *tc) {
 
     r = aug_setm(aug, "/augeas/version/save/*", "mode[]", "invalid");
     CuAssertIntEquals(tc, -1, r);
+
+    aug_close(aug);
+}
+
+/* Check that defining a variable leads to a corresponding entry in
+ * /augeas/variables and that that entry disappears when the variable is
+ * undefined */
+static void testDefVarMeta(CuTest *tc) {
+    int r;
+    struct augeas *aug;
+    static const char *const expr = "/augeas/version/save/mode";
+    const char *value;
+
+    aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
+    CuAssertPtrNotNull(tc, aug);
+    CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
+
+    r = aug_defvar(aug, "var", expr);
+    CuAssertIntEquals(tc, 4, r);
+
+    r = aug_match(aug, "/augeas/variables/*", NULL);
+    CuAssertIntEquals(tc, 1, r);
+
+    r = aug_get(aug, "/augeas/variables/var", &value);
+    CuAssertStrEquals(tc, expr, value);
+
+    r = aug_defvar(aug, "var", NULL);
+    CuAssertIntEquals(tc, 0, r);
+
+    r = aug_match(aug, "/augeas/variables/*", NULL);
+    CuAssertIntEquals(tc, 0, r);
+
+    aug_close(aug);
+}
+
+/* Check that defining a variable with defnode leads to a corresponding
+ * entry in /augeas/variables and that that entry disappears when the
+ * variable is undefined
+ */
+static void testDefNodeExistingMeta(CuTest *tc) {
+    int r, created;
+    struct augeas *aug;
+    static const char *const expr = "/augeas/version/save/mode";
+    const char *value;
+
+    aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
+    CuAssertPtrNotNull(tc, aug);
+    CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
+
+    r = aug_defnode(aug, "var", expr, "other", &created);
+    CuAssertIntEquals(tc, 4, r);
+    CuAssertIntEquals(tc, 0, created);
+
+    r = aug_match(aug, "/augeas/variables/*", NULL);
+    CuAssertIntEquals(tc, 1, r);
+
+    r = aug_get(aug, "/augeas/variables/var", &value);
+    CuAssertStrEquals(tc, expr, value);
+
+    r = aug_defvar(aug, "var", NULL);
+    CuAssertIntEquals(tc, 0, r);
+
+    r = aug_match(aug, "/augeas/variables/*", NULL);
+    CuAssertIntEquals(tc, 0, r);
+
+    aug_close(aug);
+}
+
+/* Check that defining a variable with defnode leads to a corresponding
+ * entry in /augeas/variables and that that entry disappears when the
+ * variable is undefined
+ */
+static void testDefNodeCreateMeta(CuTest *tc) {
+    int r, created;
+    struct augeas *aug;
+    static const char *const expr = "/augeas/version/save/mode[last()+1]";
+    static const char *const expr_can = "/augeas/version/save/mode[5]";
+    const char *value;
+
+    aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
+    CuAssertPtrNotNull(tc, aug);
+    CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
+
+    r = aug_defnode(aug, "var", expr, "other", &created);
+    CuAssertIntEquals(tc, 1, r);
+    CuAssertIntEquals(tc, 1, created);
+
+    r = aug_match(aug, "/augeas/variables/*", NULL);
+    CuAssertIntEquals(tc, 1, r);
+
+    r = aug_get(aug, "/augeas/variables/var", &value);
+    CuAssertStrEquals(tc, expr_can, value);
+
+    r = aug_defvar(aug, "var", NULL);
+    CuAssertIntEquals(tc, 0, r);
+
+    r = aug_match(aug, "/augeas/variables/*", NULL);
+    CuAssertIntEquals(tc, 0, r);
+
+    aug_close(aug);
 }
 
 int main(void) {
@@ -129,6 +229,9 @@ int main(void) {
 
     SUITE_ADD_TEST(suite, testGet);
     SUITE_ADD_TEST(suite, testSetM);
+    SUITE_ADD_TEST(suite, testDefVarMeta);
+    SUITE_ADD_TEST(suite, testDefNodeExistingMeta);
+    SUITE_ADD_TEST(suite, testDefNodeCreateMeta);
 
     abs_top_srcdir = getenv("abs_top_srcdir");
     if (abs_top_srcdir == NULL)
-- 
1.7.2.1




More information about the augeas-devel mailing list