[augeas-devel] [PATCH] Add aug_label to retrieve the label from a path.

Raphaël Pinson raphael.pinson at camptocamp.com
Wed Nov 7 09:18:18 UTC 2012


---
 src/augeas.c           |   30 ++++++++++++++++++++++++++++++
 src/augeas.h           |   17 +++++++++++++++++
 src/augeas_sym.version |    1 +
 src/augrun.c           |   32 ++++++++++++++++++++++++++++++++
 src/augtool.c          |    2 +-
 tests/test-api.c       |   19 +++++++++++++++++++
 6 files changed, 100 insertions(+), 1 deletion(-)

diff --git a/src/augeas.c b/src/augeas.c
index 08901f2..830dbeb 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -766,6 +766,36 @@ int aug_get(const struct augeas *aug, const char *path, const char **value) {
     return -1;
 }
 
+int aug_label(const struct augeas *aug, const char *path, const char **label) {
+    struct pathx *p = NULL;
+    struct tree *match;
+    int r;
+
+    api_entry(aug);
+
+    p = pathx_aug_parse(aug, aug->origin, tree_root_ctx(aug), path, true);
+    ERR_BAIL(aug);
+
+    if (label != NULL)
+        *label = NULL;
+
+    r = pathx_find_one(p, &match);
+    ERR_BAIL(aug);
+    ERR_THROW(r > 1, aug, AUG_EMMATCH, "There are %d nodes matching %s",
+              r, path);
+
+    if (r == 1 && label != NULL)
+        *label = match->label;
+    free_pathx(p);
+
+    api_exit(aug);
+    return r;
+ error:
+    free_pathx(p);
+    api_exit(aug);
+    return -1;
+}
+
 static void record_var_meta(struct augeas *aug, const char *name,
                             const char *expr) {
     /* Record the definition of the variable */
diff --git a/src/augeas.h b/src/augeas.h
index fde3d09..8a44fa6 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -142,6 +142,23 @@ int aug_defnode(augeas *aug, const char *name, const char *expr,
  */
 int aug_get(const augeas *aug, const char *path, const char **value);
 
+/* Function: aug_label
+ *
+ * Lookup the label associated with PATH. LABEL can be NULL, in which case
+ * it is ignored. If LABEL is not NULL, it is used to return a pointer to
+ * the value associated with PATH if PATH matches exactly one node. If PATH
+ * matches no nodes or more than one node, *LABEL is set to NULL.
+ *
+ * The string *LABEL must not be freed by the caller, and is valid as long
+ * as its node remains unchanged.
+ *
+ * Returns:
+ * 1 if there is exactly one node matching PATH, 0 if there is none,
+ * and a negative value if there is more than one node matching PATH, or if
+ * PATH is not a legal path expression.
+ */
+int aug_label(const augeas *aug, const char *path, const char **label);
+
 /* Function: aug_set
  *
  * Set the value associated with PATH to VALUE. VALUE is copied into the
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index c56d443..1501801 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -58,4 +58,5 @@ AUGEAS_0.16.0 {
       aug_text_retrieve;
       aug_rename;
       aug_transform;
+      aug_label;
 } AUGEAS_0.15.0;
diff --git a/src/augrun.c b/src/augrun.c
index 28d6c63..2677484 100644
--- a/src/augrun.c
+++ b/src/augrun.c
@@ -842,6 +842,37 @@ static const struct command_def cmd_get_def = {
     .help = "Get and print the value associated with PATH"
 };
 
+static void cmd_label(struct command *cmd) {
+    const char *path = arg_value(cmd, "path");
+    const char *lbl;
+    int r;
+
+    r = aug_label(cmd->aug, path, &lbl);
+    ERR_RET(cmd);
+    fprintf(cmd->out, "%s", path);
+    if (r == 0) {
+        fprintf(cmd->out, " (o)\n");
+    } else if (lbl == NULL) {
+        fprintf(cmd->out, " (none)\n");
+    } else {
+        fprintf(cmd->out, " = %s\n", lbl);
+    }
+}
+
+static const struct command_opt_def cmd_label_opts[] = {
+    { .type = CMD_PATH, .name = "path", .optional = false,
+      .help = "get the label of this node" },
+    CMD_OPT_DEF_LAST
+};
+
+static const struct command_def cmd_label_def = {
+    .name = "label",
+    .opts = cmd_label_opts,
+    .handler = cmd_label,
+    .synopsis = "get the label of a node",
+    .help = "Get and print the label associated with PATH"
+};
+
 static void cmd_print(struct command *cmd) {
     const char *path = arg_value(cmd, "path");
 
@@ -1129,6 +1160,7 @@ static const struct command_grp_def cmd_grp_read_def = {
     .commands = {
         &cmd_dump_xml_def,
         &cmd_get_def,
+        &cmd_label_def,
         &cmd_ls_def,
         &cmd_match_def,
         &cmd_print_def,
diff --git a/src/augtool.c b/src/augtool.c
index 830082f..94d85f4 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -168,7 +168,7 @@ static char *readline_command_generator(const char *text, int state) {
     // FIXME: expose somewhere under /augeas
     static const char *const commands[] = {
         "quit", "clear", "defnode", "defvar",
-        "get", "ins", "load", "ls", "match",
+        "get", "label", "ins", "load", "ls", "match",
         "mv", "rename", "print", "dump-xml", "rm", "save", "set", "setm",
         "clearm", "span", "store", "retrieve", "transform",
         "help", NULL };
diff --git a/tests/test-api.c b/tests/test-api.c
index e74a6db..eb4ffe1 100644
--- a/tests/test-api.c
+++ b/tests/test-api.c
@@ -44,6 +44,7 @@ static char *loadpath;
 static void testGet(CuTest *tc) {
     int r;
     const char *value;
+    const char *label;
     struct augeas *aug;
 
     aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_LOAD);
@@ -73,6 +74,24 @@ static void testGet(CuTest *tc) {
     CuAssertPtrEquals(tc, NULL, value);
     CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
 
+    /* aug_label returns 1 and the label if exactly one node matches */
+    r = aug_label(aug, "/augeas/version/save/*[1]", &label);
+    CuAssertIntEquals(tc, 1, r);
+    CuAssertPtrNotNull(tc, label);
+    CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
+
+    /* aug_label returns 0 and no label when no node matches */
+    r = aug_label(aug, "/augeas/version/save/*[ last() + 1 ]", &label);
+    CuAssertIntEquals(tc, 0, r);
+    CuAssertPtrEquals(tc, NULL, label);
+    CuAssertIntEquals(tc, AUG_NOERROR, aug_error(aug));
+
+    /* aug_label should return an error when multiple nodes match */
+    r = aug_label(aug, "/augeas/version/save/*", &label);
+    CuAssertIntEquals(tc, -1, r);
+    CuAssertPtrEquals(tc, NULL, label);
+    CuAssertIntEquals(tc, AUG_EMMATCH, aug_error(aug));
+
     /* augeas should prepend context if relative path given */
     r = aug_set(aug, "/augeas/context", "/augeas/version");
     r = aug_get(aug, "save/*[1]", &value);
-- 
1.7.9.5




More information about the augeas-devel mailing list