summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <withnall@endlessm.com>2018-12-13 16:55:48 +0000
committerPhilip Withnall <withnall@endlessm.com>2018-12-17 17:16:04 +0000
commitb06fa34bb1cb3eb33bae819ebedd1689b3c29f0f (patch)
treef29eb2b6b0635c10c32201cddce78bdaff8df7f9
parentdf2f13f89b36b5095d3e3e70c610aa5408a4e522 (diff)
downloadglib-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.c153
-rw-r--r--gio/gcontenttype.h6
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__ */