diff options
author | Philip Withnall <withnall@endlessm.com> | 2018-12-13 16:55:48 +0000 |
---|---|---|
committer | Philip Withnall <withnall@endlessm.com> | 2018-12-17 17:16:04 +0000 |
commit | b06fa34bb1cb3eb33bae819ebedd1689b3c29f0f (patch) | |
tree | f29eb2b6b0635c10c32201cddce78bdaff8df7f9 | |
parent | df2f13f89b36b5095d3e3e70c610aa5408a4e522 (diff) | |
download | glib-b06fa34bb1cb3eb33bae819ebedd1689b3c29f0f.tar.gz |
gcontenttype: Add g_content_type_{get,set}_mime_dirs() API
This allows the list of directories which contain MIME data to be set,
separately from the list of directories returned by
g_get_user_data_home() and g_get_system_data_dirs().
While the latter are overridden for a unit test, we don’t have access to
the system MIME registry, which can sometimes be useful for tests which
need to know about standard MIME associations from shared-mime-info.
Allow g_content_type_set_mime_dirs() to be used from unit tests to allow
them to use the system MIME registry again, or to allow them to be
pointed to another custom registry.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
-rw-r--r-- | gio/gcontenttype.c | 153 | ||||
-rw-r--r-- | gio/gcontenttype.h | 6 |
2 files changed, 129 insertions, 30 deletions
diff --git a/gio/gcontenttype.c b/gio/gcontenttype.c index 60228e935..c34349575 100644 --- a/gio/gcontenttype.c +++ b/gio/gcontenttype.c @@ -55,6 +55,8 @@ #define XDG_PREFIX _gio_xdg #include "xdgmime/xdgmime.h" +static void tree_magic_schedule_reload (void); + /* We lock this mutex whenever we modify global state in this module. */ G_LOCK_DEFINE_STATIC (gio_xdgmime); @@ -111,6 +113,106 @@ _g_unix_content_type_get_parents (const gchar *type) return (gchar **)g_ptr_array_free (array, FALSE); } +G_LOCK_DEFINE_STATIC (global_mime_dirs); +static gchar **global_mime_dirs = NULL; + +static void +_g_content_type_set_mime_dirs_locked (const char * const *dirs) +{ + g_clear_pointer (&global_mime_dirs, g_strfreev); + + if (dirs != NULL) + { + global_mime_dirs = g_strdupv ((gchar **) dirs); + } + else + { + GPtrArray *mime_dirs = g_ptr_array_new_with_free_func (g_free); + const gchar * const *system_dirs = g_get_system_data_dirs (); + + g_ptr_array_add (mime_dirs, g_build_filename (g_get_user_data_dir (), "mime", NULL)); + for (; *system_dirs != NULL; system_dirs++) + g_ptr_array_add (mime_dirs, g_build_filename (*system_dirs, "mime", NULL)); + g_ptr_array_add (mime_dirs, NULL); /* NULL terminator */ + + global_mime_dirs = (gchar **) g_ptr_array_free (mime_dirs, FALSE); + } + + xdg_mime_set_dirs ((const gchar * const *) global_mime_dirs); + tree_magic_schedule_reload (); +} + +/** + * g_content_type_set_mime_dirs: + * @dirs: (array zero-terminated=1) (nullable): %NULL-terminated list of + * directories to load MIME data from, including any `mime/` subdirectory, + * and with the first directory to try listed first + * + * Set the list of directories used by GIO to load the MIME database. + * If @dirs is %NULL, the directories used are the default: + * + * - the `mime` subdirectory of the directory in `$XDG_DATA_HOME` + * - the `mime` subdirectory of every directory in `$XDG_DATA_DIRS` + * + * This function is intended to be used when writing tests that depend on + * information stored in the MIME database, in order to control the data. + * + * Typically, in case your tests use %G_TEST_OPTION_ISOLATE_DIRS, but they + * depend on the system’s MIME database, you should call this function + * with @dirs set to %NULL before calling g_test_init(), for instance: + * + * |[<!-- language="C" --> + * // Load MIME data from the system + * g_content_type_set_mime_dirs (NULL); + * // Isolate the environment + * g_test_init (&argc, &argv, G_TEST_OPTION_ISOLATE_DIRS, NULL); + * + * … + * + * return g_test_run (); + * ]| + * + * Since: 2.60 + */ +/*< private >*/ +void +g_content_type_set_mime_dirs (const gchar * const *dirs) +{ + G_LOCK (global_mime_dirs); + _g_content_type_set_mime_dirs_locked (dirs); + G_UNLOCK (global_mime_dirs); +} + +/** + * g_content_type_get_mime_dirs: + * + * Get the list of directories which MIME data is loaded from. See + * g_content_type_set_mime_dirs() for details. + * + * Returns: (transfer none) (array zero-terminated=1): %NULL-terminated list of + * directories to load MIME data from, including any `mime/` subdirectory, + * and with the first directory to try listed first + * Since: 2.60 + */ +/*< private >*/ +const gchar * const * +g_content_type_get_mime_dirs (void) +{ + const gchar * const *mime_dirs; + + G_LOCK (global_mime_dirs); + + if (global_mime_dirs == NULL) + _g_content_type_set_mime_dirs_locked (NULL); + + mime_dirs = (const gchar * const *) global_mime_dirs; + + G_UNLOCK (global_mime_dirs); + + g_assert (mime_dirs != NULL); + return mime_dirs; +} + /** * g_content_type_equals: * @type1: a content type string @@ -306,7 +408,7 @@ load_comment_for_mime_helper (const char *dir, mime_info_text }; - filename = g_build_filename (dir, "mime", basename, NULL); + filename = g_build_filename (dir, basename, NULL); res = g_file_get_contents (filename, &data, &len, NULL); g_free (filename); @@ -328,22 +430,14 @@ load_comment_for_mime_helper (const char *dir, static char * load_comment_for_mime (const char *mimetype) { - const char * const* dirs; + const char * const *dirs; char *basename; char *comment; - int i; + gsize i; basename = g_strdup_printf ("%s.xml", mimetype); - comment = load_comment_for_mime_helper (g_get_user_data_dir (), basename); - if (comment) - { - g_free (basename); - return comment; - } - - dirs = g_get_system_data_dirs (); - + dirs = g_content_type_get_mime_dirs (); for (i = 0; dirs[i] != NULL; i++) { comment = load_comment_for_mime_helper (dirs[i], basename); @@ -780,10 +874,10 @@ enumerate_mimetypes_dir (const char *dir, { DIR *d; struct dirent *ent; - char *mimedir; + const char *mimedir; char *name; - mimedir = g_build_filename (dir, "mime", NULL); + mimedir = dir; d = opendir (mimedir); if (d) @@ -800,8 +894,6 @@ enumerate_mimetypes_dir (const char *dir, } closedir (d); } - - g_free (mimedir); } /** @@ -817,18 +909,16 @@ enumerate_mimetypes_dir (const char *dir, GList * g_content_types_get_registered (void) { - const char * const* dirs; + const char * const *dirs; GHashTable *mimetypes; GHashTableIter iter; gpointer key; - int i; + gsize i; GList *l; mimetypes = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); - enumerate_mimetypes_dir (g_get_user_data_dir (), mimetypes); - dirs = g_get_system_data_dirs (); - + dirs = g_content_type_get_mime_dirs (); for (i = 0; dirs[i] != NULL; i++) enumerate_mimetypes_dir (dirs[i], mimetypes); @@ -1030,7 +1120,7 @@ read_tree_magic_from_directory (const gchar *prefix) TreeMatchlet *matchlet; gint depth; - filename = g_build_filename (prefix, "mime", "treemagic", NULL); + filename = g_build_filename (prefix, "treemagic", NULL); if (g_file_get_contents (filename, &text, &len, NULL)) { @@ -1068,11 +1158,16 @@ read_tree_magic_from_directory (const gchar *prefix) g_free (filename); } +static void +tree_magic_schedule_reload (void) +{ + need_reload = TRUE; +} static void xdg_mime_reload (void *user_data) { - need_reload = TRUE; + tree_magic_schedule_reload (); } static void @@ -1086,9 +1181,7 @@ static void tree_magic_init (void) { static gboolean initialized = FALSE; - const gchar *dir; - const gchar * const * dirs; - int i; + gsize i; if (!initialized) { @@ -1100,14 +1193,14 @@ tree_magic_init (void) if (need_reload) { + const char * const *dirs; + need_reload = FALSE; tree_magic_shutdown (); - dir = g_get_user_data_dir (); - read_tree_magic_from_directory (dir); - dirs = g_get_system_data_dirs (); - for (i = 0; dirs[i]; i++) + dirs = g_content_type_get_mime_dirs (); + for (i = 0; dirs[i] != NULL; i++) read_tree_magic_from_directory (dirs[i]); } } diff --git a/gio/gcontenttype.h b/gio/gcontenttype.h index d87672dd5..d970acbe1 100644 --- a/gio/gcontenttype.h +++ b/gio/gcontenttype.h @@ -69,6 +69,12 @@ gchar ** g_content_type_guess_for_tree (GFile *root); GLIB_AVAILABLE_IN_ALL GList * g_content_types_get_registered (void); +/*< private >*/ +GLIB_AVAILABLE_IN_2_60 +const gchar * const *g_content_type_get_mime_dirs (void); +GLIB_AVAILABLE_IN_2_60 +void g_content_type_set_mime_dirs (const gchar * const *dirs); + G_END_DECLS #endif /* __G_CONTENT_TYPE_H__ */ |