From 7cf268ab73f71c09ed85f917c5c5f2703d71e400 Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Sat, 29 Aug 2020 21:10:48 +0200 Subject: Import starred files data from Tracker 2.x Starred files data is now migrated from the Tracker 2.x database if found. This depends on the `tracker3` CLI tool, which should be present anywhere that we find libtracker-sparql 3.0. The --2to3 export functionality was added in https://gitlab.gnome.org/GNOME/tracker/-/merge_requests/308 If/when the migration completes successfully, a stamp file named `~/.local/share/nautilus/tracker2-migration-complete` is created. --- src/nautilus-application.c | 2 + src/nautilus-search-engine-tracker.c | 2 +- src/nautilus-tag-manager.c | 173 +++++++++++++++++++++++++++++++++++ src/nautilus-tag-manager.h | 2 + 4 files changed, 178 insertions(+), 1 deletion(-) diff --git a/src/nautilus-application.c b/src/nautilus-application.c index 17f1da59a..10478da9c 100644 --- a/src/nautilus-application.c +++ b/src/nautilus-application.c @@ -1351,6 +1351,8 @@ nautilus_application_startup_common (NautilusApplication *self) nautilus_init_application_actions (self); + nautilus_tag_manager_maybe_migrate_tracker2_data (priv->tag_manager); + nautilus_profile_end (NULL); g_signal_connect (self, "notify::active-window", G_CALLBACK (on_application_active_window_changed), NULL); diff --git a/src/nautilus-search-engine-tracker.c b/src/nautilus-search-engine-tracker.c index a0e0d638c..9ebac0b28 100644 --- a/src/nautilus-search-engine-tracker.c +++ b/src/nautilus-search-engine-tracker.c @@ -393,7 +393,7 @@ nautilus_search_engine_tracker_start (NautilusSearchProvider *provider) " nie:mimeType ?mime"); } - if (tracker->fts_enabled) + if (tracker->fts_enabled && *search_text) { /* Use fts:match only for content search to not lose some filename results due to stop words. */ g_autofree gchar *filtered_search_text; diff --git a/src/nautilus-tag-manager.c b/src/nautilus-tag-manager.c index f41b3ec8f..fbd8571e5 100644 --- a/src/nautilus-tag-manager.c +++ b/src/nautilus-tag-manager.c @@ -25,6 +25,7 @@ #define DEBUG_FLAG NAUTILUS_DEBUG_TAG_MANAGER #include "nautilus-debug.h" +#include #include #include "config.h" @@ -84,6 +85,14 @@ enum static guint signals[LAST_SIGNAL]; +/* Limit to 10MB output from Tracker -- surely, nobody has over a million starred files. */ +#define TRACKER2_MAX_IMPORT_BYTES 10 * 1024 * 1024 + +static const gchar *tracker2_migration_stamp (void) +{ + return g_build_filename (g_get_user_data_dir (), "nautilus", "tracker2-migration-complete", NULL); +} + static void start_query_or_update (TrackerSparqlConnection *db, GString *query, @@ -690,3 +699,167 @@ nautilus_tag_manager_can_star_contents (NautilusTagManager *tag_manager, */ return g_file_has_prefix (directory, tag_manager->home) || g_file_equal (directory, tag_manager->home); } + +static void +process_tracker2_data_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + NautilusTagManager *self = NAUTILUS_TAG_MANAGER (source_object); + const gchar *path = tracker2_migration_stamp (); + g_autoptr (GError) error = NULL; + + tracker_sparql_connection_update_finish (self->db, res, &error); + + if (!error) + { + DEBUG ("Data migration was successful. Creating stamp %s", path); + + g_file_set_contents (path, "", -1, &error); + if (error) + { + g_warning ("Failed to create %s after migration: %s", path, error->message); + } + } + else + { + g_warning ("Error during data migration: %s", error->message); + } +} + +static void +process_tracker2_data (NautilusTagManager *self, + GBytes *key_file_data) +{ + g_autoptr (GKeyFile) key_file = NULL; + g_autoptr (GError) error = NULL; + gchar **groups, **group; + GList *selection = NULL; + NautilusFile *file; + + key_file = g_key_file_new (); + g_key_file_load_from_bytes (key_file, + key_file_data, + G_KEY_FILE_NONE, + &error); + g_bytes_unref (key_file_data); + + if (error) + { + g_warning ("Tracker 2 migration: Failed to parse key file data: %s", error->message); + return; + } + + groups = g_key_file_get_groups (key_file, NULL); + + for (group = groups; *group != NULL; group++) + { + file = nautilus_file_get_by_uri (*group); + + if (file) + { + DEBUG ("Tracker 2 migration: starring %s", *group); + selection = g_list_prepend (selection, file); + } + else + { + DEBUG ("Tracker 2 migration: couldn't get NautilusFile for %s", *group); + } + } + + nautilus_tag_manager_star_files (self, + G_OBJECT (self), + selection, + process_tracker2_data_cb, + self->cancellable); + + g_free (groups); +} + +static void +export_tracker2_data_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GInputStream *stream = G_INPUT_STREAM (source_object); + NautilusTagManager *self = NAUTILUS_TAG_MANAGER (user_data); + g_autoptr (GError) error = NULL; + GBytes *key_file_data; + + key_file_data = g_input_stream_read_bytes_finish (stream, res, &error); + + if (key_file_data) + { + process_tracker2_data (self, key_file_data); + } + else + { + g_warning ("Tracker2 migration: Failed to read data from pipe: %s", error->message); + } +} + +static void +child_watch_cb (GPid pid, + gint status, + gpointer user_data) +{ + DEBUG ("Child %" G_PID_FORMAT " exited %s", pid, + g_spawn_check_exit_status (status, NULL) ? "normally" : "abnormally"); + g_spawn_close_pid (pid); +} + +static void +export_tracker2_data (NautilusTagManager *self) +{ + gchar *argv[] = {"tracker3", "export", "--2to3", "files-starred", "--keyfile", NULL}; + gint stdout_fd; + GPid child_pid; + g_autoptr (GError) error = NULL; + gboolean success; + g_autoptr (GInputStream) stream = NULL; + GSpawnFlags flags; + + flags = G_SPAWN_DO_NOT_REAP_CHILD | + G_SPAWN_STDERR_TO_DEV_NULL | + G_SPAWN_SEARCH_PATH_FROM_ENVP; + success = g_spawn_async_with_pipes (NULL, + argv, + NULL, + flags, + NULL, + NULL, + &child_pid, + NULL, + &stdout_fd, + NULL, + &error); + if (!success) + { + g_warning ("Tracker 2 migration: Couldn't run `tracker3`: %s", error->message); + return; + } + + g_child_watch_add (child_pid, child_watch_cb, NULL); + + stream = g_unix_input_stream_new (stdout_fd, TRUE); + g_input_stream_read_bytes_async (stream, + TRACKER2_MAX_IMPORT_BYTES, + G_PRIORITY_LOW, + self->cancellable, + export_tracker2_data_cb, + self); +} + +void +nautilus_tag_manager_maybe_migrate_tracker2_data (NautilusTagManager *self) +{ + if (g_file_test (tracker2_migration_stamp (), G_FILE_TEST_EXISTS)) + { + DEBUG ("Tracker 2 migration: already completed."); + } + else + { + DEBUG ("Tracker 2 migration: starting."); + export_tracker2_data (self); + } +} diff --git a/src/nautilus-tag-manager.h b/src/nautilus-tag-manager.h index c0d793adc..2e926ae75 100644 --- a/src/nautilus-tag-manager.h +++ b/src/nautilus-tag-manager.h @@ -54,4 +54,6 @@ gboolean nautilus_tag_manager_file_is_starred (NautilusTagManager * gboolean nautilus_tag_manager_can_star_contents (NautilusTagManager *self, GFile *directory); +void nautilus_tag_manager_maybe_migrate_tracker2_data (NautilusTagManager *self); + G_END_DECLS -- cgit v1.2.1