diff options
author | Mark McLoughlin <mark@skynet.ie> | 2004-06-22 11:43:47 +0000 |
---|---|---|
committer | Mark McLoughlin <markmc@src.gnome.org> | 2004-06-22 11:43:47 +0000 |
commit | 2bb792de417e79185dcbd3d8f3255d64c2aeee18 (patch) | |
tree | 98184f7e556fe3a68e3ef28bf288a0870f49f5fd /backends | |
parent | 28d07e279a98eb0e2bae93fe3fe732344e539347 (diff) | |
download | gconf-2bb792de417e79185dcbd3d8f3255d64c2aeee18.tar.gz |
Fix for bug #138498 - turn on "subtree-in-a-file" for the subdirectories
2004-06-21 Mark McLoughlin <mark@skynet.ie>
Fix for bug #138498 - turn on "subtree-in-a-file" for the
subdirectories of the following directories:
/apps/evolution",
/apps/panel/profiles",
/apps
/desktop/gnome
/system
/schemas/apps
/schemas/desktop/gnome
/schemas/system
/schemas
/
You can turn this of by passing the "nomerge" flag to the
backend - e.g. xml:readwrite,nomerge:$(HOME)/.gconf
* backends/markup-tree.[ch]:
(markup_tree_get): pass in the nomerge path.
(markup_dir_build_file_path),
(markup_dir_build_dir_path): simple wrappers for build_path().
(load_subtree), (load_entries), (load_subdirs),
(delete_useless_subdirs): upd. for above change.
(recursively_load_subtree): impl. recursively loading the tree
below a given dir.
(should_save_as_subtree): logic to figure out which dirs should
be saved as merged files.
(markup_dir_sync): save the dir in a merged file if neccessary.
(markup_dir_build_path): allow building a non-filesystem path.
(parse_tree), (save_tree): upd.
(write_dir): set the "not_in_filesystem" flag.
* backends/markup-backend.c:
(resolve_address), (ms_new): parse and use the "nomerge" flag.
* backends/gconf-merge-tree.c: (merge_tree): upd.
Diffstat (limited to 'backends')
-rw-r--r-- | backends/gconf-merge-tree.c | 25 | ||||
-rw-r--r-- | backends/markup-backend.c | 21 | ||||
-rw-r--r-- | backends/markup-tree.c | 153 | ||||
-rw-r--r-- | backends/markup-tree.h | 3 |
4 files changed, 162 insertions, 40 deletions
diff --git a/backends/gconf-merge-tree.c b/backends/gconf-merge-tree.c index 759eb376..fff83797 100644 --- a/backends/gconf-merge-tree.c +++ b/backends/gconf-merge-tree.c @@ -39,25 +39,6 @@ _gconf_mode_t_to_mode (mode_t orig) return mode; } -static void -recursively_load_entire_tree (MarkupDir *dir) -{ - GSList *tmp; - - load_entries (dir); - load_subdirs (dir); - - tmp = dir->subdirs; - while (tmp != NULL) - { - MarkupDir *subdir = tmp->data; - - recursively_load_entire_tree (subdir); - - tmp = tmp->next; - } -} - static gboolean merge_tree (const char *root_dir) { @@ -80,9 +61,9 @@ merge_tree (const char *root_dir) } - tree = markup_tree_get (root_dir, dir_mode, file_mode); + tree = markup_tree_get (root_dir, dir_mode, file_mode, FALSE); - recursively_load_entire_tree (tree->root); + recursively_load_subtree (tree->root); error = NULL; save_tree (tree->root, TRUE, file_mode, &error); @@ -90,7 +71,7 @@ merge_tree (const char *root_dir) { char *markup_file; - markup_file = markup_dir_build_path (tree->root, TRUE, TRUE); + markup_file = markup_dir_build_file_path (tree->root, TRUE); fprintf (stderr, _("Error saving GConf tree to '%s': %s\n"), markup_file, error->message); diff --git a/backends/markup-backend.c b/backends/markup-backend.c index cc4401d1..c94253ad 100644 --- a/backends/markup-backend.c +++ b/backends/markup-backend.c @@ -65,11 +65,13 @@ typedef struct MarkupTree *tree; guint dir_mode; guint file_mode; + guint try_merge : 1; } MarkupSource; static MarkupSource* ms_new (const char *root_dir, guint dir_mode, guint file_mode, + gboolean try_merge, GConfLock *lock); static void ms_destroy (MarkupSource *source); @@ -262,6 +264,7 @@ resolve_address (const char *address, char** address_flags; char** iter; gboolean force_readonly; + gboolean try_merge; root_dir = get_dir_from_address (address, err); if (root_dir == NULL) @@ -286,6 +289,7 @@ resolve_address (const char *address, } force_readonly = FALSE; + try_merge = TRUE; address_flags = gconf_address_flags (address); if (address_flags) @@ -296,7 +300,10 @@ resolve_address (const char *address, if (strcmp (*iter, "readonly") == 0) { force_readonly = TRUE; - break; + } + else if (strcmp (*iter, "nomerge") == 0) + { + try_merge = FALSE; } ++iter; @@ -386,9 +393,12 @@ resolve_address (const char *address, return NULL; } + if (try_merge && !(flags & GCONF_SOURCE_ALL_WRITEABLE)) + try_merge = FALSE; + /* Create the new source */ - xsource = ms_new (root_dir, dir_mode, file_mode, lock); + xsource = ms_new (root_dir, dir_mode, file_mode, try_merge, lock); gconf_log (GCL_DEBUG, _("Directory/file permissions for XML source at root %s are: %o/%o"), @@ -891,6 +901,7 @@ static MarkupSource* ms_new (const char* root_dir, guint dir_mode, guint file_mode, + gboolean try_merge, GConfLock *lock) { MarkupSource* ms; @@ -909,8 +920,12 @@ ms_new (const char* root_dir, ms->dir_mode = dir_mode; ms->file_mode = file_mode; + ms->try_merge = try_merge; - ms->tree = markup_tree_get (ms->root_dir, ms->dir_mode, ms->file_mode); + ms->tree = markup_tree_get (ms->root_dir, + ms->dir_mode, + ms->file_mode, + ms->try_merge); return ms; } diff --git a/backends/markup-tree.c b/backends/markup-tree.c index 7527f00c..3f1b3aeb 100644 --- a/backends/markup-tree.c +++ b/backends/markup-tree.c @@ -63,8 +63,9 @@ static void markup_dir_free (MarkupDir *dir); static gboolean markup_dir_needs_sync (MarkupDir *dir); static gboolean markup_dir_sync (MarkupDir *dir); static char* markup_dir_build_path (MarkupDir *dir, - gboolean with_data_file, - gboolean subtree_data_file); + gboolean filesystem_path, + gboolean with_data_file, + gboolean subtree_data_file); static void markup_dir_set_entries_need_save (MarkupDir *dir); static MarkupEntry* markup_entry_new (MarkupDir *dir, @@ -89,14 +90,34 @@ struct _MarkupTree MarkupDir *root; guint refcount; + + guint try_merge : 1; }; static GHashTable *trees_by_root_dir = NULL; +/* List of dirs whose subdirs should be saved as a + * subtree-in-a-file. The order is important. + */ +static const char *save_as_subtree_dirs[] = +{ + "/apps/evolution", + "/apps/panel/profiles", + "/apps", + "/desktop/gnome", + "/system" + "/schemas/apps", + "/schemas/desktop/gnome", + "/schemas/system", + "/schemas", + "/" +}; + MarkupTree* markup_tree_get (const char *root_dir, guint dir_mode, - guint file_mode) + guint file_mode, + gboolean try_merge) { MarkupTree *tree = NULL; @@ -116,6 +137,7 @@ markup_tree_get (const char *root_dir, tree->dirname = g_strdup (root_dir); tree->dir_mode = dir_mode; tree->file_mode = file_mode; + tree->try_merge = try_merge != FALSE; tree->root = markup_dir_new (tree, NULL, "/"); @@ -258,6 +280,20 @@ markup_dir_queue_sync (MarkupDir *dir) } } +static inline char * +markup_dir_build_file_path (MarkupDir *dir, + gboolean subtree_data_file) +{ + return markup_dir_build_path (dir, TRUE, TRUE, subtree_data_file); +} + +static inline char * +markup_dir_build_dir_path (MarkupDir *dir, + gboolean filesystem_path) +{ + return markup_dir_build_path (dir, filesystem_path, FALSE, FALSE); +} + static MarkupDir* markup_tree_get_dir_internal (MarkupTree *tree, const char *full_key, @@ -361,7 +397,7 @@ load_subtree (MarkupDir *dir) GError *tmp_err = NULL; char *markup_file; - markup_file = markup_dir_build_path (dir, TRUE, TRUE); + markup_file = markup_dir_build_file_path (dir, TRUE); if (!gconf_file_exists (markup_file)) { g_free (markup_file); @@ -427,7 +463,7 @@ load_entries (MarkupDir *dir) /* this message is debug-only because it usually happens * when creating a new directory */ - markup_file = markup_dir_build_path (dir, TRUE, FALSE); + markup_file = markup_dir_build_file_path (dir, FALSE); gconf_log (GCL_DEBUG, "Failed to load file \"%s\": %s", markup_file, tmp_err->message); @@ -467,7 +503,7 @@ load_subdirs (MarkupDir *dir) if (load_subtree (dir)) return TRUE; - markup_dir = markup_dir_build_path (dir, FALSE, FALSE); + markup_dir = markup_dir_build_dir_path (dir, TRUE); dp = opendir (markup_dir); @@ -786,8 +822,8 @@ delete_useless_subdirs (MarkupDir *dir) char *fs_dirname; char *fs_filename; - fs_dirname = markup_dir_build_path (subdir, FALSE, FALSE); - fs_filename = markup_dir_build_path (subdir, TRUE, dir->save_as_subtree); + fs_dirname = markup_dir_build_dir_path (subdir, TRUE); + fs_filename = markup_dir_build_file_path (subdir, dir->save_as_subtree); if (unlink (fs_filename) < 0) { @@ -887,6 +923,80 @@ delete_useless_entries (MarkupDir *dir) return some_deleted; } +static void +recursively_load_subtree (MarkupDir *dir) +{ + GSList *tmp; + + load_entries (dir); + load_subdirs (dir); + + tmp = dir->subdirs; + while (tmp != NULL) + { + MarkupDir *subdir = tmp->data; + + recursively_load_subtree (subdir); + + tmp = tmp->next; + } +} + +static gboolean +should_save_as_subtree (MarkupDir *dir) +{ + gboolean save_as_subtree = FALSE; + char *dir_path; + char *parent_path; + int pathlen; + int i; + + if (!dir->tree->try_merge) + return FALSE; + + /* never merge root */ + if (!dir->parent) + return FALSE; + + dir_path = markup_dir_build_dir_path (dir, FALSE); + pathlen = strlen (dir_path); + + parent_path = markup_dir_build_dir_path (dir->parent, FALSE); + + i = 0; + while (i < G_N_ELEMENTS (save_as_subtree_dirs)) + { + const char *match = save_as_subtree_dirs [i]; + + /* 2 rules: + * 1) If @match is an ancestor of this dir, don't + * consider merging this dir + * 2) If @match is this dir's parent, then merge + * this dir + * + * (1) is so that we don't e.g., with "/apps" and + * "/apps/panel/profiles", merge /apps/panel when + * we really want to merge /apps/panel/profiles/default + */ + + if (strncmp (match, dir_path, pathlen) == 0) + break; + + if (strcmp (match, parent_path) == 0) + { + save_as_subtree = TRUE; + break; + } + + ++i; + } + + g_free (dir_path); + g_free (parent_path); + + return save_as_subtree; +} + static gboolean markup_dir_sync (MarkupDir *dir) { @@ -918,10 +1028,16 @@ markup_dir_sync (MarkupDir *dir) tmp = tmp->next; } + + if (!dir->save_as_subtree && should_save_as_subtree (dir)) + { + dir->save_as_subtree = TRUE; + recursively_load_subtree (dir); + } - fs_dirname = markup_dir_build_path (dir, FALSE, FALSE); - fs_filename = markup_dir_build_path (dir, TRUE, FALSE); - fs_subtree = markup_dir_build_path (dir, TRUE, TRUE); + fs_dirname = markup_dir_build_dir_path (dir, TRUE); + fs_filename = markup_dir_build_file_path (dir, FALSE); + fs_subtree = markup_dir_build_file_path (dir, TRUE); /* For a dir to be loaded as a subdir, it must have a * %gconf.xml file, even if it has no entries in that @@ -1051,6 +1167,7 @@ markup_dir_sync (MarkupDir *dir) static char* markup_dir_build_path (MarkupDir *dir, + gboolean filesystem_path, gboolean with_data_file, gboolean subtree_data_file) { @@ -1059,6 +1176,8 @@ markup_dir_build_path (MarkupDir *dir, GSList *tmp; MarkupDir *iter; + g_assert (filesystem_path || !with_data_file); + components = NULL; iter = dir; while (iter->parent != NULL) /* exclude root dir */ @@ -1067,7 +1186,11 @@ markup_dir_build_path (MarkupDir *dir, iter = iter->parent; } - name = g_string_new (dir->tree->dirname); + if (filesystem_path) + name = g_string_new (dir->tree->dirname); + else + name = g_string_new (components ? NULL : "/"); + tmp = components; while (tmp != NULL) { @@ -3072,7 +3195,7 @@ parse_tree (MarkupDir *root, char *text; gsize length; - filename = markup_dir_build_path (root, TRUE, parse_subtree); + filename = markup_dir_build_file_path (root, parse_subtree); parse_info_init (&info, root, parse_subtree); @@ -3570,6 +3693,8 @@ write_dir (MarkupDir *dir, gboolean retval = FALSE; char *whitespace; + dir->not_in_filesystem = TRUE; + /* This dir will be deleted from the * MarkupTree after syncing anyway ... */ @@ -3639,7 +3764,7 @@ save_tree (MarkupDir *dir, new_fd = -1; f = NULL; - filename = markup_dir_build_path (dir, TRUE, save_as_subtree); + filename = markup_dir_build_file_path (dir, save_as_subtree); new_filename = g_strconcat (filename, ".new", NULL); new_fd = open (new_filename, O_WRONLY | O_CREAT, file_mode); diff --git a/backends/markup-tree.h b/backends/markup-tree.h index a6bf566e..47d7dd99 100644 --- a/backends/markup-tree.h +++ b/backends/markup-tree.h @@ -31,7 +31,8 @@ typedef struct _MarkupEntry MarkupEntry; MarkupTree* markup_tree_get (const char *root_dir, guint dir_mode, - guint file_mode); + guint file_mode, + gboolean try_merge); void markup_tree_unref (MarkupTree *tree); void markup_tree_rebuild (MarkupTree *tree); MarkupDir* markup_tree_lookup_dir (MarkupTree *tree, |