summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2013-10-04 20:05:21 -0400
committerRyan Lortie <desrt@desrt.ca>2013-10-04 20:05:21 -0400
commit1955e35da257eda68517765c3ad79ed801b58755 (patch)
tree68a457a39ff1c24a1430668dcebba21db1fae98f
parentc1624e02a41bab21e3496f2a3d26eb2d14a210ca (diff)
Split out the building of the mime cache
Create a new file for the code that builds the mime cache. We still do the actual write to disk from the main file, though.
-rw-r--r--src/Makefile.am2
-rw-r--r--src/mime-cache.c283
-rw-r--r--src/mime-cache.h30
-rw-r--r--src/update-desktop-database.c265
4 files changed, 318 insertions, 262 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 28c3444..3177660 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -31,6 +31,8 @@ desktop_file_install_SOURCES = \
update_desktop_database_SOURCES = \
mimeutils.c \
mimeutils.h \
+ mime-cache.c \
+ mime-cache.h \
update-desktop-database.c
desktop_file_validate_LDADD = $(DESKTOP_FILE_UTILS_LIBS)
diff --git a/src/mime-cache.c b/src/mime-cache.c
new file mode 100644
index 0000000..815f2e0
--- /dev/null
+++ b/src/mime-cache.c
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2004-2006 Red Hat, Inc.
+ * Copyright (C) 2006, 2008 Vincent Untz
+ * Copyright © 2013 Canonical Limited
+ *
+ * Program written by Ray Strode <rstrode@redhat.com>
+ * Vincent Untz <vuntz@gnome.org>
+ * Ryan Lortie <desrt@desrt.ca>
+ *
+ * update-desktop-database is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * update-desktop-database is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with update-desktop-database; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite
+ * 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <config.h>
+
+#include "mime-cache.h"
+
+#include <glib/gi18n.h>
+#include <glib.h>
+
+#include "keyfileutils.h"
+#include "mimeutils.h"
+
+static void
+list_free_deep (gpointer key, GList *l, gpointer data)
+{
+ g_list_foreach (l, (GFunc)g_free, NULL);
+ g_list_free (l);
+}
+
+static void
+cache_desktop_file (GHashTable *mime_types_map,
+ const char *desktop_file,
+ const char *mime_type,
+ GError **error)
+{
+ GList *desktop_files;
+
+ desktop_files = (GList *) g_hash_table_lookup (mime_types_map, mime_type);
+
+ /* do not add twice a desktop file mentioning the mime type more than once
+ * (no need to use g_list_find() because we cache all mime types registered
+ * by a desktop file before moving to another desktop file) */
+ if (desktop_files &&
+ strcmp (desktop_file, (const char *) desktop_files->data) == 0)
+ return;
+
+ desktop_files = g_list_prepend (desktop_files, g_strdup (desktop_file));
+ g_hash_table_insert (mime_types_map, g_strdup (mime_type), desktop_files);
+}
+
+
+static void
+process_desktop_file (GHashTable *mime_types_map,
+ const char *desktop_file,
+ const char *name,
+ GError **error)
+{
+ GError *load_error;
+ GKeyFile *keyfile;
+ char **mime_types;
+ int i;
+
+ keyfile = g_key_file_new ();
+
+ load_error = NULL;
+ g_key_file_load_from_file (keyfile, desktop_file,
+ G_KEY_FILE_NONE, &load_error);
+
+ if (load_error != NULL)
+ {
+ g_propagate_error (error, load_error);
+ return;
+ }
+
+ /* Hidden=true means that the .desktop file should be completely ignored */
+ if (g_key_file_get_boolean (keyfile, GROUP_DESKTOP_ENTRY, "Hidden", NULL))
+ {
+ g_key_file_free (keyfile);
+ return;
+ }
+
+ mime_types = g_key_file_get_string_list (keyfile,
+ GROUP_DESKTOP_ENTRY,
+ "MimeType", NULL, &load_error);
+
+ g_key_file_free (keyfile);
+
+ if (load_error != NULL)
+ {
+ g_propagate_error (error, load_error);
+ return;
+ }
+
+ for (i = 0; mime_types[i] != NULL; i++)
+ {
+ char *mime_type;
+ MimeUtilsValidity valid;
+ char *valid_error;
+
+ mime_type = g_strchomp (mime_types[i]);
+ valid = mu_mime_type_is_valid (mime_types[i], &valid_error);
+ switch (valid)
+ {
+ case MU_VALID:
+ break;
+ case MU_DISCOURAGED:
+ g_warning (_("Warning in file \"%s\": usage of MIME type \"%s\" is "
+ "discouraged (%s)\n"),
+ desktop_file, mime_types[i], valid_error);
+ g_free (valid_error);
+ break;
+ case MU_INVALID:
+ g_warning (_("Error in file \"%s\": \"%s\" is an invalid MIME type "
+ "(%s)\n"),
+ desktop_file, mime_types[i], valid_error);
+ g_free (valid_error);
+ /* not a break: we continue to the next mime type */
+ continue;
+ default:
+ g_assert_not_reached ();
+ }
+
+ cache_desktop_file (mime_types_map, name, mime_type, &load_error);
+
+ if (load_error != NULL)
+ {
+ g_propagate_error (error, load_error);
+ g_strfreev (mime_types);
+ return;
+ }
+ }
+ g_strfreev (mime_types);
+}
+
+static void
+process_desktop_files (GHashTable *mime_types_map,
+ const char *desktop_dir,
+ const char *prefix,
+ GError **error)
+{
+ GError *process_error;
+ GDir *dir;
+ const char *filename;
+
+ process_error = NULL;
+ dir = g_dir_open (desktop_dir, 0, &process_error);
+
+ if (process_error != NULL)
+ {
+ g_propagate_error (error, process_error);
+ return;
+ }
+
+ while ((filename = g_dir_read_name (dir)) != NULL)
+ {
+ char *full_path, *name;
+
+ full_path = g_build_filename (desktop_dir, filename, NULL);
+
+ if (g_file_test (full_path, G_FILE_TEST_IS_DIR))
+ {
+ char *sub_prefix;
+
+ sub_prefix = g_strdup_printf ("%s%s-", prefix, filename);
+
+ process_desktop_files (mime_types_map, full_path, sub_prefix, &process_error);
+ g_free (sub_prefix);
+
+ if (process_error != NULL)
+ {
+ g_warning (_("Could not process directory \"%s\": %s\n"), full_path, process_error->message);
+ g_error_free (process_error);
+ process_error = NULL;
+ }
+ g_free (full_path);
+ continue;
+ }
+ else if (!g_str_has_suffix (filename, ".desktop"))
+ {
+ g_free (full_path);
+ continue;
+ }
+
+ name = g_strdup_printf ("%s%s", prefix, filename);
+ process_desktop_file (mime_types_map, full_path, name, &process_error);
+ g_free (name);
+
+ if (process_error != NULL)
+ {
+ if (!g_error_matches (process_error,
+ G_KEY_FILE_ERROR,
+ G_KEY_FILE_ERROR_KEY_NOT_FOUND))
+ {
+ g_warning (_("Could not parse file \"%s\": %s\n"), full_path, process_error->message);
+ }
+ else
+ {
+ g_debug (_("File \"%s\" lacks MimeType key\n"), full_path);
+ }
+
+ g_error_free (process_error);
+ process_error = NULL;
+ }
+
+ g_free (full_path);
+ }
+
+ g_dir_close (dir);
+}
+
+static void
+add_mime_type (const char *mime_type, GList *desktop_files, GString *str)
+{
+ GList *desktop_file;
+
+ g_string_append (str, mime_type);
+ g_string_append_c (str, '=');
+ for (desktop_file = desktop_files;
+ desktop_file != NULL;
+ desktop_file = desktop_file->next)
+ {
+ g_string_append (str, (const char *) desktop_file->data);
+ g_string_append_c (str, ';');
+ }
+ g_string_append_c (str, '\n');
+}
+
+GBytes *
+mime_cache_build (const char *desktop_dir,
+ GError **error)
+{
+ GHashTable *mime_types_map;
+ GError *update_error;
+ GList *keys, *key;
+ GString *contents;
+ GBytes *result;
+ gsize size;
+
+ result = NULL;
+
+ mime_types_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+ update_error = NULL;
+ process_desktop_files (mime_types_map, desktop_dir, "", &update_error);
+
+ if (update_error != NULL)
+ {
+ g_propagate_error (error, update_error);
+ goto out;
+ }
+
+ contents = g_string_new ("[MIME Cache]\n");
+
+ keys = g_hash_table_get_keys (mime_types_map);
+ keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
+
+ for (key = keys; key != NULL; key = key->next)
+ add_mime_type (key->data, g_hash_table_lookup (mime_types_map, key->data), contents);
+
+ g_list_free (keys);
+
+ size = contents->len;
+ result = g_bytes_new_take (g_string_free (contents, FALSE), size);
+
+out:
+ g_hash_table_foreach (mime_types_map, (GHFunc) list_free_deep, NULL);
+ g_hash_table_unref (mime_types_map);
+
+ return result;
+}
diff --git a/src/mime-cache.h b/src/mime-cache.h
new file mode 100644
index 0000000..62b8c10
--- /dev/null
+++ b/src/mime-cache.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2013 Canonical Limited
+ *
+ * update-desktop-database is free software; you can redistribute it
+ * and/or modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * update-desktop-database is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with update-desktop-database; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite
+ * 330, Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt@desrt.ca>
+ */
+
+#ifndef __mime_cache_h__
+#define __mime_cache_h__
+
+#include <glib.h>
+
+GBytes * mime_cache_build (const gchar *desktop_dir,
+ GError **error);
+
+#endif /* __mime_cache_h__ */
diff --git a/src/update-desktop-database.c b/src/update-desktop-database.c
index 92cb9a3..260d79a 100644
--- a/src/update-desktop-database.c
+++ b/src/update-desktop-database.c
@@ -1,12 +1,11 @@
-/* update-desktop-database.c - maintains mimetype<->desktop mapping cache
- * vim: set ts=2 sw=2 et: */
-
/*
* Copyright (C) 2004-2006 Red Hat, Inc.
* Copyright (C) 2006, 2008 Vincent Untz
+ * Copyright © 2013 Canonical Limited
*
* Program written by Ray Strode <rstrode@redhat.com>
* Vincent Untz <vuntz@gnome.org>
+ * Ryan Lortie <desrt@desrt.ca>
*
* update-desktop-database is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public License as
@@ -25,21 +24,12 @@
*/
#include <config.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
#include <glib.h>
#include <glib/gi18n.h>
-#include "keyfileutils.h"
-#include "mimeutils.h"
+#include "mime-cache.h"
-#define NAME "update-desktop-database"
#define CACHE_FILENAME "mimeinfo.cache"
static gboolean verbose = FALSE, quiet = FALSE;
@@ -59,255 +49,6 @@ log_handler (const gchar *log_domain,
g_log_default_handler (log_domain, log_level, message, NULL);
}
-static void
-list_free_deep (gpointer key, GList *l, gpointer data)
-{
- g_list_foreach (l, (GFunc)g_free, NULL);
- g_list_free (l);
-}
-
-static void
-cache_desktop_file (GHashTable *mime_types_map,
- const char *desktop_file,
- const char *mime_type,
- GError **error)
-{
- GList *desktop_files;
-
- desktop_files = (GList *) g_hash_table_lookup (mime_types_map, mime_type);
-
- /* do not add twice a desktop file mentioning the mime type more than once
- * (no need to use g_list_find() because we cache all mime types registered
- * by a desktop file before moving to another desktop file) */
- if (desktop_files &&
- strcmp (desktop_file, (const char *) desktop_files->data) == 0)
- return;
-
- desktop_files = g_list_prepend (desktop_files, g_strdup (desktop_file));
- g_hash_table_insert (mime_types_map, g_strdup (mime_type), desktop_files);
-}
-
-
-static void
-process_desktop_file (GHashTable *mime_types_map,
- const char *desktop_file,
- const char *name,
- GError **error)
-{
- GError *load_error;
- GKeyFile *keyfile;
- char **mime_types;
- int i;
-
- keyfile = g_key_file_new ();
-
- load_error = NULL;
- g_key_file_load_from_file (keyfile, desktop_file,
- G_KEY_FILE_NONE, &load_error);
-
- if (load_error != NULL)
- {
- g_propagate_error (error, load_error);
- return;
- }
-
- /* Hidden=true means that the .desktop file should be completely ignored */
- if (g_key_file_get_boolean (keyfile, GROUP_DESKTOP_ENTRY, "Hidden", NULL))
- {
- g_key_file_free (keyfile);
- return;
- }
-
- mime_types = g_key_file_get_string_list (keyfile,
- GROUP_DESKTOP_ENTRY,
- "MimeType", NULL, &load_error);
-
- g_key_file_free (keyfile);
-
- if (load_error != NULL)
- {
- g_propagate_error (error, load_error);
- return;
- }
-
- for (i = 0; mime_types[i] != NULL; i++)
- {
- char *mime_type;
- MimeUtilsValidity valid;
- char *valid_error;
-
- mime_type = g_strchomp (mime_types[i]);
- valid = mu_mime_type_is_valid (mime_types[i], &valid_error);
- switch (valid)
- {
- case MU_VALID:
- break;
- case MU_DISCOURAGED:
- g_warning (_("Warning in file \"%s\": usage of MIME type \"%s\" is "
- "discouraged (%s)\n"),
- desktop_file, mime_types[i], valid_error);
- g_free (valid_error);
- break;
- case MU_INVALID:
- g_warning (_("Error in file \"%s\": \"%s\" is an invalid MIME type "
- "(%s)\n"),
- desktop_file, mime_types[i], valid_error);
- g_free (valid_error);
- /* not a break: we continue to the next mime type */
- continue;
- default:
- g_assert_not_reached ();
- }
-
- cache_desktop_file (mime_types_map, name, mime_type, &load_error);
-
- if (load_error != NULL)
- {
- g_propagate_error (error, load_error);
- g_strfreev (mime_types);
- return;
- }
- }
- g_strfreev (mime_types);
-}
-
-static void
-process_desktop_files (GHashTable *mime_types_map,
- const char *desktop_dir,
- const char *prefix,
- GError **error)
-{
- GError *process_error;
- GDir *dir;
- const char *filename;
-
- process_error = NULL;
- dir = g_dir_open (desktop_dir, 0, &process_error);
-
- if (process_error != NULL)
- {
- g_propagate_error (error, process_error);
- return;
- }
-
- while ((filename = g_dir_read_name (dir)) != NULL)
- {
- char *full_path, *name;
-
- full_path = g_build_filename (desktop_dir, filename, NULL);
-
- if (g_file_test (full_path, G_FILE_TEST_IS_DIR))
- {
- char *sub_prefix;
-
- sub_prefix = g_strdup_printf ("%s%s-", prefix, filename);
-
- process_desktop_files (mime_types_map, full_path, sub_prefix, &process_error);
- g_free (sub_prefix);
-
- if (process_error != NULL)
- {
- g_warning (_("Could not process directory \"%s\": %s\n"), full_path, process_error->message);
- g_error_free (process_error);
- process_error = NULL;
- }
- g_free (full_path);
- continue;
- }
- else if (!g_str_has_suffix (filename, ".desktop"))
- {
- g_free (full_path);
- continue;
- }
-
- name = g_strdup_printf ("%s%s", prefix, filename);
- process_desktop_file (mime_types_map, full_path, name, &process_error);
- g_free (name);
-
- if (process_error != NULL)
- {
- if (!g_error_matches (process_error,
- G_KEY_FILE_ERROR,
- G_KEY_FILE_ERROR_KEY_NOT_FOUND))
- {
- g_warning (_("Could not parse file \"%s\": %s\n"), full_path, process_error->message);
- }
- else
- {
- g_debug (_("File \"%s\" lacks MimeType key\n"), full_path);
- }
-
- g_error_free (process_error);
- process_error = NULL;
- }
-
- g_free (full_path);
- }
-
- g_dir_close (dir);
-}
-
-static void
-add_mime_type (const char *mime_type, GList *desktop_files, GString *str)
-{
- GList *desktop_file;
-
- g_string_append (str, mime_type);
- g_string_append_c (str, '=');
- for (desktop_file = desktop_files;
- desktop_file != NULL;
- desktop_file = desktop_file->next)
- {
- g_string_append (str, (const char *) desktop_file->data);
- g_string_append_c (str, ';');
- }
- g_string_append_c (str, '\n');
-}
-
-static GBytes *
-mime_cache_build (const char *desktop_dir,
- GError **error)
-{
- GHashTable *mime_types_map;
- GError *update_error;
- GList *keys, *key;
- GString *contents;
- GBytes *result;
- gsize size;
-
- result = NULL;
-
- mime_types_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-
- update_error = NULL;
- process_desktop_files (mime_types_map, desktop_dir, "", &update_error);
-
- if (update_error != NULL)
- {
- g_propagate_error (error, update_error);
- goto out;
- }
-
- contents = g_string_new ("[MIME Cache]\n");
-
- keys = g_hash_table_get_keys (mime_types_map);
- keys = g_list_sort (keys, (GCompareFunc) g_strcmp0);
-
- for (key = keys; key != NULL; key = key->next)
- add_mime_type (key->data, g_hash_table_lookup (mime_types_map, key->data), contents);
-
- g_list_free (keys);
-
- size = contents->len;
- result = g_bytes_new_take (g_string_free (contents, FALSE), size);
-
-out:
- g_hash_table_foreach (mime_types_map, (GHFunc) list_free_deep, NULL);
- g_hash_table_unref (mime_types_map);
-
- return result;
-}
-
static gboolean
update_database (const char *desktop_dir,
GError **error)