[augeas-devel] [PATCH] Add aug_transform and the transform command. Add -t|--transform option to augtool

Raphaël Pinson raphael.pinson at camptocamp.com
Thu Aug 2 22:05:15 UTC 2012


This is a rework of the previous patch which adds:

 - an aug_transform API call
 - a transform command for aug_srun
 - a -t|--transform option to augtool

---
 src/augeas.c           |   48 ++++++++++++++++++++++++
 src/augeas.h           |   12 ++++++
 src/augeas_sym.version |    1 +
 src/augrun.c           |   33 ++++++++++++++++
 src/augtool.c          |   98 ++++++++++++++++++++++++++++++++----------------
 tests/run.tests        |   21 +++++++++++
 tests/test-api.c       |   39 +++++++++++++++++++
 7 files changed, 219 insertions(+), 33 deletions(-)

diff --git a/src/augeas.c b/src/augeas.c
index 22ebd14..998d27b 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -1729,6 +1729,54 @@ int aug_to_xml(const struct augeas *aug, const char *pathin,
     return -1;
 }
 
+int aug_transform(struct augeas *aug, const char *lens, const char *file) {
+    int r = 0;
+    char *lenspath = malloc(strlen(lens)+14);
+    int lenspathlen = sprintf(lenspath, "/augeas/load/%s", lens);
+
+    char *inclpath = malloc(lenspathlen+16);
+    sprintf(inclpath, "%s/incl[last()+1]", lenspath);
+
+    char *lenslenspath = malloc(lenspathlen+6);
+    sprintf(lenslenspath, "%s/lens", lenspath);
+
+    char *lensname;
+    if (strchr(lens, '.')) {
+        lensname = malloc(strlen(lens)+1);
+        strcpy(lensname, lens);
+    } else {
+        lensname = malloc(strlen(lens)+5);
+        sprintf(lensname, "%s.lns", lens);
+    }
+
+    api_entry(aug);
+
+    ARG_CHECK(STREQ("", lens), aug, "aug_transform: LENS must not be empty");
+    ARG_CHECK(STREQ("", file), aug, "aug_transform: FILE must not be empty");
+
+    if (aug_match(aug, lenslenspath, NULL) == 0)
+        r = aug_set(aug, lenslenspath, lensname);
+        ERR_BAIL(aug);
+
+    r = aug_set(aug, inclpath, file);
+    ERR_BAIL(aug);
+
+    free(lenspath);
+    free(inclpath);
+    free(lenslenspath);
+    free(lensname);
+    api_exit(aug);
+
+    return r;
+ error:
+    free(lenspath);
+    free(inclpath);
+    free(lenslenspath);
+    free(lensname);
+    api_exit(aug);
+    return -1;
+}
+
 int aug_print(const struct augeas *aug, FILE *out, const char *pathin) {
     struct pathx *p;
     int result;
diff --git a/src/augeas.h b/src/augeas.h
index c49308b..9c04cf3 100644
--- a/src/augeas.h
+++ b/src/augeas.h
@@ -353,6 +353,18 @@ int aug_to_xml(const augeas *aug, const char *path, xmlNode **xmldoc,
                unsigned int flags);
 
 /*
+ * Function: aug_transform
+ *
+ * Add a transform for FILE using LENS.
+ * The LENS maybe be a module name or a full lens name.
+ * If a module name is given, then lns will be the lens assumed.
+ *
+ * Returns:
+ * 1 on success, -1 on failure
+ */
+int aug_transform(augeas *aug, const char *lens, const char *file);
+
+/*
  * Function: aug_srun
  *
  * Run one or more newline-separated commands. The output of the commands
diff --git a/src/augeas_sym.version b/src/augeas_sym.version
index 5a6ddfc..710202b 100644
--- a/src/augeas_sym.version
+++ b/src/augeas_sym.version
@@ -56,4 +56,5 @@ AUGEAS_0.16.0 {
     global:
       aug_text_store;
       aug_text_retrieve;
+      aug_transform;
 } AUGEAS_0.15.0;
diff --git a/src/augrun.c b/src/augrun.c
index 7895252..20a94ee 100644
--- a/src/augrun.c
+++ b/src/augrun.c
@@ -910,6 +910,38 @@ static const struct command_def cmd_dump_xml_def = {
     .help = "Export entries in the tree as XML. If PATH is given, printing starts there,\n otherwise the whole tree is printed. If FILENAME is given, the XML is saved\n to the given file."
 };
 
+static void cmd_transform(struct command *cmd) {
+    const char *lens = arg_value(cmd, "lens");
+    const char *file = arg_value(cmd, "file");
+    int r;
+
+    r = aug_transform(cmd->aug, lens, file);
+    if (r < 0)
+        ERR_REPORT(cmd, AUG_ECMDRUN,
+                   "Adding transform for %s on lens %s failed", lens, file);
+}
+
+static const struct command_opt_def cmd_transform_opts[] = {
+    { .type = CMD_PATH, .name = "lens", .optional = false,
+      .help = "the lens to use" },
+    { .type = CMD_PATH, .name = "file", .optional = false,
+      .help = "the file to associate to the lens" },
+    CMD_OPT_DEF_LAST
+};
+
+static const char const cmd_transform_help[] =
+    "Add a transform for FILE using LENS.\n"
+    "The LENS maybe be a module name or a full lens name."
+    "If a module name is given, then lns will be the lens assumed.";
+
+static const struct command_def cmd_transform_def = {
+    .name = "transform",
+    .opts = cmd_transform_opts,
+    .handler = cmd_transform,
+    .synopsis = "add a transform",
+    .help = cmd_transform_help
+};
+
 static void cmd_save(struct command *cmd) {
     int r;
     r = aug_save(cmd->aug);
@@ -1099,6 +1131,7 @@ static const struct command_def const *commands[] = {
     &cmd_store_def,
     &cmd_retrieve_def,
     &cmd_touch_def,
+    &cmd_transform_def,
     &cmd_help_def,
     &cmd_def_last
 };
diff --git a/src/augtool.c b/src/augtool.c
index ce4a8a3..0e202e7 100644
--- a/src/augtool.c
+++ b/src/augtool.c
@@ -44,6 +44,8 @@ static const char *const progname = "augtool";
 static unsigned int flags = AUG_NONE;
 const char *root = NULL;
 char *loadpath = NULL;
+char *transforms = NULL;
+size_t transformslen = 0;
 const char *inputfile = NULL;
 int echo_commands = 0;         /* Gets also changed in main_loop */
 bool print_version = false;
@@ -168,7 +170,8 @@ static char *readline_command_generator(const char *text, int state) {
         "quit", "clear", "defnode", "defvar",
         "get", "ins", "load", "ls", "match",
         "mv", "print", "dump-xml", "rm", "save", "set", "setm",
-        "clearm", "span", "store", "retrieve", "help", NULL };
+        "clearm", "span", "store", "retrieve", "transform",
+        "help", NULL };
 
     static int current = 0;
     const char *name;
@@ -266,22 +269,25 @@ static void usage(void) {
     fprintf(stderr, "Run '%s help' to get a list of possible commands.\n",
             progname);
     fprintf(stderr, "\nOptions:\n\n");
-    fprintf(stderr, "  -c, --typecheck    typecheck lenses\n");
-    fprintf(stderr, "  -b, --backup       preserve originals of modified files with\n"
-                    "                     extension '.augsave'\n");
-    fprintf(stderr, "  -n, --new          save changes in files with extension '.augnew',\n"
-                    "                     leave original unchanged\n");
-    fprintf(stderr, "  -r, --root ROOT    use ROOT as the root of the filesystem\n");
-    fprintf(stderr, "  -I, --include DIR  search DIR for modules; can be given mutiple times\n");
-    fprintf(stderr, "  -e, --echo         echo commands when reading from a file\n");
-    fprintf(stderr, "  -f, --file FILE    read commands from FILE\n");
-    fprintf(stderr, "  -s, --autosave     automatically save at the end of instructions\n");
-    fprintf(stderr, "  -i, --interactive  run an interactive shell after evaluating the commands in STDIN and FILE\n");
-    fprintf(stderr, "  -S, --nostdinc     do not search the builtin default directories for modules\n");
-    fprintf(stderr, "  -L, --noload       do not load any files into the tree on startup\n");
-    fprintf(stderr, "  -A, --noautoload   do not autoload modules from the search path\n");
-    fprintf(stderr, "  --span             load span positions for nodes related to a file\n");
-    fprintf(stderr, "  --version          print version information and exit.\n");
+    fprintf(stderr, "  -c, --typecheck            typecheck lenses\n");
+    fprintf(stderr, "  -b, --backup               preserve originals of modified files with\n"
+                    "                             extension '.augsave'\n");
+    fprintf(stderr, "  -n, --new                  save changes in files with extension '.augnew',\n"
+                    "                             leave original unchanged\n");
+    fprintf(stderr, "  -r, --root ROOT            use ROOT as the root of the filesystem\n");
+    fprintf(stderr, "  -I, --include DIR          search DIR for modules; can be given mutiple times\n");
+    fprintf(stderr, "  -t, --transform LENS=FILE  add a transform for FILE using LENS\n");
+    fprintf(stderr, "  -e, --echo                 echo commands when reading from a file\n");
+    fprintf(stderr, "  -f, --file FILE            read commands from FILE\n");
+    fprintf(stderr, "  -s, --autosave             automatically save at the end of instructions\n");
+    fprintf(stderr, "  -i, --interactive          run an interactive shell after evaluating\n"
+                    "                             the commands in STDIN and FILE\n");
+    fprintf(stderr, "  -S, --nostdinc             do not search the builtin default directories\n"
+                    "                             for modules\n");
+    fprintf(stderr, "  -L, --noload               do not load any files into the tree on startup\n");
+    fprintf(stderr, "  -A, --noautoload           do not autoload modules from the search path\n");
+    fprintf(stderr, "  --span                     load span positions for nodes related to a file\n");
+    fprintf(stderr, "  --version                  print version information and exit.\n");
 
     exit(EXIT_FAILURE);
 }
@@ -294,26 +300,27 @@ static void parse_opts(int argc, char **argv) {
         VAL_SPAN = VAL_VERSION + 1
     };
     struct option options[] = {
-        { "help",      0, 0, 'h' },
-        { "typecheck", 0, 0, 'c' },
-        { "backup",    0, 0, 'b' },
-        { "new",       0, 0, 'n' },
-        { "root",      1, 0, 'r' },
-        { "include",   1, 0, 'I' },
-        { "echo",      0, 0, 'e' },
-        { "file",      1, 0, 'f' },
-        { "autosave",  0, 0, 's' },
-        { "interactive",  0, 0, 'i' },
-        { "nostdinc",  0, 0, 'S' },
-        { "noload",    0, 0, 'L' },
-        { "noautoload", 0, 0, 'A' },
-        { "span",      0, 0, VAL_SPAN },
-        { "version",   0, 0, VAL_VERSION },
+        { "help",        0, 0, 'h' },
+        { "typecheck",   0, 0, 'c' },
+        { "backup",      0, 0, 'b' },
+        { "new",         0, 0, 'n' },
+        { "root",        1, 0, 'r' },
+        { "include",     1, 0, 'I' },
+        { "transform",   1, 0, 't' },
+        { "echo",        0, 0, 'e' },
+        { "file",        1, 0, 'f' },
+        { "autosave",    0, 0, 's' },
+        { "interactive", 0, 0, 'i' },
+        { "nostdinc",    0, 0, 'S' },
+        { "noload",      0, 0, 'L' },
+        { "noautoload",  0, 0, 'A' },
+        { "span",        0, 0, VAL_SPAN },
+        { "version",     0, 0, VAL_VERSION },
         { 0, 0, 0, 0}
     };
     int idx;
 
-    while ((opt = getopt_long(argc, argv, "hnbcr:I:ef:siSLA", options, &idx)) != -1) {
+    while ((opt = getopt_long(argc, argv, "hnbcr:I:t:ef:siSLA", options, &idx)) != -1) {
         switch(opt) {
         case 'c':
             flags |= AUG_TYPE_CHECK;
@@ -333,6 +340,9 @@ static void parse_opts(int argc, char **argv) {
         case 'I':
             argz_add(&loadpath, &loadpathlen, optarg);
             break;
+        case 't':
+            argz_add(&transforms, &transformslen, optarg);
+            break;
         case 'e':
             echo_commands = 1;
             break;
@@ -537,8 +547,24 @@ static int run_args(int argc, char **argv) {
     return (code == 0 || code == -2) ? 0 : -1;
 }
 
+static void add_transform(const char *t) {
+    char delims[] = "=";
+    char *lens, *file;
+    char *transform = strdup(t);
+    int r;
+   
+    lens = strtok(transform, delims);
+    file = strtok(NULL, delims);
+
+    r = aug_transform(aug, lens, file);
+    if (r < 0)
+        fprintf(stderr, "error: %s\n", aug_error_message(aug));
+}
+
 int main(int argc, char **argv) {
     int r;
+    char *t = NULL;
+    bool added_transform = false;
 
     setlocale(LC_ALL, "");
 
@@ -551,6 +577,12 @@ int main(int argc, char **argv) {
             print_aug_error();
         exit(EXIT_FAILURE);
     }
+    while ((t = argz_next(transforms, transformslen, t))) {
+        add_transform(t);
+	added_transform = true;
+    }
+    if (added_transform)
+        r = aug_load(aug);
     if (print_version) {
         print_version_info();
         return EXIT_SUCCESS;
diff --git a/tests/run.tests b/tests/run.tests
index 4f451a2..f9f36ea 100644
--- a/tests/run.tests
+++ b/tests/run.tests
@@ -288,6 +288,27 @@ test get-bad-pathx -1 EPATHX
   get /files[]
 
 #
+# test transform
+#
+test transform-1 3
+  transform Test /tmp/bar
+  get /augeas/load/Test/lens
+  get /augeas/load/Test/incl
+prints
+  /augeas/load/Test/lens = Test.lns
+  /augeas/load/Test/incl = /tmp/bar
+
+test transform-2 3
+  transform Bar /tmp/foo
+  transform Bar /tmp/baz/*
+  print /augeas/load/Bar
+prints
+  /augeas/load/Bar
+  /augeas/load/Bar/lens = "Bar.lns"
+  /augeas/load/Bar/incl[1] = "/tmp/foo"
+  /augeas/load/Bar/incl[2] = "/tmp/baz/*"
+
+#
 # test print
 #
 test print-save 1
diff --git a/tests/test-api.c b/tests/test-api.c
index 5726540..ef9cce5 100644
--- a/tests/test-api.c
+++ b/tests/test-api.c
@@ -455,6 +455,45 @@ static void testToXml(CuTest *tc) {
     aug_close(aug);
 }
 
+static void testTransform(CuTest *tc) {
+    struct augeas *aug;
+    int r;
+    const char *v;
+
+    aug = aug_init(root, loadpath, AUG_NO_STDINC|AUG_NO_MODL_AUTOLOAD);
+
+    r = aug_transform(aug, "Passwd", "/etc/passwd");
+    CuAssertRetSuccess(tc, r);
+
+    r = aug_get(aug, "/augeas/load/Passwd/incl", &v);
+    CuAssertRetSuccess(tc, r);
+    CuAssertStrEquals(tc, "/etc/passwd", v);
+
+    r = aug_get(aug, "/augeas/load/Passwd/lens", &v);
+    CuAssertRetSuccess(tc, r);
+    CuAssertStrEquals(tc, "Passwd.lns", v);
+
+    r = aug_transform(aug, "Shellvars.lns_norec", "/etc/sysconfig/grub");
+    CuAssertRetSuccess(tc, r);
+
+    r = aug_transform(aug, "Shellvars.lns_norec", "/etc/sysconfig/network");
+    CuAssertRetSuccess(tc, r);
+
+    r = aug_get(aug, "/augeas/load/Shellvars.lns_norec/incl[1]", &v);
+    CuAssertRetSuccess(tc, r);
+    CuAssertStrEquals(tc, "/etc/sysconfig/grub", v);
+
+    r = aug_get(aug, "/augeas/load/Shellvars.lns_norec/incl[2]", &v);
+    CuAssertRetSuccess(tc, r);
+    CuAssertStrEquals(tc, "/etc/sysconfig/network", v);
+
+    r = aug_get(aug, "/augeas/load/Shellvars.lns_norec/lens", &v);
+    CuAssertRetSuccess(tc, r);
+    CuAssertStrEquals(tc, "Shellvars.lns_norec", v);
+
+    aug_close(aug);
+}
+
 static void testTextStore(CuTest *tc) {
     static const char *const hosts = "192.168.0.1 rtr.example.com router\n";
     /* Not acceptable for Hosts.lns - missing canonical and \n */
-- 
1.7.9.5




More information about the augeas-devel mailing list