Remove obsolete files

Remove all files left over from previous release which aren't required for
0.7.3.
This commit is contained in:
Matthew Booth 2010-11-11 17:02:41 +00:00
parent d72bcea26f
commit fdeba742da
13 changed files with 0 additions and 1291 deletions

1
.gitignore vendored
View File

@ -1,2 +1 @@
augeas-0.7.2.tar.gz
augeas-0.7.3.tar.gz augeas-0.7.3.tar.gz

View File

@ -1,33 +0,0 @@
From 0c43ca0f0ce9008a991c2a2d99e938f4a60712a3 Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 14:12:47 -0700
Subject: [PATCH 1/9] * src/augeas.c (aug_defvar): use constants to create /augeas/variables
---
src/augeas.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index c21afe9..7b51a77 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -41,6 +41,7 @@ static const char *const s_load = "load";
static const char *const s_pathx = "pathx";
static const char *const s_error = "error";
static const char *const s_pos = "pos";
+static const char *const s_vars = "variables";
#define TREE_HIDDEN(tree) ((tree)->label == NULL)
@@ -529,7 +530,7 @@ 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, "augeas", "variables");
+ 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);
--
1.6.6.1

View File

@ -1,28 +0,0 @@
From 6c713a0855f6f2f144ebc2240fc4ec0e3470aacc Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 14:13:13 -0700
Subject: [PATCH 2/9] * src/augeas.c (aug_init): create /augeas/variables on startup
---
src/augeas.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index 7b51a77..9ca26b6 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -406,8 +406,9 @@ struct augeas *aug_init(const char *root, const char *loadpath,
} else {
aug_set(result, AUGEAS_META_SAVE_MODE, AUG_SAVE_OVERWRITE_TEXT);
}
- /* Make sure we always have /files */
- aug_set(result, AUGEAS_FILES_TREE, NULL);
+ /* Make sure we always have /files and /augeas/variables */
+ tree_path_cr(result->origin, 1, s_files);
+ tree_path_cr(result->origin, 2, s_augeas, s_vars);
if (interpreter_init(result) == -1)
goto error;
--
1.6.6.1

View File

@ -1,56 +0,0 @@
From 984ff1b8f37c64339ed9663d2b052dadbea82032 Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 14:21:42 -0700
Subject: [PATCH 3/9] Redefine all variables upon load
This is a slight change in behavior: before, we used to just discard the
contents of all variables upon load. Now, we redefine variables by
evaluating the expression with which they were defined initially again.
The change in behavior is backwards compatible, since at worst, users will
redefine variables themselves after an aug_load
---
src/augeas.c | 6 ++++++
tests/test-load.c | 2 +-
2 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index 9ca26b6..2e5f296 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -447,6 +447,7 @@ int aug_load(struct augeas *aug) {
struct tree *meta_files = tree_child_cr(meta, s_files);
struct tree *files = tree_child_cr(aug->origin, s_files);
struct tree *load = tree_child_cr(meta, s_load);
+ struct tree *vars = tree_child_cr(meta, s_vars);
api_entry(aug);
@@ -461,6 +462,11 @@ int aug_load(struct augeas *aug) {
}
tree_clean(aug->origin);
+ list_for_each(v, vars->children) {
+ aug_defvar(aug, v->label, v->value);
+ ERR_BAIL(aug);
+ }
+
api_exit(aug);
return 0;
error:
diff --git a/tests/test-load.c b/tests/test-load.c
index 547e222..e4dd38a 100644
--- a/tests/test-load.c
+++ b/tests/test-load.c
@@ -205,7 +205,7 @@ static void testLoadDefined(CuTest *tc) {
CuAssertRetSuccess(tc, r);
r = aug_match(aug, "$v", NULL);
- CuAssertIntEquals(tc, 0, r);
+ CuAssertIntEquals(tc, 2, r);
aug_close(aug);
}
--
1.6.6.1

View File

@ -1,96 +0,0 @@
From 218003a813acae99370d45157fe57589b8a8685c Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 14:50:14 -0700
Subject: [PATCH 4/9] Move 'run' test utility to cutest.[ch]
* tests/cutest.h (run): add prototype
* tests/cutest.c (run): add impl
* tests/test-save.c (run): remove
---
tests/cutest.c | 24 ++++++++++++++++++++++++
tests/cutest.h | 2 ++
tests/test-save.c | 20 --------------------
3 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/tests/cutest.c b/tests/cutest.c
index 4cfe0fc..120e31c 100644
--- a/tests/cutest.c
+++ b/tests/cutest.c
@@ -296,6 +296,30 @@ void CuSuiteDetails(CuSuite* testSuite, char **details) {
}
/*
+ * Test utilities
+ */
+void run(CuTest *tc, const char *format, ...) {
+ char *command;
+ va_list args;
+ int r;
+
+ va_start(args, format);
+ r = vasprintf(&command, format, args);
+ va_end (args);
+ if (r < 0)
+ CuFail(tc, "Failed to format command (out of memory)");
+ r = system(command);
+ if (r < 0 || (WIFEXITED(r) && WEXITSTATUS(r) != 0)) {
+ char *msg;
+ r = asprintf(&msg, "Command %s failed with status %d\n",
+ command, WEXITSTATUS(r));
+ CuFail(tc, msg);
+ free(msg);
+ }
+ free(command);
+}
+
+/*
* Local variables:
* indent-tabs-mode: nil
* c-indent-level: 4
diff --git a/tests/cutest.h b/tests/cutest.h
index ae9fe0f..a667e50 100644
--- a/tests/cutest.h
+++ b/tests/cutest.h
@@ -120,6 +120,8 @@ void CuSuiteRun(CuSuite* testSuite);
void CuSuiteSummary(CuSuite* testSuite, char **summary);
void CuSuiteDetails(CuSuite* testSuite, char **details);
+/* Run a command */
+void run(CuTest *tc, const char *format, ...);
#endif /* CU_TEST_H */
/*
diff --git a/tests/test-save.c b/tests/test-save.c
index c563ad3..daeace3 100644
--- a/tests/test-save.c
+++ b/tests/test-save.c
@@ -40,26 +40,6 @@ struct augeas *aug = NULL;
exit(EXIT_FAILURE); \
} while(0)
-static void run(CuTest *tc, const char *format, ...) {
- char *command;
- va_list args;
- int r;
-
- va_start(args, format);
- r = vasprintf(&command, format, args);
- va_end (args);
- if (r < 0)
- CuFail(tc, "Failed to format command (out of memory)");
- r = system(command);
- if (r < 0 || (WIFEXITED(r) && WEXITSTATUS(r) != 0)) {
- char *msg;
- r = asprintf(&msg, "Command %s failed with status %d\n",
- command, WEXITSTATUS(r));
- CuFail(tc, msg);
- free(msg);
- }
-}
-
static void setup(CuTest *tc) {
char *lensdir;
--
1.6.6.1

View File

@ -1,98 +0,0 @@
From 21d39d66b9c2d827cbede4ace1fe0fc0b637992b Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 15:01:03 -0700
Subject: [PATCH 5/9] * src/test-load.c (testLoadSave): work off a writable /etc/hosts
This addresses a FIXME that could lead to use not detecting incorrect behavior
---
tests/test-load.c | 53 +++++++++++++++++++++++++++++++++++++----------------
1 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/tests/test-load.c b/tests/test-load.c
index e4dd38a..a8107a1 100644
--- a/tests/test-load.c
+++ b/tests/test-load.c
@@ -32,7 +32,8 @@
#define CuAssertRetSuccess(tc, n) CuAssertTrue(tc, (n) == 0)
static const char *abs_top_srcdir;
-static char *root;
+static const char *abs_top_builddir;
+static char *root = NULL;
static char *loadpath;
#define die(msg) \
@@ -41,6 +42,36 @@ static char *loadpath;
exit(EXIT_FAILURE); \
} while(0)
+static struct augeas *setup_writable_hosts(CuTest *tc) {
+ char *etcdir, *build_root;
+ struct augeas *aug = NULL;
+ int r;
+
+ if (asprintf(&build_root, "%s/build/test-load/%s",
+ abs_top_builddir, tc->name) < 0) {
+ CuFail(tc, "failed to set build_root");
+ }
+
+ if (asprintf(&etcdir, "%s/etc", build_root) < 0)
+ CuFail(tc, "asprintf etcdir failed");
+
+ run(tc, "test -d %s && chmod -R u+w %s || :", build_root, build_root);
+ run(tc, "rm -rf %s", build_root);
+ run(tc, "mkdir -p %s", etcdir);
+ run(tc, "cp -pr %s/etc/hosts %s", root, etcdir);
+ run(tc, "chmod -R u+w %s", build_root);
+
+ aug = aug_init(build_root, loadpath, AUG_NO_MODL_AUTOLOAD);
+ CuAssertPtrNotNull(tc, aug);
+
+ r = aug_set(aug, "/augeas/load/Hosts/lens", "Hosts.lns");
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_set(aug, "/augeas/load/Hosts/incl", "/etc/hosts");
+ CuAssertRetSuccess(tc, r);
+
+ return aug;
+}
static void testDefault(CuTest *tc) {
augeas *aug = NULL;
@@ -162,21 +193,7 @@ static void testLoadSave(CuTest *tc) {
augeas *aug = NULL;
int r;
- /* FIXME: This test behaves properly during distcheck, since srcdir
- * is writeprotected, making an incorrect attempt to write
- * /etc/hosts.augnew fail; during normal 'make check' the test will
- * succeed.
- * To address this, we should copy the files fro, tests/root into
- * another directory and 'chmod a-w /etc' in that root
- */
- aug = aug_init(root, loadpath, AUG_NO_MODL_AUTOLOAD|AUG_SAVE_NOOP);
- CuAssertPtrNotNull(tc, aug);
-
- r = aug_set(aug, "/augeas/load/Hosts/lens", "Hosts.lns");
- CuAssertRetSuccess(tc, r);
-
- r = aug_set(aug, "/augeas/load/Hosts/incl", "/etc/hosts");
- CuAssertRetSuccess(tc, r);
+ aug = setup_writable_hosts(tc);
r = aug_load(aug);
CuAssertRetSuccess(tc, r);
@@ -262,6 +279,10 @@ int main(void) {
if (abs_top_srcdir == NULL)
die("env var abs_top_srcdir must be set");
+ abs_top_builddir = getenv("abs_top_builddir");
+ if (abs_top_builddir == NULL)
+ die("env var abs_top_builddir must be set");
+
if (asprintf(&root, "%s/tests/root", abs_top_srcdir) < 0) {
die("failed to set root");
}
--
1.6.6.1

View File

@ -1,55 +0,0 @@
From 11b85805955557ae87494fff57ead04be6ab90b6 Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 15:43:07 -0700
Subject: [PATCH 6/9] Add xstrtoint64 to internal.[ch]
The implementation is directly from libvirt
* src/internal.h (xstrtoint64): add prototype
* src/internal.c (xstrtoint64): add impl
---
src/internal.c | 13 +++++++++++++
src/internal.h | 3 +++
2 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/src/internal.c b/src/internal.c
index befd3af..8419ca2 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -392,6 +392,19 @@ int xasprintf(char **strp, const char *format, ...) {
return result;
}
+/* From libvirt's src/xen/block_stats.c */
+int xstrtoint64(char const *s, int base, int64_t *result) {
+ long long int lli;
+ char *p;
+
+ errno = 0;
+ lli = strtoll(s, &p, base);
+ if (errno || !(*p == 0 || *p == '\n') || p == s || (int64_t) lli != lli)
+ return -1;
+ *result = lli;
+ return 0;
+}
+
void calc_line_ofs(const char *text, size_t pos, size_t *line, size_t *ofs) {
*line = 1;
*ofs = 0;
diff --git a/src/internal.h b/src/internal.h
index b2a402f..51aa025 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -272,6 +272,9 @@ const char *xstrerror(int errnum, char *buf, size_t len);
/* Like asprintf, but set *STRP to NULL on error */
int xasprintf(char **strp, const char *format, ...);
+/* Convert S to RESULT with error checking */
+int xstrtoint64(char const *s, int base, int64_t *result);
+
/* Calculate line and column number of character POS in TEXT */
void calc_line_ofs(const char *text, size_t pos, size_t *line, size_t *ofs);
--
1.6.6.1

View File

@ -1,42 +0,0 @@
From 72c636decaa8b8c1764710c60f9932892c411207 Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 15:44:35 -0700
Subject: [PATCH 7/9] Make tree_clean available outside of augeas.c
* src/augeas.c (tree_clean): remove 'static'
* src/internal.h (tree_clean): add prototype
---
src/augeas.c | 3 +--
src/internal.h | 2 ++
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index 2e5f296..5ca1789 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -74,8 +74,7 @@ static void tree_mark_dirty(struct tree *tree) {
tree->dirty = 1;
}
-/* Clear the dirty flag in the whole TREE */
-static void tree_clean(struct tree *tree) {
+void tree_clean(struct tree *tree) {
if (tree->dirty) {
list_for_each(c, tree->children)
tree_clean(c);
diff --git a/src/internal.h b/src/internal.h
index 51aa025..f1e6f3a 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -379,6 +379,8 @@ int dump_tree(FILE *out, struct tree *tree);
int tree_equal(const struct tree *t1, const struct tree *t2);
char *path_expand(struct tree *tree, const char *ppath);
char *path_of_tree(struct tree *tree);
+/* Clear the dirty flag in the whole TREE */
+void tree_clean(struct tree *tree);
/* Return first child with label LABEL or NULL */
struct tree *tree_child(struct tree *tree, const char *label);
/* Return first existing child with label LABEL or create one. Return NULL
--
1.6.6.1

View File

@ -1,68 +0,0 @@
From 0695bdd057b2cbfc6146ac498179c0f162ee889f Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 15:46:53 -0700
Subject: [PATCH 8/9] Add utility tree_store_value to avoid unnecessary strdup's
* src/internal.h (tree_store_value): add prototype
* src/augeas.c (tree_store_value): new function; (tree_set_value): use
tree_store_value
---
src/augeas.c | 18 ++++++++++++++----
src/internal.h | 5 ++++-
2 files changed, 18 insertions(+), 5 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index 5ca1789..744b699 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -156,17 +156,27 @@ struct tree *tree_find_cr(struct augeas *aug, const char *path) {
return result;
}
-int tree_set_value(struct tree *tree, const char *value) {
+void tree_store_value(struct tree *tree, char **value) {
if (tree->value != NULL) {
free(tree->value);
tree->value = NULL;
}
+ if (*value != NULL) {
+ tree->value = *value;
+ *value = NULL;
+ }
+ tree_mark_dirty(tree);
+}
+
+int tree_set_value(struct tree *tree, const char *value) {
+ char *v = NULL;
+
if (value != NULL) {
- tree->value = strdup(value);
- if (tree->value == NULL)
+ v = strdup(value);
+ if (v == NULL)
return -1;
}
- tree_mark_dirty(tree);
+ tree_store_value(tree, &v);
return 0;
}
diff --git a/src/internal.h b/src/internal.h
index f1e6f3a..7513d47 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -389,7 +389,10 @@ struct tree *tree_child_cr(struct tree *tree, const char *label);
/* Create a path in the tree; nodes along the path are looked up with
* tree_child_cr */
struct tree *tree_path_cr(struct tree *tree, int n, ...);
-/* Set the value of TREE and update dirty flags */
+/* Store VALUE directly as the value of TREE and set VALUE to NULL.
+ * Update dirty flags */
+void tree_store_value(struct tree *tree, char **value);
+/* Set the value of TREE to a copy of VALUE and update dirty flags */
int tree_set_value(struct tree *tree, const char *value);
/* Cleanly remove all children of TREE, but leave TREE itself unchanged */
void tree_unlink_children(struct augeas *aug, struct tree *tree);
--
1.6.6.1

View File

@ -1,501 +0,0 @@
From 5ee8163051be8214507c13c86171ac90ca7cb91f Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Tue, 29 Jun 2010 15:32:44 -0700
Subject: [PATCH 9/9] Avoid unnecessary file parsing when reloading the tree
We used to reparse every file we knew about upon aug_load. Now, we only
reparse files if the file has changed on disk.
We test a few scenarios to make sure aug_load retains its behavior of
obliterating the tree and filling it with the latest from disk. This
includes throwing away unsaved changes or trees that have been deleted.
---
src/augeas.c | 72 ++++++++++++++++++++++++++-
src/transform.c | 78 +++++++++++++++++++++++++++--
tests/cutest.c | 17 ++++++
tests/cutest.h | 4 ++
tests/test-load.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++
tests/xpath.tests | 1 +
6 files changed, 307 insertions(+), 7 deletions(-)
diff --git a/src/augeas.c b/src/augeas.c
index 744b699..45c2207 100644
--- a/src/augeas.c
+++ b/src/augeas.c
@@ -451,6 +451,51 @@ void tree_unlink_children(struct augeas *aug, struct tree *tree) {
tree_unlink(tree->children);
}
+static void tree_mark_files(struct tree *tree) {
+ if (tree_child(tree, "path") != NULL) {
+ tree_mark_dirty(tree);
+ } else {
+ list_for_each(c, tree->children) {
+ tree_mark_files(c);
+ }
+ }
+}
+
+static void tree_rm_dirty_files(struct augeas *aug, struct tree *tree) {
+ struct tree *p;
+
+ if (!tree->dirty)
+ return;
+
+ if ((p = tree_child(tree, "path")) != NULL) {
+ aug_rm(aug, p->value);
+ tree_unlink(tree);
+ } else {
+ struct tree *c = tree->children;
+ while (c != NULL) {
+ struct tree *next = c->next;
+ tree_rm_dirty_files(aug, c);
+ c = next;
+ }
+ }
+}
+
+static void tree_rm_dirty_leaves(struct augeas *aug, struct tree *tree,
+ struct tree *protect) {
+ if (! tree->dirty)
+ return;
+
+ struct tree *c = tree->children;
+ while (c != NULL) {
+ struct tree *next = c->next;
+ tree_rm_dirty_leaves(aug, c, protect);
+ c = next;
+ }
+
+ if (tree != protect && tree->children == NULL)
+ tree_unlink(tree);
+}
+
int aug_load(struct augeas *aug) {
struct tree *meta = tree_child_cr(aug->origin, s_augeas);
struct tree *meta_files = tree_child_cr(meta, s_files);
@@ -462,13 +507,36 @@ int aug_load(struct augeas *aug) {
ERR_NOMEM(load == NULL, aug);
- tree_unlink_children(aug, meta_files);
- tree_unlink_children(aug, files);
+ /* To avoid unnecessary loads of files, we reload an existing file in
+ * several steps:
+ * (1) mark all file nodes under /augeas/files as dirty (and only those)
+ * (2) process all files matched by a lens; we check (in
+ * transform_load) if the file has been modified. If it has, we
+ * reparse it. Either way, we clear the dirty flag. We also need to
+ * reread the file if part or all of it has been modified in the
+ * tree but not been saved yet
+ * (3) remove all files from the tree that still have a dirty entry
+ * under /augeas/files. Those files are not processed by any lens
+ * anymore
+ * (4) Remove entries from /augeas/files and /files that correspond
+ * to directories without any files of interest
+ */
+ tree_clean(meta_files);
+ tree_mark_files(meta_files);
list_for_each(xfm, load->children) {
if (transform_validate(aug, xfm) == 0)
transform_load(aug, xfm);
}
+
+ /* This makes it possible to spot 'directories' that are now empty
+ * because we removed their file contents */
+ tree_clean(files);
+
+ tree_rm_dirty_files(aug, meta_files);
+ tree_rm_dirty_leaves(aug, meta_files, meta_files);
+ tree_rm_dirty_leaves(aug, files, files);
+
tree_clean(aug->origin);
list_for_each(v, vars->children) {
diff --git a/src/transform.c b/src/transform.c
index 0c56034..00552da 100644
--- a/src/transform.c
+++ b/src/transform.c
@@ -49,6 +49,7 @@ static const int glob_flags = GLOB_NOSORT;
/* Loaded files are tracked underneath METATREE. When a file with name
* FNAME is loaded, certain entries are made under METATREE / FNAME:
* path : path where tree for FNAME is put
+ * mtime : time of last modification of the file as reported by stat(2)
* lens/info : information about where the applied lens was loaded from
* lens/id : unique hexadecimal id of the lens
* error : indication of errors during processing FNAME, or NULL
@@ -60,6 +61,7 @@ static const int glob_flags = GLOB_NOSORT;
static const char *const s_path = "path";
static const char *const s_lens = "lens";
static const char *const s_info = "info";
+static const char *const s_mtime = "mtime";
static const char *const s_error = "error";
/* These are all put underneath "error" */
@@ -111,6 +113,59 @@ static bool is_regular_file(const char *path) {
return S_ISREG(st.st_mode);
}
+static char *mtime_as_string(struct augeas *aug, const char *fname) {
+ int r;
+ struct stat st;
+ char *result = NULL;
+
+ r = stat(fname, &st);
+ if (r < 0) {
+ /* If we fail to stat, silently ignore the error
+ * and report an impossible mtime */
+ result = strdup("0");
+ ERR_NOMEM(result == NULL, aug);
+ } else {
+ r = xasprintf(&result, "%ld", (long) st.st_mtime);
+ ERR_NOMEM(r < 0, aug);
+ }
+ return result;
+ error:
+ FREE(result);
+ return NULL;
+}
+
+static bool file_current(struct augeas *aug, const char *fname,
+ struct tree *finfo) {
+ struct tree *mtime = tree_child(finfo, s_mtime);
+ struct tree *file = NULL, *path = NULL;
+ int r;
+ struct stat st;
+ int64_t mtime_i;
+
+ if (mtime == NULL || mtime->value == NULL)
+ return false;
+
+ r = xstrtoint64(mtime->value, 10, &mtime_i);
+ if (r < 0) {
+ /* Ignore silently and err on the side of caution */
+ return false;
+ }
+
+ r = stat(fname, &st);
+ if (r < 0)
+ return false;
+
+ if (mtime_i != (int64_t) st.st_mtime)
+ return false;
+
+ path = tree_child(finfo, s_path);
+ if (path == NULL)
+ return false;
+
+ file = tree_find(aug, path->value);
+ return (file != NULL && ! file->dirty);
+}
+
static int filter_generate(struct tree *xfm, const char *root,
int *nmatches, char ***matches) {
glob_t globbuf;
@@ -326,7 +381,8 @@ static int store_error(struct augeas *aug,
* Returns 0 on success, -1 on error
*/
static int add_file_info(struct augeas *aug, const char *node,
- struct lens *lens, const char *lens_name) {
+ struct lens *lens, const char *lens_name,
+ const char *filename) {
struct tree *file, *tree;
char *tmp = NULL;
int r;
@@ -348,6 +404,13 @@ static int add_file_info(struct augeas *aug, const char *node,
r = tree_set_value(tree, node);
ERR_NOMEM(r < 0, aug);
+ /* Set 'mtime' */
+ tmp = mtime_as_string(aug, filename);
+ ERR_BAIL(aug);
+ tree = tree_child_cr(file, s_mtime);
+ ERR_NOMEM(tree == NULL, aug);
+ tree_store_value(tree, &tmp);
+
/* Set 'lens/info' */
tmp = format_info(lens->info);
ERR_NOMEM(tmp == NULL, aug);
@@ -362,6 +425,8 @@ static int add_file_info(struct augeas *aug, const char *node,
r = tree_set_value(tree, lens_name);
ERR_NOMEM(r < 0, aug);
+ tree_clean(file);
+
result = 0;
error:
free(path);
@@ -404,7 +469,7 @@ static int load_file(struct augeas *aug, struct lens *lens,
path = file_name_path(aug, filename);
ERR_NOMEM(path == NULL, aug);
- r = add_file_info(aug, path, lens, lens_name);
+ r = add_file_info(aug, path, lens, lens_name, filename);
if (r < 0)
goto done;
@@ -602,7 +667,8 @@ int transform_load(struct augeas *aug, struct tree *xfm) {
for (int i=0; i < nmatches; i++) {
const char *filename = matches[i] + strlen(aug->root) - 1;
struct tree *finfo = file_info(aug, filename);
- if (finfo != NULL && tree_child(finfo, s_lens) != NULL) {
+ if (finfo != NULL && !finfo->dirty &&
+ tree_child(finfo, s_lens) != NULL) {
const char *s = xfm_lens_name(finfo);
char *fpath = file_name_path(aug, matches[i]);
transform_file_error(aug, "mxfm_load", filename,
@@ -610,9 +676,11 @@ int transform_load(struct augeas *aug, struct tree *xfm) {
s, lens_name);
aug_rm(aug, fpath);
free(fpath);
- } else {
+ } else if (!file_current(aug, matches[i], finfo)) {
load_file(aug, lens, lens_name, matches[i]);
}
+ if (finfo != NULL)
+ finfo->dirty = 0;
FREE(matches[i]);
}
lens_release(lens);
@@ -945,7 +1013,7 @@ int transform_save(struct augeas *aug, struct tree *xfm,
result = 1;
done:
- r = add_file_info(aug, path, lens, lens_name);
+ r = add_file_info(aug, path, lens, lens_name, filename);
if (r < 0) {
err_status = "file_info";
result = -1;
diff --git a/tests/cutest.c b/tests/cutest.c
index 120e31c..08dbfd7 100644
--- a/tests/cutest.c
+++ b/tests/cutest.c
@@ -138,6 +138,23 @@ void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line,
CuFailInternal(tc, file, line, string);
}
+void CuAssertStrNotEqual_LineMsg(CuTest* tc, const char* file, int line,
+ const char* message,
+ const char* expected, const char* actual) {
+ char *string = NULL;
+
+ if (expected != NULL && actual != NULL && strcmp(expected, actual) != 0)
+ return;
+
+ if (message != NULL) {
+ asprintf_or_die(&string, "%s: expected <%s> but was <%s>", message,
+ expected, actual);
+ } else {
+ asprintf_or_die(&string, "expected <%s> but was <%s>", expected, actual);
+ }
+ CuFailInternal(tc, file, line, string);
+}
+
void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line,
const char* message,
int expected, int actual) {
diff --git a/tests/cutest.h b/tests/cutest.h
index a667e50..616fb1f 100644
--- a/tests/cutest.h
+++ b/tests/cutest.h
@@ -61,6 +61,9 @@ void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message,
void CuAssertStrEquals_LineMsg(CuTest* tc,
const char* file, int line, const char* message,
const char* expected, const char* actual);
+void CuAssertStrNotEqual_LineMsg(CuTest* tc,
+ const char* file, int line, const char* message,
+ const char* expected, const char* actual);
void CuAssertIntEquals_LineMsg(CuTest* tc,
const char* file, int line, const char* message,
int expected, int actual);
@@ -82,6 +85,7 @@ void CuAssertPtrNotEqual_LineMsg(CuTest* tc,
#define CuAssertStrEquals(tc,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
#define CuAssertStrEquals_Msg(tc,ms,ex,ac) CuAssertStrEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
+#define CuAssertStrNotEqual(tc,ex,ac) CuAssertStrNotEqual_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
#define CuAssertIntEquals(tc,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac))
#define CuAssertIntEquals_Msg(tc,ms,ex,ac) CuAssertIntEquals_LineMsg((tc),__FILE__,__LINE__,(ms),(ex),(ac))
#define CuAssertDblEquals(tc,ex,ac,dl) CuAssertDblEquals_LineMsg((tc),__FILE__,__LINE__,NULL,(ex),(ac),(dl))
diff --git a/tests/test-load.c b/tests/test-load.c
index a8107a1..fe92305 100644
--- a/tests/test-load.c
+++ b/tests/test-load.c
@@ -70,6 +70,8 @@ static struct augeas *setup_writable_hosts(CuTest *tc) {
r = aug_set(aug, "/augeas/load/Hosts/incl", "/etc/hosts");
CuAssertRetSuccess(tc, r);
+ free(build_root);
+ free(etcdir);
return aug;
}
@@ -262,6 +264,142 @@ static void testDefvarExpr(CuTest *tc) {
aug_close(aug);
}
+static void testReloadChanged(CuTest *tc) {
+ FILE *fp;
+ augeas *aug = NULL;
+ const char *build_root, *mtime2, *s;
+ char *mtime1;
+ char *hosts = NULL;
+ int r;
+
+ aug = setup_writable_hosts(tc);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_get(aug, "/augeas/root", &build_root);
+ CuAssertIntEquals(tc, 1, r);
+
+ r = aug_get(aug, "/augeas/files/etc/hosts/mtime", &s);
+ CuAssertIntEquals(tc, 1, r);
+ mtime1 = strdup(s);
+ CuAssertPtrNotNull(tc, mtime1);
+
+ /* Tickle /etc/hosts behind augeas' back */
+ r = asprintf(&hosts, "%setc/hosts", build_root);
+ CuAssertPositive(tc, r);
+
+ fp = fopen(hosts, "a");
+ CuAssertPtrNotNull(tc, fp);
+
+ r = fprintf(fp, "192.168.0.1 other.example.com\n");
+ CuAssertTrue(tc, r > 0);
+
+ r = fclose(fp);
+ CuAssertRetSuccess(tc, r);
+
+ /* Unsaved changes are discarded */
+ r = aug_set(aug, "/files/etc/hosts/1/ipaddr", "127.0.0.2");
+ CuAssertRetSuccess(tc, r);
+
+ /* Check that we really did load the right file*/
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_get(aug, "/augeas/files/etc/hosts/mtime", &mtime2);
+ CuAssertIntEquals(tc, 1, r);
+ CuAssertStrNotEqual(tc, mtime1, mtime2);
+
+ r = aug_match(aug, "/files/etc/hosts/*[ipaddr = '192.168.0.1']", NULL);
+ CuAssertIntEquals(tc, 1, r);
+
+ r = aug_match(aug, "/files/etc/hosts/1[ipaddr = '127.0.0.1']", NULL);
+ CuAssertIntEquals(tc, 1, r);
+
+ free(mtime1);
+ free(hosts);
+ aug_close(aug);
+}
+
+static void testReloadDirty(CuTest *tc) {
+ augeas *aug = NULL;
+ int r;
+
+ aug = setup_writable_hosts(tc);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ /* Unsaved changes are discarded */
+ r = aug_set(aug, "/files/etc/hosts/1/ipaddr", "127.0.0.2");
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_match(aug, "/files/etc/hosts/1[ipaddr = '127.0.0.1']", NULL);
+ CuAssertIntEquals(tc, 1, r);
+
+ aug_close(aug);
+}
+
+static void testReloadDeleted(CuTest *tc) {
+ augeas *aug = NULL;
+ int r;
+
+ aug = setup_writable_hosts(tc);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ /* A missing file causes a reload */
+ r = aug_rm(aug, "/files/etc/hosts");
+ CuAssertPositive(tc, r);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_match(aug, "/files/etc/hosts/1[ipaddr = '127.0.0.1']", NULL);
+ CuAssertIntEquals(tc, 1, r);
+
+ /* A missing entry in a file causes a reload */
+ r = aug_rm(aug, "/files/etc/hosts/1/ipaddr");
+ CuAssertPositive(tc, r);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_match(aug, "/files/etc/hosts/1[ipaddr = '127.0.0.1']", NULL);
+ CuAssertIntEquals(tc, 1, r);
+
+ aug_close(aug);
+}
+
+static void testReloadDeletedMeta(CuTest *tc) {
+ augeas *aug = NULL;
+ int r;
+
+ aug = setup_writable_hosts(tc);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ /* Unsaved changes are discarded */
+ r = aug_rm(aug, "/augeas/files/etc/hosts");
+ CuAssertPositive(tc, r);
+
+ r = aug_set(aug, "/files/etc/hosts/1/ipaddr", "127.0.0.2");
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_load(aug);
+ CuAssertRetSuccess(tc, r);
+
+ r = aug_match(aug, "/files/etc/hosts/1[ipaddr = '127.0.0.1']", NULL);
+ CuAssertIntEquals(tc, 1, r);
+
+ aug_close(aug);
+}
+
int main(void) {
char *output = NULL;
CuSuite* suite = CuSuiteNew();
@@ -274,6 +412,10 @@ int main(void) {
SUITE_ADD_TEST(suite, testLoadSave);
SUITE_ADD_TEST(suite, testLoadDefined);
SUITE_ADD_TEST(suite, testDefvarExpr);
+ SUITE_ADD_TEST(suite, testReloadChanged);
+ SUITE_ADD_TEST(suite, testReloadDirty);
+ SUITE_ADD_TEST(suite, testReloadDeleted);
+ SUITE_ADD_TEST(suite, testReloadDeletedMeta);
abs_top_srcdir = getenv("abs_top_srcdir");
if (abs_top_srcdir == NULL)
diff --git a/tests/xpath.tests b/tests/xpath.tests
index f2575a3..b16792a 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -148,6 +148,7 @@ test ipaddr-sibling //*[../ipaddr]
test lircd-ancestor //*[ancestor::kudzu][label() != '#comment']
/augeas/files/etc/sysconfig/kudzu/path = /files/etc/sysconfig/kudzu
+ /augeas/files/etc/sysconfig/kudzu/mtime = ...
/augeas/files/etc/sysconfig/kudzu/lens = @Shellvars
/augeas/files/etc/sysconfig/kudzu/lens/info = ...
/files/etc/sysconfig/kudzu/SAFE = no
--
1.6.6.1

View File

@ -1,2 +1 @@
0fe232b7f37a6e468e81019895fd01f4 augeas-0.7.2.tar.gz
d907943fc21c2d1db5dc8d97ec02a9e5 augeas-0.7.3.tar.gz d907943fc21c2d1db5dc8d97ec02a9e5 augeas-0.7.3.tar.gz

View File

@ -1,19 +0,0 @@
From 81552d12ea1d6fc19ccb9a7d7e57ff09af74ce60 Mon Sep 17 00:00:00 2001
From: David Lutterkort <lutter@redhat.com>
Date: Mon, 14 Dec 2009 14:38:11 -0800
Subject: [PATCH] * doc/ftdetect/augeas.vim: fix syntax
---
doc/ftdetect/augeas.vim | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/doc/ftdetect/augeas.vim b/doc/ftdetect/augeas.vim
index 2520eb8..7120691 100644
--- a/doc/ftdetect/augeas.vim
+++ b/doc/ftdetect/augeas.vim
@@ -1 +1 @@
-au BufNewFile?,BufRead? *.aug set filetype=augeas
+au BufNewFile,BufRead *.aug set filetype=augeas
--
1.6.5.2

293
xorg.aug
View File

@ -1,293 +0,0 @@
(*
Module: Xorg
Parses /etc/X11/xorg.conf
Authors: Raphael Pinson <raphink@gmail.com>
Matthew Booth <mbooth@redhat.com>
About: Reference
This lens tries to keep as close as possible to `man xorg.conf` where
possible.
The definitions from `man xorg.conf` are put as commentaries for reference
throughout the file. More information can be found in the manual.
About: License
This file is licensed under the GPL.
About: Lens Usage
Sample usage of this lens in augtool
* Get the identifier of the devices with a "Clone" option:
> match "/files/etc/X11/xorg.conf/Device[Option = 'Clone']/Identifier"
About: Configuration files
This lens applies to /etc/X11/xorg.conf. See <filter>.
*)
module Xorg =
autoload xfm
(************************************************************************
* Group: USEFUL PRIMITIVES
*************************************************************************)
(* Group: Generic primitives *)
(* Variable: eol *)
let eol = Util.eol
(* Variable: to_eol
* Match everything from here to eol, cropping whitespace at both ends
*)
let to_eol = /[^ \t\n](.*[^ \t\n])?/
(* Variable: indent *)
let indent = Util.indent
(* Variable: comment *)
let comment = Util.comment
(* Variable: empty *)
let empty = Util.empty
(* Group: Separators *)
(* Variable: sep_spc *)
let sep_spc = Util.del_ws_spc
(* Variable: sep_dquote *)
let sep_dquote = Util.del_str "\""
(* Group: Fields and values *)
(* Variable: entries_re
* This is a list of all patterns which have specific handlers, and should
* therefore not be matched by the generic handler
*)
let entries_re = /([oO]ption|[sS]creen|[iI]nput[dD]evice|[dD]river|[sS]ub[sS]ection|[dD]isplay|[iI]dentifier|[vV]ideo[rR]am|[dD]efault[dD]epth|[dD]evice)/
(* Variable: generic_entry_re *)
let generic_entry_re = /[^# \t\n\/]+/ - entries_re
(* Variable: quoted_string_val *)
let quoted_string_val = del "\"" "\"" . store /[^"\n]+/ . del "\"" "\""
(* " relax, emacs *)
(* Variable: int *)
let int = /[0-9]+/
(************************************************************************
* Group: ENTRIES AND OPTIONS
*************************************************************************)
(* View: entry_int
* This matches an entry which takes a single integer for an argument
*)
let entry_int (canon:string) (re:regexp) =
[ indent . del re canon . label canon . sep_spc . store int . eol ]
(* View: entry_rgb
* This matches an entry which takes 3 integers as arguments representing red,
* green and blue components
*)
let entry_rgb (canon:string) (re:regexp) =
[ indent . del re canon . label canon
. [ label "red" . sep_spc . store int ]
. [ label "green" . sep_spc . store int ]
. [ label "blue" . sep_spc . store int ]
. eol ]
(* View: entry_xy
* This matches an entry which takes 2 integers as arguments representing X and
* Y coordinates
*)
let entry_xy (canon:string) (re:regexp) =
[ indent . del re canon . label canon
. [ label "x" . sep_spc . store int ]
. [ label "y" . sep_spc . store int ]
. eol ]
(* View: entry_str
* This matches an entry which takes a single quoted string
*)
let entry_str (canon:string) (re:regexp) =
[ indent . del re canon . label canon
. sep_spc . quoted_string_val . eol ]
(* View: entry_generic
* An entry without a specific handler. Store everything after the keyword,
* cropping whitespace at both ends.
*)
let entry_generic = [ indent . key generic_entry_re
. sep_spc . store to_eol . eol ]
(* View: option *)
let option = [ indent . del /[oO]ption/ "Option" . label "Option" . sep_spc
. quoted_string_val
. [ label "value" . sep_spc . quoted_string_val ]*
. eol ]
(* View: screen
* The Screen entry of ServerLayout
*)
let screen = [ indent . del /[sS]creen/ "Screen" . label "Screen" . sep_spc
. [ label "num" . store int . sep_spc ]?
. quoted_string_val . sep_spc
. [ label "position" . store to_eol ]
. eol ]
(* View: input_device *)
let input_device = [ indent . del /[iI]nput[dD]evice/ "InputDevice"
. label "InputDevice" . sep_spc . quoted_string_val
. [ label "option" . sep_spc . quoted_string_val ]*
. eol ]
(* View: driver *)
let driver = entry_str "Driver" /[dD]river/
(* View: identifier *)
let identifier = entry_str "Identifier" /[iI]dentifier/
(* View: videoram *)
let videoram = entry_int "VideoRam" /[vV]ideo[rR]am/
(* View: default_depth *)
let default_depth = entry_int "DefaultDepth" /[dD]efault[dD]epth/
(* View: device *)
let device = entry_str "Device" /[dD]evice/
(************************************************************************
* Group: DISPLAY SUBSECTION
*************************************************************************)
(* View: display_modes *)
let display_modes = [ indent . del /[mM]odes/ "Modes" . label "Modes"
. [ label "mode" . sep_spc . quoted_string_val ]+
. eol ]
(*************************************************************************
* View: display_entry
* Known values for entries in the Display subsection
*
* Definition:
* > Depth depth
* > FbBpp bpp
* > Weight red-weight green-weight blue-weight
* > Virtual xdim ydim
* > ViewPort x0 y0
* > Modes "mode-name" ...
* > Visual "visual-name"
* > Black red green blue
* > White red green blue
* > Options
*)
let display_entry = entry_int "Depth" /[dD]epth/ |
entry_int "FbBpp" /[fF]b[bB]pp/ |
entry_rgb "Weight" /[wW]eight/ |
entry_xy "Virtual" /[vV]irtual/ |
entry_xy "ViewPort" /[vV]iew[pP]ort/ |
display_modes |
entry_str "Visual" /[vV]isual/ |
entry_rgb "Black" /[bB]lack/ |
entry_rgb "White" /[wW]hite/ |
entry_str "Options" /[oO]ptions/ |
empty |
comment
(* View: display *)
let display = [ indent . del "SubSection" "SubSection" . sep_spc
. sep_dquote . key "Display" . sep_dquote
. eol
. display_entry*
. indent . del "EndSubSection" "EndSubSection" . eol ]
(************************************************************************
* Group: SECTIONS
*************************************************************************)
(************************************************************************
* Variable: section_re
* Known values for Section names
*
* Definition:
* > The section names are:
* >
* > Files File pathnames
* > ServerFlags Server flags
* > Module Dynamic module loading
* > InputDevice Input device description
* > Device Graphics device description
* > VideoAdaptor Xv video adaptor description
* > Monitor Monitor description
* > Modes Video modes descriptions
* > Screen Screen configuration
* > ServerLayout Overall layout
* > DRI DRI-specific configuration
* > Vendor Vendor-specific configuration
*************************************************************************)
let section_re = /(Files|ServerFlags|Module|InputDevice|Device|VideoAdaptor|Monitor|Modes|Screen|ServerLayout|DRI|Vendor)/
(************************************************************************
* Variable: secton_re_obsolete
* The following obsolete section names are still recognised for
* compatibility purposes. In new config files, the InputDevice
* section should be used instead.
*
* Definition:
* > Keyboard Keyboard configuration
* > Pointer Pointer/mouse configuration
*************************************************************************)
let section_re_obsolete = /(Keyboard|Pointer)/
(* View: section_entry *)
let section_entry = option |
screen |
display |
input_device |
driver |
identifier |
videoram |
default_depth |
device |
entry_generic |
empty | comment
(************************************************************************
* View: section
* A section in xorg.conf
*
* Definition:
* > Section "SectionName"
* > SectionEntry
* > ...
* > EndSection
*************************************************************************)
let section = [ indent . del "Section" "Section"
. sep_spc . sep_dquote
. key (section_re|section_re_obsolete) . sep_dquote
. eol
. section_entry*
. indent . del "EndSection" "EndSection" . eol ]
(*
* View: lns
* The xorg.conf lens
*)
let lns = ( empty | comment | section )*
(* Variable: filter *)
let filter = (incl "/etc/X11/xorg.conf")
let xfm = transform lns filter