Index: nautilus/data/meson.build =================================================================== --- nautilus.orig/data/meson.build +++ nautilus/data/meson.build @@ -137,6 +137,3 @@ if appstream_util.found() ] ) endif - -subdir('ontology') -subdir('tracker') Index: nautilus/data/ontology/meson.build =================================================================== --- nautilus.orig/data/ontology/meson.build +++ /dev/null @@ -1,8 +0,0 @@ -ontology_data = files( - 'nautilus.description', - 'nautilus.ontology', -) - -install_data(ontology_data, - install_dir: join_paths(datadir, 'nautilus', 'ontology') -) Index: nautilus/data/ontology/nautilus.description =================================================================== --- nautilus.orig/data/ontology/nautilus.description +++ /dev/null @@ -1,9 +0,0 @@ -@prefix dsc: . - - a dsc:Ontology ; - dsc:title "Nautilus ontology" ; - dsc:description "Tracker database schema for Nautilus private data." ; - - dsc:localPrefix "nautilus" ; - dsc:baseUrl "https://gitlab.gnome.org/GNOME/nautilus#" ; - dsc:relativePath "./nautilus.ontology" ; Index: nautilus/data/ontology/nautilus.ontology =================================================================== --- nautilus.orig/data/ontology/nautilus.ontology +++ /dev/null @@ -1,20 +0,0 @@ -@prefix rdf: . -@prefix rdfs: . -@prefix xsd: . -@prefix nrl: . -@prefix nautilus: . - -nautilus: a nrl:Namespace, nrl:Ontology ; - nrl:prefix "nautilus" ; - nrl:lastModified "2020-05-01T10:00:00Z" . - -nautilus:File a rdfs:Class ; - rdfs:comment "Represents a file on disk by its URL. Equivalent to http://tracker.api.gnome.org/ontology/v3/nfo#FileDataObject" ; - rdfs:subClassOf rdfs:Resource ; - nrl:notify true . - -nautilus:starred a rdf:Property ; - rdfs:comment "Marks files that are starred in Nautilus." ; - rdfs:domain nautilus:File ; - rdfs:range xsd:boolean ; - nrl:maxCardinality 1 . Index: nautilus/data/tracker/meson.build =================================================================== --- nautilus.orig/data/tracker/meson.build +++ /dev/null @@ -1,31 +0,0 @@ -# Files needed for running Tracker inside the Flatpak sandbox, for systems -# which don't have a suitable version of Tracker in the host OS. -# -# We must export the .service files from the sandbox so they work on the -# session bus. This means the Tracker domain name must correspond with the -# application ID. - -domain_ontologies_dir = get_option('datadir') / 'tracker3' / 'domain-ontologies' -dbus_services_dir = get_option('datadir') / 'dbus-1' / 'services' - -tracker_domain_config = configuration_data() -tracker_domain_config.set('application_id', application_id) -tracker_domain_config.set('domain_rule', get_option('prefix') / domain_ontologies_dir / application_id + '.domain.rule') - -configure_file( - input: 'org.gnome.Nautilus.domain.rule.in', - output: application_id + '.domain.rule', - configuration: tracker_domain_config, - install_dir: domain_ontologies_dir) - -configure_file( - input: 'org.gnome.Nautilus.Tracker3.Miner.Extract.service.in', - output: application_id + '.Tracker3.Miner.Extract.service', - configuration: tracker_domain_config, - install_dir: dbus_services_dir) - -configure_file( - input: 'org.gnome.Nautilus.Tracker3.Miner.Files.service.in', - output: application_id + '.Tracker3.Miner.Files.service', - configuration: tracker_domain_config, - install_dir: dbus_services_dir) Index: nautilus/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in =================================================================== --- nautilus.orig/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Extract.service.in +++ /dev/null @@ -1,7 +0,0 @@ -[D-BUS Service] -Name=@application_id@.Tracker3.Miner.Extract -Exec=/app/libexec/tracker-extract-3 --domain-ontology @domain_rule@ - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker3/Miner/Extract -NameSuffix=Miner.Files Index: nautilus/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in =================================================================== --- nautilus.orig/data/tracker/org.gnome.Nautilus.Tracker3.Miner.Files.service.in +++ /dev/null @@ -1,7 +0,0 @@ -[D-BUS Service] -Name=@application_id@.Tracker3.Miner.Files -Exec=/app/libexec/tracker-miner-fs-3 --domain-ontology @domain_rule@ --initial-sleep 0 - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker3/Miner/Files -NameSuffix=Miner.Files Index: nautilus/data/tracker/org.gnome.Nautilus.domain.rule.in =================================================================== --- nautilus.orig/data/tracker/org.gnome.Nautilus.domain.rule.in +++ /dev/null @@ -1,21 +0,0 @@ -# This defines a private Tracker domain for Nautilus. -# -# It's used to run the Tracker indexer inside a Flatpak sandbox, when Nautilus -# is running on a host that doesn't have a suitable version of Tracker -# installed. - -[DomainOntology] -# Location for the Tracker database -CacheLocation=$XDG_CACHE_HOME/nautilus/miner/files - -# Name of the ontology to use, must be one located in -# $(sharedir)/tracker/ontologies -OntologyName=nepomuk - -# DBus name for the owner (not optional). Tracker will use -# the domain as the prefix of the DBus name for all the -# services related to this domain ontology. -Domain=@application_id@ - -# List of miners we expect to run in this domain. -Miners=Miner.Files;Miner.Extract Index: nautilus/meson.build =================================================================== --- nautilus.orig/meson.build +++ nautilus/meson.build @@ -6,7 +6,7 @@ project('nautilus', 'c', # * Update GTK-based codes over src/gtk/gtk-code-generator.sh version: '3.38.2', - meson_version: '>= 0.49.0', + meson_version: '>= 0.47.0', license: 'GPL3+' ) @@ -124,7 +124,7 @@ selinux = [] if get_option('selinux') selinux = dependency('libselinux', version: '>= 2.0') endif -tracker_sparql = dependency('tracker-sparql-3.0') +tracker_sparql = dependency('tracker-sparql-2.0') xml = dependency('libxml-2.0', version: '>= 2.7.8') #################### Index: nautilus/src/nautilus-application.c =================================================================== --- nautilus.orig/src/nautilus-application.c +++ nautilus/src/nautilus-application.c @@ -1351,8 +1351,6 @@ nautilus_application_startup_common (Nau 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); Index: nautilus/src/nautilus-batch-rename-utilities.c =================================================================== --- nautilus.orig/src/nautilus-batch-rename-utilities.c +++ nautilus/src/nautilus-batch-rename-utilities.c @@ -19,7 +19,6 @@ #include "nautilus-batch-rename-dialog.h" #include "nautilus-batch-rename-utilities.h" #include "nautilus-file.h" -#include "nautilus-tracker-utilities.h" #include #include @@ -1057,21 +1056,21 @@ check_metadata_for_selection (NautilusBa query = g_string_new ("SELECT " "nfo:fileName(?file) " - "nie:contentCreated(?content) " - "year(nie:contentCreated(?content)) " - "month(nie:contentCreated(?content)) " - "day(nie:contentCreated(?content)) " - "hours(nie:contentCreated(?content)) " - "minutes(nie:contentCreated(?content)) " - "seconds(nie:contentCreated(?content)) " - "nfo:model(nfo:equipment(?content)) " - "nmm:seasonNumber(?content) " - "nmm:episodeNumber(?content) " - "nmm:trackNumber(?content) " - "nmm:artistName(nmm:performer(?content)) " - "nie:title(?content) " - "nie:title(nmm:musicAlbum(?content)) " - "WHERE { ?file a nfo:FileDataObject. ?file nie:url ?url. ?content nie:isStoredAs ?file. "); + "nie:contentCreated(?file) " + "year(nie:contentCreated(?file)) " + "month(nie:contentCreated(?file)) " + "day(nie:contentCreated(?file)) " + "hours(nie:contentCreated(?file)) " + "minutes(nie:contentCreated(?file)) " + "seconds(nie:contentCreated(?file)) " + "nfo:model(nfo:equipment(?file)) " + "nmm:season(?file) " + "nmm:episodeNumber(?file) " + "nmm:trackNumber(?file) " + "nmm:artistName(nmm:performer(?file)) " + "nie:title(?file) " + "nmm:albumTitle(nmm:musicAlbum(?file)) " + "WHERE { ?file a nfo:FileDataObject. ?file nie:url ?url. "); parent_uri = nautilus_file_get_parent_uri (NAUTILUS_FILE (selection->data)); @@ -1116,9 +1115,9 @@ check_metadata_for_selection (NautilusBa selection_metadata = g_list_reverse (selection_metadata); - g_string_append (query, "} ORDER BY ASC(nie:contentCreated(?content))"); + g_string_append (query, "} ORDER BY ASC(nie:contentCreated(?file))"); - connection = nautilus_tracker_get_miner_fs_connection (&error); + connection = tracker_sparql_connection_get (NULL, &error); if (!connection) { if (error) Index: nautilus/src/nautilus-file-changes-queue.c =================================================================== --- nautilus.orig/src/nautilus-file-changes-queue.c +++ nautilus/src/nautilus-file-changes-queue.c @@ -21,7 +21,6 @@ #include "nautilus-file-changes-queue.h" #include "nautilus-directory-notify.h" -#include "nautilus-tag-manager.h" typedef enum { @@ -207,7 +206,6 @@ pairs_list_free (GList *pairs) void nautilus_file_changes_consume_changes (gboolean consume_all) { - g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get (); NautilusFileChange *change; GList *additions, *changes, *deletions, *moves; GFilePair *pair; @@ -323,10 +321,6 @@ nautilus_file_changes_consume_changes (g case CHANGE_FILE_MOVED: { - nautilus_tag_manager_update_moved_uris (tag_manager, - change->from, - change->to); - pair = g_new (GFilePair, 1); pair->from = change->from; pair->to = change->to; Index: nautilus/src/nautilus-file.c =================================================================== --- nautilus.orig/src/nautilus-file.c +++ nautilus/src/nautilus-file.c @@ -1853,10 +1853,6 @@ rename_get_info_callback (GObject * new_info = g_file_query_info_finish (G_FILE (source_object), res, &error); if (new_info != NULL) { - g_autoptr (NautilusTagManager) tag_manager = nautilus_tag_manager_get (); - g_autoptr (GFile) old_location = NULL; - g_autoptr (GFile) new_location = NULL; - directory = op->file->details->directory; new_name = g_file_info_get_name (new_info); @@ -1872,17 +1868,12 @@ rename_get_info_callback (GObject * nautilus_file_changed (existing_file); } - old_location = nautilus_file_get_location (op->file); - old_uri = g_file_get_uri (old_location); + old_uri = nautilus_file_get_uri (op->file); update_info_and_name (op->file, new_info); - new_location = nautilus_file_get_location (op->file); - new_uri = g_file_get_uri (new_location); - + new_uri = nautilus_file_get_uri (op->file); nautilus_directory_moved (old_uri, new_uri); - nautilus_tag_manager_update_moved_uris (tag_manager, old_location, new_location); - g_free (new_uri); g_free (old_uri); Index: nautilus/src/nautilus-files-view.c =================================================================== --- nautilus.orig/src/nautilus-files-view.c +++ nautilus/src/nautilus-files-view.c @@ -7450,7 +7450,7 @@ real_update_actions_state (NautilusFiles GDriveStartStopType start_stop_type; g_autoptr (GFile) current_location = NULL; g_autofree gchar *current_uri = NULL; - gboolean can_star_current_directory; + gboolean current_directory_tracked; gboolean show_star; gboolean show_unstar; gchar *uri; @@ -7784,12 +7784,12 @@ real_update_actions_state (NautilusFiles current_location = nautilus_file_get_location (nautilus_files_view_get_directory_as_file (view)); current_uri = g_file_get_uri (current_location); - can_star_current_directory = nautilus_tag_manager_can_star_contents (priv->tag_manager, current_location); + current_directory_tracked = nautilus_tracker_directory_is_tracked (current_location); show_star = (selection != NULL) && - (can_star_current_directory || selection_contains_starred); + (current_directory_tracked || selection_contains_starred); show_unstar = (selection != NULL) && - (can_star_current_directory || selection_contains_starred); + (current_directory_tracked || selection_contains_starred); for (l = selection; l != NULL; l = l->next) { NautilusFile *file; Index: nautilus/src/nautilus-global-preferences.c =================================================================== --- nautilus.orig/src/nautilus-global-preferences.c +++ nautilus/src/nautilus-global-preferences.c @@ -66,5 +66,5 @@ nautilus_global_preferences_init (void) gnome_lockdown_preferences = g_settings_new ("org.gnome.desktop.lockdown"); gnome_background_preferences = g_settings_new ("org.gnome.desktop.background"); gnome_interface_preferences = g_settings_new ("org.gnome.desktop.interface"); - tracker_preferences = g_settings_new ("org.freedesktop.Tracker3.Miner.Files"); + tracker_preferences = g_settings_new ("org.freedesktop.Tracker.Miner.Files"); } Index: nautilus/src/nautilus-list-view.c =================================================================== --- nautilus.orig/src/nautilus-list-view.c +++ nautilus/src/nautilus-list-view.c @@ -2494,15 +2494,14 @@ get_visible_columns (NautilusListView *l GPtrArray *res; GList *l; g_autofree gchar *uri = NULL; - gboolean can_star_current_directory; + gboolean in_tracked_dir; gboolean is_starred; file = nautilus_files_view_get_directory_as_file (NAUTILUS_FILES_VIEW (list_view)); uri = nautilus_file_get_uri (file); location = g_file_new_for_uri (uri); - can_star_current_directory = nautilus_tag_manager_can_star_contents (list_view->details->tag_manager, - location); + in_tracked_dir = nautilus_tracker_directory_is_tracked (location); is_starred = eel_uri_is_starred (uri); visible_columns = nautilus_file_get_metadata_list (file, @@ -2516,7 +2515,7 @@ get_visible_columns (NautilusListView *l for (l = visible_columns; l != NULL; l = l->next) { if (g_strcmp0 (l->data, "starred") != 0 || - (g_strcmp0 (l->data, "starred") == 0 && (can_star_current_directory || is_starred))) + (g_strcmp0 (l->data, "starred") == 0 && (in_tracked_dir || is_starred))) { g_ptr_array_add (res, l->data); } Index: nautilus/src/nautilus-search-engine-tracker.c =================================================================== --- nautilus.orig/src/nautilus-search-engine-tracker.c +++ nautilus/src/nautilus-search-engine-tracker.c @@ -25,7 +25,6 @@ #include "nautilus-search-engine-private.h" #include "nautilus-search-hit.h" #include "nautilus-search-provider.h" -#include "nautilus-tracker-utilities.h" #define DEBUG_FLAG NAUTILUS_DEBUG_SEARCH #include "nautilus-debug.h" @@ -78,9 +77,8 @@ finalize (GObject *object) } g_clear_object (&tracker->query); + g_clear_object (&tracker->connection); g_queue_free_full (tracker->hits_pending, g_object_unref); - /* This is a singleton, no need to unref. */ - tracker->connection = NULL; G_OBJECT_CLASS (nautilus_search_engine_tracker_parent_class)->finalize (object); } @@ -294,31 +292,6 @@ search_finished_idle (gpointer user_data */ #define FILENAME_RANK "5.0" -static gchar * -filter_alnum_strdup (gchar *string) -{ - GString *filtered; - gchar *c; - - filtered = g_string_new (""); - for (c = string; *c; c = g_utf8_next_char (c)) - { - gunichar uc; - - uc = g_utf8_get_char (c); - if (g_unichar_isalnum (uc)) - { - g_string_append_unichar (filtered, uc); - } - else - { - g_string_append_c (filtered, ' '); - } - } - - return g_string_free (filtered, FALSE); -} - static void nautilus_search_engine_tracker_start (NautilusSearchProvider *provider) { @@ -361,56 +334,43 @@ nautilus_search_engine_tracker_start (Na mimetypes = nautilus_query_get_mime_types (tracker->query); sparql = g_string_new ("SELECT DISTINCT" - " ?url" + " nie:url(?urn)" " xsd:double(COALESCE(?rank2, ?rank1)) AS ?rank" - " nfo:fileLastModified(?file)" - " nfo:fileLastAccessed(?file)"); - - if (tracker->fts_enabled && *search_text) - { - g_string_append (sparql, " fts:snippet(?content)"); - } - - g_string_append (sparql, "FROM tracker:FileSystem "); + " nfo:fileLastModified(?urn)" + " nfo:fileLastAccessed(?urn)"); if (tracker->fts_enabled) { - g_string_append (sparql, "FROM tracker:Documents "); + g_string_append (sparql, " fts:snippet(?urn)"); } g_string_append (sparql, "\nWHERE {" - " ?file a nfo:FileDataObject;" + " ?urn a nfo:FileDataObject;" " nfo:fileLastModified ?mtime;" " nfo:fileLastAccessed ?atime;" - " nie:dataSource/tracker:available true;" - " nie:url ?url."); + " tracker:available true;" + " nie:url ?url"); if (mimetypes->len > 0) { - g_string_append (sparql, - " ?content nie:isStoredAs ?file;" - " nie:mimeType ?mime"); + g_string_append (sparql, "; nie:mimeType ?mime"); } - if (tracker->fts_enabled && *search_text) + if (tracker->fts_enabled) { /* Use fts:match only for content search to not lose some filename results due to stop words. */ - g_autofree gchar *filtered_search_text; - - filtered_search_text = filter_alnum_strdup (search_text); g_string_append_printf (sparql, - " { " - " ?content nie:isStoredAs ?file ." - " ?content fts:match \"%s*\" ." - " BIND(fts:rank(?content) AS ?rank1) ." + " {" + " ?urn fts:match '\"nie:plainTextContent\" : \"%s\"*' ." + " BIND(fts:rank(?urn) AS ?rank1) ." " } UNION", - filtered_search_text); + search_text); } g_string_append_printf (sparql, " {" - " ?file nfo:fileName ?filename ." + " ?urn nfo:fileName ?filename ." " FILTER(fn:contains(fn:lower-case(?filename), '%s')) ." " BIND(" FILENAME_RANK " AS ?rank2) ." " }", @@ -601,7 +561,8 @@ nautilus_search_engine_tracker_init (Nau engine->hits_pending = g_queue_new (); - engine->connection = nautilus_tracker_get_miner_fs_connection (&error); + engine->connection = tracker_sparql_connection_get (NULL, &error); + if (error) { g_warning ("Could not establish a connection to Tracker: %s", error->message); Index: nautilus/src/nautilus-starred-directory.c =================================================================== --- nautilus.orig/src/nautilus-starred-directory.c +++ nautilus/src/nautilus-starred-directory.c @@ -510,6 +510,7 @@ nautilus_starred_directory_dispose (GObj { NautilusFavoriteDirectory *starred; GList *l; + NautilusFile *file; starred = NAUTILUS_STARRED_DIRECTORY (object); Index: nautilus/src/nautilus-tag-manager.c =================================================================== --- nautilus.orig/src/nautilus-tag-manager.c +++ nautilus/src/nautilus-tag-manager.c @@ -1,7 +1,6 @@ /* nautilus-tag-manager.c * * Copyright (C) 2017 Alexandru Pandelea - * Copyright (C) 2020 Sam Thursfield * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,29 +20,17 @@ #include "nautilus-file.h" #include "nautilus-file-undo-operations.h" #include "nautilus-file-undo-manager.h" -#include "nautilus-tracker-utilities.h" -#define DEBUG_FLAG NAUTILUS_DEBUG_TAG_MANAGER -#include "nautilus-debug.h" -#include #include -#include "config.h" - struct _NautilusTagManager { GObject object; - gboolean database_ok; - TrackerSparqlConnection *db; TrackerNotifier *notifier; + GError *notifier_error; - TrackerSparqlStatement *query_starred_files; - TrackerSparqlStatement *query_file_is_starred; - - GHashTable *starred_file_uris; - GFile *home; - + GHashTable *starred_files; GCancellable *cancellable; }; @@ -57,10 +44,21 @@ typedef enum typedef struct { + GTask *task; + GList *selection; + GHashTable *ids; + GObject *object; + GAsyncReadyCallback callback; + GCancellable *cancellable; +} InsertTaskData; + +typedef struct +{ NautilusTagManager *tag_manager; GTask *task; GList *selection; gboolean star; + GHashTable *ids; } UpdateData; enum @@ -69,49 +67,96 @@ enum LAST_SIGNAL }; -#define QUERY_STARRED_FILES \ - "SELECT ?file " \ - "{ " \ - " ?file a nautilus:File ; " \ - " nautilus:starred true . " \ - "}" - -#define QUERY_FILE_IS_STARRED \ - "ASK " \ - "{ " \ - " ~file a nautilus:File ; " \ - " nautilus:starred true . " \ - "}" +#define STARRED_TAG "" 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 * +nautilus_tag_manager_file_with_id_changed_url (GHashTable *hash_table, + gint64 id, + const gchar *url) +{ + GHashTableIter iter; + gpointer key, value; + + g_hash_table_iter_init (&iter, hash_table); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + if ((gint64) value == id && g_strcmp0 (url, key) != 0) + { + return key; + } + } + + return NULL; +} -static const gchar *tracker2_migration_stamp (void) +static void +destroy_insert_task_data (gpointer data) { - return g_build_filename (g_get_user_data_dir (), "nautilus", "tracker2-migration-complete", NULL); + InsertTaskData *task_data; + + task_data = data; + + nautilus_file_list_free (task_data->selection); + g_free (data); +} + +static GString * +add_selection_filter (GList *selection, + GString *query) +{ + NautilusFile *file; + GList *l; + + g_string_append (query, " FILTER(?url IN ("); + + for (l = selection; l != NULL; l = l->next) + { + g_autofree gchar *uri = NULL; + g_autofree gchar *escaped_uri = NULL; + + file = l->data; + + uri = nautilus_file_get_uri (file); + escaped_uri = tracker_sparql_escape_string (uri); + g_string_append_printf (query, "'%s'", escaped_uri); + + if (l->next != NULL) + { + g_string_append (query, ", "); + } + } + + g_string_append (query, "))"); + + return query; } static void -start_query_or_update (TrackerSparqlConnection *db, - GString *query, - GAsyncReadyCallback callback, - gpointer user_data, - gboolean is_query, - GCancellable *cancellable) +start_query_or_update (GString *query, + GAsyncReadyCallback callback, + gpointer user_data, + gboolean is_query, + GCancellable *cancellable) { g_autoptr (GError) error = NULL; + TrackerSparqlConnection *connection; - if (!db) + connection = tracker_sparql_connection_get (cancellable, &error); + if (!connection) { - g_message ("nautilus-tag-manager: No Tracker connection"); + if (error) + { + g_warning ("Error on getting connection: %s", error->message); + } + return; } if (is_query) { - tracker_sparql_connection_query_async (db, + tracker_sparql_connection_query_async (connection, query->str, cancellable, callback, @@ -119,12 +164,65 @@ start_query_or_update (TrackerSparqlConn } else { - tracker_sparql_connection_update_async (db, + tracker_sparql_connection_update_async (connection, query->str, + G_PRIORITY_DEFAULT, cancellable, callback, user_data); } + + g_object_unref (connection); +} + +static void +on_query_callback (GObject *object, + GAsyncResult *result, + gpointer user_data, + GAsyncReadyCallback callback, + OperationType op_type, + GCancellable *cancellable) +{ + TrackerSparqlCursor *cursor; + g_autoptr (GError) error = NULL; + TrackerSparqlConnection *connection; + GTask *task; + + task = user_data; + + connection = TRACKER_SPARQL_CONNECTION (object); + + cursor = tracker_sparql_connection_query_finish (connection, + result, + &error); + + if (error != NULL) + { + if (error->code != G_IO_ERROR_CANCELLED) + { + if (op_type == GET_STARRED_FILES) + { + g_warning ("Error on getting starred files: %s", error->message); + } + else if (op_type == GET_IDS_FOR_URLS) + { + g_warning ("Error on getting id for url: %s", error->message); + g_task_return_pointer (task, g_task_get_task_data (task), NULL); + g_object_unref (task); + } + else + { + g_warning ("Error on getting query callback: %s", error->message); + } + } + } + else + { + tracker_sparql_cursor_next_async (cursor, + cancellable, + callback, + user_data); + } } static void @@ -132,21 +230,46 @@ on_update_callback (GObject *object GAsyncResult *result, gpointer user_data) { - TrackerSparqlConnection *db; + TrackerSparqlConnection *connection; GError *error; UpdateData *data; + gint64 *id; + GList *l; + gchar *uri; data = user_data; error = NULL; - db = TRACKER_SPARQL_CONNECTION (object); + connection = TRACKER_SPARQL_CONNECTION (object); - tracker_sparql_connection_update_finish (db, result, &error); + tracker_sparql_connection_update_finish (connection, result, &error); if (error == NULL) { - /* FIXME: make sure data->tag_manager->starred_file_uris is up to date */ + for (l = data->selection; l != NULL; l = l->next) + { + uri = nautilus_file_get_uri (NAUTILUS_FILE (l->data)); + + if (data->star) + { + if (g_hash_table_contains (data->ids, uri)) + { + id = g_new0 (gint64, 1); + + *id = (gint64) g_hash_table_lookup (data->ids, uri); + g_hash_table_insert (data->tag_manager->starred_files, + nautilus_file_get_uri (NAUTILUS_FILE (l->data)), + id); + } + } + else + { + g_hash_table_remove (data->tag_manager->starred_files, uri); + } + + g_free (uri); + } if (!nautilus_file_undo_manager_is_operating ()) { @@ -169,11 +292,15 @@ on_update_callback (GObject *object } else { - g_warning ("error updating tags: %s", error->message); g_task_return_error (data->task, error); g_object_unref (data->task); + g_warning ("error updating tags: %s", error->message); } + if (data->ids) + { + g_hash_table_destroy (data->ids); + } nautilus_file_list_free (data->selection); g_free (data); } @@ -224,24 +351,7 @@ get_query_status (TrackerSparqlCursor *c GList * nautilus_tag_manager_get_starred_files (NautilusTagManager *self) { - GHashTableIter starred_iter; - gchar *starred_uri; - GList *starred_file_uris = NULL; - - g_hash_table_iter_init (&starred_iter, self->starred_file_uris); - while (g_hash_table_iter_next (&starred_iter, (gpointer *) &starred_uri, NULL)) - { - g_autoptr (GFile) file = g_file_new_for_uri (starred_uri); - - /* Skip files ouside $HOME, because we don't support starring these yet. - * See comment on nautilus_tag_manager_can_star_contents() */ - if (g_file_has_prefix (file, self->home)) - { - starred_file_uris = g_list_prepend (starred_file_uris, starred_uri); - } - } - - return starred_file_uris; + return g_hash_table_get_keys (self->starred_files); } static void @@ -251,6 +361,7 @@ on_get_starred_files_cursor_callback (GO { TrackerSparqlCursor *cursor; const gchar *url; + gint64 *id; gboolean success; NautilusTagManager *self; GList *changed_files; @@ -266,24 +377,21 @@ on_get_starred_files_cursor_callback (GO return; } + id = g_new0 (gint64, 1); + url = tracker_sparql_cursor_get_string (cursor, 0, NULL); + *id = tracker_sparql_cursor_get_integer (cursor, 1); - g_hash_table_add (self->starred_file_uris, g_strdup (url)); + g_hash_table_insert (self->starred_files, + g_strdup (url), + id); file = nautilus_file_get_by_uri (url); + changed_files = g_list_prepend (NULL, file); - if (file) - { - changed_files = g_list_prepend (NULL, file); + g_signal_emit_by_name (self, "starred-changed", changed_files); - g_signal_emit_by_name (self, "starred-changed", changed_files); - - nautilus_file_list_free (changed_files); - } - else - { - DEBUG ("File %s is starred but not found", url); - } + nautilus_file_list_free (changed_files); tracker_sparql_cursor_next_async (cursor, self->cancellable, @@ -296,150 +404,256 @@ on_get_starred_files_query_callback (GOb GAsyncResult *result, gpointer user_data) { - TrackerSparqlCursor *cursor; - g_autoptr (GError) error = NULL; - TrackerSparqlStatement *statement; NautilusTagManager *self; self = NAUTILUS_TAG_MANAGER (user_data); - statement = TRACKER_SPARQL_STATEMENT (object); - - cursor = tracker_sparql_statement_execute_finish (statement, - result, - &error); - if (error != NULL) - { - if (error->code != G_IO_ERROR_CANCELLED) - { - g_warning ("Error on getting starred files: %s", error->message); - } - } - else - { - tracker_sparql_cursor_next_async (cursor, - self->cancellable, - on_get_starred_files_cursor_callback, - user_data); - } + on_query_callback (object, + result, + user_data, + on_get_starred_files_cursor_callback, + GET_STARRED_FILES, + self->cancellable); } static void nautilus_tag_manager_query_starred_files (NautilusTagManager *self, GCancellable *cancellable) { - if (!self->database_ok) - { - g_message ("nautilus-tag-manager: No Tracker connection"); - return; - } + GString *query; self->cancellable = cancellable; - tracker_sparql_statement_execute_async (self->query_starred_files, - cancellable, - on_get_starred_files_query_callback, - self); + query = g_string_new ("SELECT ?url tracker:id(?urn) " + "WHERE { ?urn nie:url ?url ; nao:hasTag " STARRED_TAG "}"); + + start_query_or_update (query, + on_get_starred_files_query_callback, + self, + TRUE, + cancellable); + + g_string_free (query, TRUE); +} + +static gpointer +nautilus_tag_manager_gpointer_task_finish (GObject *source_object, + GAsyncResult *res, + GError **error) +{ + g_return_val_if_fail (g_task_is_valid (res, source_object), FALSE); + + return g_task_propagate_pointer (G_TASK (res), error); } static GString * nautilus_tag_manager_delete_tag (NautilusTagManager *self, - GList *selection) + GList *selection, + GString *query) { - GString *query; - NautilusFile *file; - GList *l; + g_string_append (query, + "DELETE { ?urn nao:hasTag " STARRED_TAG " }" + "WHERE { ?urn a nfo:FileDataObject ; nie:url ?url ."); - query = g_string_new ("DELETE DATA {"); + query = add_selection_filter (selection, query); - for (l = selection; l != NULL; l = l->next) - { - g_autofree gchar *uri = NULL; + g_string_append (query, "}\n"); - file = l->data; + return query; +} - uri = nautilus_file_get_uri (file); - g_string_append_printf (query, - " <%s> a nautilus:File ; " - " nautilus:starred true . ", - uri); - } +static GString * +nautilus_tag_manager_insert_tag (NautilusTagManager *self, + GList *selection, + GString *query) +{ + g_string_append (query, + "INSERT DATA { " STARRED_TAG " a nao:Tag .}\n" + "INSERT { ?urn nao:hasTag " STARRED_TAG " }" + "WHERE { ?urn a nfo:FileDataObject ; nie:url ?url ."); + + query = add_selection_filter (selection, query); - g_string_append (query, "}"); + g_string_append (query, "}\n"); return query; } -static GString * -nautilus_tag_manager_insert_tag (NautilusTagManager *self, - GList *selection) +gboolean +nautilus_tag_manager_file_is_starred (NautilusTagManager *self, + const gchar *file_name) { - GString *query; - NautilusFile *file; + return g_hash_table_contains (self->starred_files, file_name); +} + +static void +on_get_file_ids_for_urls_cursor_callback (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + TrackerSparqlCursor *cursor; + GTask *task; + gint64 *id; + const gchar *url; + gboolean success; GList *l; + gchar *file_url; + InsertTaskData *data; - query = g_string_new ("INSERT DATA {"); + task = user_data; + data = g_task_get_task_data (task); - for (l = selection; l != NULL; l = l->next) + cursor = TRACKER_SPARQL_CURSOR (object); + + success = get_query_status (cursor, result, GET_IDS_FOR_URLS, task); + if (!success) { - g_autofree gchar *uri = NULL; + return; + } - file = l->data; + id = g_new0 (gint64, 1); - uri = nautilus_file_get_uri (file); - g_string_append_printf (query, - " <%s> a nautilus:File ; " - " nautilus:starred true . ", - uri); + url = tracker_sparql_cursor_get_string (cursor, 0, NULL); + *id = tracker_sparql_cursor_get_integer (cursor, 1); + + for (l = data->selection; l != NULL; l = l->next) + { + file_url = nautilus_file_get_uri (NAUTILUS_FILE (l->data)); + + if (g_strcmp0 (file_url, url) == 0) + { + g_hash_table_insert (data->ids, + g_strdup (url), + id); + + g_free (file_url); + + break; + } + + g_free (file_url); } - g_string_append (query, "}"); + tracker_sparql_cursor_next_async (cursor, + g_task_get_cancellable (task), + on_get_file_ids_for_urls_cursor_callback, + task); +} - return query; + +static void +on_get_file_ids_for_urls_query_callback (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + GTask *task; + + task = user_data; + + on_query_callback (object, + result, + user_data, + on_get_file_ids_for_urls_cursor_callback, + GET_IDS_FOR_URLS, + g_task_get_cancellable (task)); } -gboolean -nautilus_tag_manager_file_is_starred (NautilusTagManager *self, - const gchar *file_uri) +static void +nautilus_tag_manager_get_file_ids_for_urls (GObject *object, + GList *selection, + GTask *task) { - return g_hash_table_contains (self->starred_file_uris, file_uri); + GString *query; + + query = g_string_new ("SELECT ?url tracker:id(?urn) WHERE { ?urn nie:url ?url; ."); + + query = add_selection_filter (selection, query); + + g_string_append (query, "}\n"); + + start_query_or_update (query, + on_get_file_ids_for_urls_query_callback, + task, + TRUE, + g_task_get_cancellable (task)); + + g_string_free (query, TRUE); } -void -nautilus_tag_manager_star_files (NautilusTagManager *self, - GObject *object, - GList *selection, - GAsyncReadyCallback callback, - GCancellable *cancellable) +static void +on_star_files_callback (GObject *object, + GAsyncResult *res, + gpointer user_data) { + NautilusTagManager *self; GString *query; + InsertTaskData *data; g_autoptr (GError) error = NULL; GTask *task; UpdateData *update_data; - DEBUG ("Starring %i files", g_list_length (selection)); + self = NAUTILUS_TAG_MANAGER (object); - task = g_task_new (object, cancellable, callback, NULL); + data = nautilus_tag_manager_gpointer_task_finish (object, res, &error); - query = nautilus_tag_manager_insert_tag (self, selection); + task = g_task_new (data->object, data->cancellable, data->callback, NULL); + + query = g_string_new (""); + + query = nautilus_tag_manager_insert_tag (self, + data->selection, + query); update_data = g_new0 (UpdateData, 1); update_data->task = task; update_data->tag_manager = self; - update_data->selection = nautilus_file_list_copy (selection); + update_data->selection = nautilus_file_list_copy (data->selection); update_data->star = TRUE; + update_data->ids = data->ids; - start_query_or_update (self->db, - query, + /* the ids hash table is now owned by the update_data, + * so it will be freed by it. + */ + destroy_insert_task_data (data); + + start_query_or_update (query, on_update_callback, update_data, FALSE, - cancellable); + g_task_get_cancellable (task)); g_string_free (query, TRUE); } void +nautilus_tag_manager_star_files (NautilusTagManager *self, + GObject *object, + GList *selection, + GAsyncReadyCallback callback, + GCancellable *cancellable) +{ + GTask *task; + InsertTaskData *data; + + data = g_new0 (InsertTaskData, 1); + data->selection = nautilus_file_list_copy (selection); + data->ids = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); + data->callback = callback; + data->object = object; + data->cancellable = cancellable; + + task = g_task_new (self, cancellable, on_star_files_callback, NULL); + g_task_set_task_data (task, + data, + NULL); + + nautilus_tag_manager_get_file_ids_for_urls (G_OBJECT (self), selection, task); +} + +void nautilus_tag_manager_unstar_files (NautilusTagManager *self, GObject *object, GList *selection, @@ -450,11 +664,13 @@ nautilus_tag_manager_unstar_files (Nauti GTask *task; UpdateData *update_data; - DEBUG ("Unstarring %i files", g_list_length (selection)); - task = g_task_new (object, cancellable, callback, NULL); - query = nautilus_tag_manager_delete_tag (self, selection); + query = g_string_new (""); + + query = nautilus_tag_manager_delete_tag (self, + selection, + query); update_data = g_new0 (UpdateData, 1); update_data->task = task; @@ -462,8 +678,7 @@ nautilus_tag_manager_unstar_files (Nauti update_data->selection = nautilus_file_list_copy (selection); update_data->star = FALSE; - start_query_or_update (self->db, - query, + start_query_or_update (query, on_update_callback, update_data, FALSE, @@ -474,21 +689,22 @@ nautilus_tag_manager_unstar_files (Nauti static void on_tracker_notifier_events (TrackerNotifier *notifier, - gchar *service, - gchar *graph, GPtrArray *events, gpointer user_data) { TrackerNotifierEvent *event; NautilusTagManager *self; int i; - const gchar *file_url; + const gchar *location_uri; + const gchar *new_location_uri; GError *error = NULL; + TrackerSparqlConnection *connection; TrackerSparqlCursor *cursor; - gboolean query_has_results = FALSE; - gboolean starred; + GString *query; + gboolean query_has_results; + gint64 *id; GList *changed_files; - NautilusFile *changed_file; + NautilusFile *file; self = NAUTILUS_TAG_MANAGER (user_data); @@ -496,60 +712,101 @@ on_tracker_notifier_events (TrackerNotif { event = g_ptr_array_index (events, i); - file_url = tracker_notifier_event_get_urn (event); - changed_file = NULL; + location_uri = tracker_notifier_event_get_location (event); - DEBUG ("Got event for file %s", file_url); + query = g_string_new (""); + g_string_append_printf (query, + "SELECT ?url WHERE { ?urn nie:url ?url; nao:hasTag " STARRED_TAG " . FILTER (tracker:id(?urn) = %" G_GINT64_FORMAT ")}", + tracker_notifier_event_get_id (event)); - tracker_sparql_statement_bind_string (self->query_file_is_starred, "file", file_url); - cursor = tracker_sparql_statement_execute (self->query_file_is_starred, - NULL, - &error); + /* check if the file changed it's location and update hash table if so */ + new_location_uri = nautilus_tag_manager_file_with_id_changed_url (self->starred_files, + tracker_notifier_event_get_id (event), + location_uri); + if (new_location_uri) + { + id = g_new0 (gint64, 1); + *id = tracker_notifier_event_get_id (event); + + g_hash_table_remove (self->starred_files, new_location_uri); + g_hash_table_insert (self->starred_files, + g_strdup (location_uri), + id); - if (cursor) - { - query_has_results = tracker_sparql_cursor_next (cursor, NULL, &error); + file = nautilus_file_get_by_uri (location_uri); + changed_files = g_list_prepend (NULL, file); + + g_signal_emit_by_name (self, "starred-changed", changed_files); + + nautilus_file_list_free (changed_files); } - if (error || !cursor || !query_has_results) + connection = tracker_sparql_connection_get (NULL, &error); + + if (!connection) { - g_warning ("Couldn't query the starred files database: '%s'", error ? error->message : "(null error)"); + g_printerr ("Couldn't obtain a direct connection to the Tracker store: %s", + error ? error->message : "unknown error"); g_clear_error (&error); + return; } - starred = tracker_sparql_cursor_get_boolean (cursor, 0); - if (starred) + cursor = tracker_sparql_connection_query (connection, + query->str, + NULL, + &error); + + if (error) { - gboolean inserted = g_hash_table_add (self->starred_file_uris, g_strdup (file_url)); + g_printerr ("Couldn't query the Tracker Store: '%s'", error->message); - if (inserted) - { - DEBUG ("Added %s to starred files list", file_url); - changed_file = nautilus_file_get_by_uri (file_url); - } + g_clear_error (&error); + + return; } - else + + if (cursor) { - gboolean removed = g_hash_table_remove (self->starred_file_uris, file_url); + query_has_results = tracker_sparql_cursor_next (cursor, NULL, &error); - if (removed) + /* if no results are found, then the file isn't marked as starred. + * If needed, update the hashtable. + */ + if (!query_has_results && location_uri && g_hash_table_contains (self->starred_files, location_uri)) { - DEBUG ("Removed %s from starred files list", file_url); - changed_file = nautilus_file_get_by_uri (file_url); + g_hash_table_remove (self->starred_files, location_uri); + + file = nautilus_file_get_by_uri (location_uri); + changed_files = g_list_prepend (NULL, file); + + g_signal_emit_by_name (self, "starred-changed", changed_files); + + nautilus_file_list_free (changed_files); } - } + else if (query_has_results && location_uri && !g_hash_table_contains (self->starred_files, location_uri)) + { + id = g_new0 (gint64, 1); + *id = tracker_notifier_event_get_id (event); - if (changed_file) - { - changed_files = g_list_prepend (NULL, changed_file); + g_hash_table_insert (self->starred_files, + g_strdup (location_uri), + id); - g_signal_emit_by_name (self, "starred-changed", changed_files); + file = nautilus_file_get_by_uri (location_uri); + changed_files = g_list_prepend (NULL, file); - nautilus_file_list_free (changed_files); + g_signal_emit_by_name (self, "starred-changed", changed_files); + + nautilus_file_list_free (changed_files); + } + + g_object_unref (cursor); } - g_object_unref (cursor); + g_object_unref (connection); + + g_string_free (query, TRUE); } } @@ -568,11 +825,8 @@ nautilus_tag_manager_finalize (GObject * } g_clear_object (&self->notifier); - g_clear_object (&self->db); - g_clear_object (&self->query_file_is_starred); - g_clear_object (&self->query_starred_files); - g_hash_table_destroy (self->starred_file_uris); + g_hash_table_destroy (self->starred_files); G_OBJECT_CLASS (nautilus_tag_manager_parent_class)->finalize (object); } @@ -614,403 +868,30 @@ nautilus_tag_manager_get (void) return tag_manager; } -static gboolean -setup_database (NautilusTagManager *self, - GCancellable *cancellable, - GError **error) -{ - const gchar *datadir; - g_autofree gchar *store_path = NULL; - g_autofree gchar *ontology_path = NULL; - g_autoptr (GFile) store = NULL; - g_autoptr (GFile) ontology = NULL; - - /* Open private database to store nautilus:starred property. */ - - datadir = NAUTILUS_DATADIR; - - store_path = g_build_filename (g_get_user_data_dir (), "nautilus", "tags", NULL); - ontology_path = g_build_filename (datadir, "ontology", NULL); - - store = g_file_new_for_path (store_path); - ontology = g_file_new_for_path (ontology_path); - - self->db = tracker_sparql_connection_new (TRACKER_SPARQL_CONNECTION_FLAGS_NONE, - store, - ontology, - cancellable, - error); - - if (*error) - { - return FALSE; - } - - /* Prepare reusable queries. */ - self->query_file_is_starred = tracker_sparql_connection_query_statement (self->db, - QUERY_FILE_IS_STARRED, - cancellable, - error); - - if (*error) - { - return FALSE; - } - - self->query_starred_files = tracker_sparql_connection_query_statement (self->db, - QUERY_STARRED_FILES, - cancellable, - error); - - if (*error) - { - return FALSE; - } - - return TRUE; -} - -/* Initialize the tag mananger. */ void nautilus_tag_manager_set_cancellable (NautilusTagManager *self, GCancellable *cancellable) { - g_autoptr (GError) error = NULL; - - self->database_ok = setup_database (self, cancellable, &error); - - if (error) - { - g_warning ("Unable to initialize tag manager: %s", error->message); - return; - } - - self->notifier = tracker_sparql_connection_create_notifier (self->db); - nautilus_tag_manager_query_starred_files (self, cancellable); - g_signal_connect (self->notifier, - "events", - G_CALLBACK (on_tracker_notifier_events), - self); -} - -static void -nautilus_tag_manager_init (NautilusTagManager *self) -{ - self->starred_file_uris = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - /* values are keys */ - NULL); - self->home = g_file_new_for_path (g_get_home_dir ()); -} - -gboolean -nautilus_tag_manager_can_star_contents (NautilusTagManager *tag_manager, - GFile *directory) -{ - /* We only allow files to be starred inside the home directory for now. - * This avoids the starred files database growing too big. - * See https://gitlab.gnome.org/GNOME/nautilus/-/merge_requests/553#note_903108 - */ - return g_file_has_prefix (directory, tag_manager->home) || g_file_equal (directory, tag_manager->home); -} - -static void -update_moved_uris_callback (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - g_autoptr (GError) error = NULL; - g_autoptr (GPtrArray) new_uris = user_data; - - tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (object), - result, - &error); - - if (error != NULL && error->code != G_IO_ERROR_CANCELLED) - { - g_warning ("Error updating moved uris: %s", error->message); - } - else - { - g_autolist (NautilusFile) updated_files = NULL; - g_autoptr (NautilusTagManager) tag_manager = NULL; - - for (guint i = 0; i < new_uris->len; i++) - { - gchar *new_uri = g_ptr_array_index (new_uris, i); - - updated_files = g_list_prepend (updated_files, nautilus_file_get_by_uri (new_uri)); - } - - tag_manager = nautilus_tag_manager_get (); - g_signal_emit_by_name (tag_manager, "starred-changed", updated_files); - } -} - -/** - * nautilus_tag_manager_update_moved_uris: - * @self: The tag manager singleton - * @src: The original location as a #GFile - * @dest: The new location as a #GFile - * - * Checks whether the rename/move operation (@src to @dest) has modified - * the URIs of any starred files, and updates the database accordingly. - */ -void -nautilus_tag_manager_update_moved_uris (NautilusTagManager *self, - GFile *src, - GFile *dest) -{ - GHashTableIter starred_iter; - gchar *starred_uri; - g_autoptr (GPtrArray) old_uris = NULL; - g_autoptr (GPtrArray) new_uris = NULL; - g_autoptr (GString) query = NULL; - - if (!self->database_ok) - { - g_message ("nautilus-tag-manager: No Tracker connection"); - return; - } - - old_uris = g_ptr_array_new (); - new_uris = g_ptr_array_new_with_free_func (g_free); - - g_hash_table_iter_init (&starred_iter, self->starred_file_uris); - while (g_hash_table_iter_next (&starred_iter, (gpointer *) &starred_uri, NULL)) - { - g_autoptr (GFile) starred_location = NULL; - g_autofree gchar *relative_path = NULL; - - starred_location = g_file_new_for_uri (starred_uri); - - if (g_file_equal (starred_location, src)) - { - /* The moved file/folder is starred */ - g_ptr_array_add (old_uris, starred_uri); - g_ptr_array_add (new_uris, g_file_get_uri (dest)); - continue; - } - - relative_path = g_file_get_relative_path (src, starred_location); - if (relative_path != NULL) - { - /* The starred file/folder is descendant of the moved/renamed directory */ - g_autoptr (GFile) new_location = NULL; - - new_location = g_file_resolve_relative_path (dest, relative_path); - - g_ptr_array_add (old_uris, starred_uri); - g_ptr_array_add (new_uris, g_file_get_uri (new_location)); - } - } - - if (new_uris->len == 0) - { - /* No starred files are affected by this move/rename */ - return; - } - - DEBUG ("Updating moved URI for %i starred files", new_uris->len); - - query = g_string_new ("DELETE DATA {"); - - for (guint i = 0; i < old_uris->len; i++) - { - gchar *old_uri = g_ptr_array_index (old_uris, i); - g_string_append_printf (query, - " <%s> a nautilus:File ; " - " nautilus:starred true . ", - old_uri); - } - - g_string_append (query, "} ; INSERT DATA {"); - - for (guint i = 0; i < new_uris->len; i++) - { - gchar *new_uri = g_ptr_array_index (new_uris, i); - g_string_append_printf (query, - " <%s> a nautilus:File ; " - " nautilus:starred true . ", - new_uri); - } - - g_string_append (query, "}"); - - /* Forward the new_uris list to later pass in the ::files-changed signal. - * There is no need to pass the old_uris because the file model is updated - * independently; we need only inform the view where to display stars now. - */ - tracker_sparql_connection_update_async (self->db, - query->str, - self->cancellable, - update_moved_uris_callback, - g_steal_pointer (&new_uris)); -} - -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 + self->notifier = tracker_notifier_new (NULL, + TRACKER_NOTIFIER_FLAG_QUERY_LOCATION, + cancellable, + &self->notifier_error); + if (self->notifier != NULL) { - g_warning ("Tracker2 migration: Failed to read data from pipe: %s", error->message); + g_signal_connect (self->notifier, + "events", + G_CALLBACK (on_tracker_notifier_events), + self); } } 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; - 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) +nautilus_tag_manager_init (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); - } + self->starred_files = g_hash_table_new_full (g_str_hash, + g_str_equal, + (GDestroyNotify) g_free, + (GDestroyNotify) g_free); } Index: nautilus/src/nautilus-tag-manager.h =================================================================== --- nautilus.orig/src/nautilus-tag-manager.h +++ nautilus/src/nautilus-tag-manager.h @@ -49,14 +49,6 @@ void nautilus_tag_manager gboolean nautilus_tag_manager_file_is_starred (NautilusTagManager *self, - const gchar *file_uri); + const gchar *file_name); -gboolean nautilus_tag_manager_can_star_contents (NautilusTagManager *self, - GFile *directory); -void nautilus_tag_manager_update_moved_uris (NautilusTagManager *tag_manager, - GFile *src, - GFile *dest); - -void nautilus_tag_manager_maybe_migrate_tracker2_data (NautilusTagManager *self); - -G_END_DECLS +G_END_DECLS \ No newline at end of file Index: nautilus/src/nautilus-tracker-utilities.c =================================================================== --- nautilus.orig/src/nautilus-tracker-utilities.c +++ nautilus/src/nautilus-tracker-utilities.c @@ -18,128 +18,141 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ -#include "config.h" #include "nautilus-tracker-utilities.h" #include "nautilus-global-preferences.h" #define TRACKER_KEY_RECURSIVE_DIRECTORIES "index-recursive-directories" #define TRACKER_KEY_SINGLE_DIRECTORIES "index-single-directories" -/* Shared global connection to Tracker Miner FS */ -static const gchar *tracker_miner_fs_busname = NULL; -static TrackerSparqlConnection *tracker_miner_fs_connection = NULL; -static GError *tracker_miner_fs_error = NULL; - -static gboolean -get_host_tracker_miner_fs (GError **error) +static GFile * +location_from_tracker_dir (const gchar *value) { - const gchar *busname = "org.freedesktop.Tracker3.Miner.Files"; + const gchar *special_dir; + g_autoptr (GFile) home = NULL; + GFile *location; + + home = g_file_new_for_path (g_get_home_dir ()); - g_message ("Connecting to %s", busname); - tracker_miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error); - if (*error) + if (g_strcmp0 (value, "$HOME") == 0) { - g_warning ("Unable to create connection for session-wide Tracker indexer: %s", (*error)->message); - return FALSE; + return g_steal_pointer (&home); } - tracker_miner_fs_busname = busname; - return TRUE; -} + special_dir = NULL; + if (g_strcmp0 (value, "&DESKTOP") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP); + } + else if (g_strcmp0 (value, "&DOCUMENTS") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_DOCUMENTS); + } + else if (g_strcmp0 (value, "&DOWNLOAD") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_DOWNLOAD); + } + else if (g_strcmp0 (value, "&MUSIC") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_MUSIC); + } + else if (g_strcmp0 (value, "&PICTURES") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES); + } + else if (g_strcmp0 (value, "&PUBLIC_SHARE") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_PUBLIC_SHARE); + } + else if (g_strcmp0 (value, "&TEMPLATES") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_TEMPLATES); + } + else if (g_strcmp0 (value, "&VIDEOS") == 0) + { + special_dir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS); + } -static gboolean -start_local_tracker_miner_fs (GError **error) -{ - const gchar *busname = APPLICATION_ID ".Tracker3.Miner.Files"; + if (special_dir != NULL) + { + location = g_file_new_for_commandline_arg (special_dir); - g_message ("Starting %s", busname); - tracker_miner_fs_connection = tracker_sparql_connection_bus_new (busname, NULL, NULL, error); - if (*error) + /* Ignore XDG directories set to $HOME, like the miner does */ + if (g_file_equal (location, home)) + { + g_clear_object (&location); + } + } + else { - g_critical ("Could not start local Tracker indexer at %s: %s", busname, (*error)->message); - return FALSE; + location = g_file_new_for_commandline_arg (value); } - tracker_miner_fs_busname = busname; - return TRUE; + return location; } -static gboolean -inside_flatpak (void) +static GList * +get_tracker_locations (const gchar *key) { - return g_file_test ("/.flatpak-info", G_FILE_TEST_EXISTS); -} + g_auto (GStrv) locations = NULL; + GList *list = NULL; + gint idx; + GFile *location; -static void -setup_tracker_miner_fs_connection (void) -{ - static gsize tried_tracker_init = FALSE; + locations = g_settings_get_strv (tracker_preferences, key); - if (g_once_init_enter (&tried_tracker_init)) + for (idx = 0; locations[idx] != NULL; idx++) { - gboolean success; - - success = get_host_tracker_miner_fs (&tracker_miner_fs_error); - - if (!success && inside_flatpak ()) + location = location_from_tracker_dir (locations[idx]); + if (location != NULL) { - g_clear_error (&tracker_miner_fs_error); - success = start_local_tracker_miner_fs (&tracker_miner_fs_error); + list = g_list_prepend (list, location); } - - g_once_init_leave (&tried_tracker_init, TRUE); } + + return list; } /** - * nautilus_tracker_get_miner_fs_connection: - * @error: return location for a #GError + * nautilus_tracker_directory_is_tracked: + * @directory: a #GFile representing a directory * - * This function returns a global singleton #TrackerSparqlConnection, or %NULL - * if we couldn't connect to Tracker Miner FS. + * This function reads the "index-recursive-directories" and + * "index-single-directories" keys from the org.freedesktop.tracker.miner.files + * schema, and assumes the listed directories (and their descendants for the + * former key) are tracked. * - * The first time you call it, this function will block while trying to connect. - * This may take some time if starting Tracker Miners from a Flatpak bundle. + * Exception: XDG user dirs set to $HOME are ignored. * - * The returned object is a globally shared singleton which should NOT be - * unreffed. + * FIXME: Tracker's files miner's logic is actually a lot more complex, + * including configurable ignore patterns, but we are overlooking that. * - * Returns: a #TrackerSparqlConnection, or %NULL + * Returns: $TRUE if the @directory is, in principle, tracked. $FALSE otherwise. */ -TrackerSparqlConnection * -nautilus_tracker_get_miner_fs_connection (GError **error) +gboolean +nautilus_tracker_directory_is_tracked (GFile *directory) { - setup_tracker_miner_fs_connection (); + g_autolist (GFile) recursive_locations = NULL; + g_autolist (GFile) single_locations = NULL; + GList *l; - if (tracker_miner_fs_error && error) + recursive_locations = get_tracker_locations (TRACKER_KEY_RECURSIVE_DIRECTORIES); + for (l = recursive_locations; l != NULL; l = l->next) { - *error = g_error_copy (tracker_miner_fs_error); + if (g_file_equal (directory, G_FILE (l->data)) || + g_file_has_prefix (directory, G_FILE (l->data))) + { + return TRUE; + } } - return tracker_miner_fs_connection; -} - -/** - * nautilus_tracker_get_miner_fs_busname: - * @error: return location for a #GError - * - * This function returns a DBus name that can be used to talk to - * tracker-miner-fs, or %NULL if there is no Tracker Miner FS available. - * - * The first time you call it, this function will block while trying to connect. - * This may take some time if starting Tracker Miners from a Flatpak bundle. - * - * Returns: a string - */ -const gchar * -nautilus_tracker_get_miner_fs_busname (GError **error) -{ - setup_tracker_miner_fs_connection (); - - if (tracker_miner_fs_error && error) + single_locations = get_tracker_locations (TRACKER_KEY_SINGLE_DIRECTORIES); + for (l = single_locations; l != NULL; l = l->next) { - *error = g_error_copy (tracker_miner_fs_error); + if (g_file_equal (directory, G_FILE (l->data))) + { + return TRUE; + } } - return tracker_miner_fs_busname; + return FALSE; } Index: nautilus/src/nautilus-tracker-utilities.h =================================================================== --- nautilus.orig/src/nautilus-tracker-utilities.h +++ nautilus/src/nautilus-tracker-utilities.h @@ -22,7 +22,5 @@ #pragma once #include -#include -TrackerSparqlConnection * nautilus_tracker_get_miner_fs_connection (GError **error); -const gchar * nautilus_tracker_get_miner_fs_busname (GError **error); +gboolean nautilus_tracker_directory_is_tracked (GFile *directory); Index: nautilus/test/automated/displayless/meson.build =================================================================== --- nautilus.orig/test/automated/displayless/meson.build +++ nautilus/test/automated/displayless/meson.build @@ -1,7 +1,3 @@ -trackertestutils = dependency('tracker-testutils-3.0') - -tracker_sandbox = find_program(trackertestutils.get_pkgconfig_variable('command')) - tests = [ ['test-file-utilities-get-common-filename-prefix', [ 'test-file-utilities-get-common-filename-prefix.c' @@ -27,6 +23,9 @@ tests = [ ['test-nautilus-search-engine-model', [ 'test-nautilus-search-engine-model.c' ]], + ['test-nautilus-search-engine-tracker', [ + 'test-nautilus-search-engine-tracker.c' + ]], ['test-file-operations-copy-files', [ 'test-file-operations-copy-files.c' ]], @@ -35,12 +34,6 @@ tests = [ ]] ] -tracker_tests = [ - ['test-nautilus-search-engine-tracker', [ - 'test-nautilus-search-engine-tracker.c', - ]], -] - foreach t: tests test( t[0], @@ -48,25 +41,6 @@ foreach t: tests env: [ test_env, 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), - 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()) - ], - timeout: 480 - ) -endforeach - - - -# Tests that read and write from the Tracker index are run using 'tracker-sandbox' -# script to use a temporary instance of tracker-miner-fs instead of the session one. -foreach t: tracker_tests - test_exe = executable(t[0], t[1], files('test-utilities.c'), dependencies: libnautilus_dep) - test( - t[0], - tracker_sandbox, - args: ['--store-tmpdir', '--index-recursive-tmpdir', test_exe], - env: [ - test_env, - 'G_TEST_BUILDDIR=@0@'.format(meson.current_build_dir()), 'G_TEST_SRCDIR=@0@'.format(meson.current_source_dir()) ], timeout: 480 Index: nautilus/test/automated/displayless/test-nautilus-search-engine-model.c =================================================================== --- nautilus.orig/test/automated/displayless/test-nautilus-search-engine-model.c +++ nautilus/test/automated/displayless/test-nautilus-search-engine-model.c @@ -1,7 +1,5 @@ #include "test-utilities.h" -static guint total_hits = 0; - static void hits_added_cb (NautilusSearchEngine *engine, GSList *hits) @@ -10,8 +8,6 @@ hits_added_cb (NautilusSearchEngine *eng for (gint hit_number = 0; hits != NULL; hits = hits->next, hit_number++) { g_print ("Hit %i: %s\n", hit_number, nautilus_search_hit_get_uri (hits->data)); - - total_hits += 1; } } @@ -72,8 +68,5 @@ main (int argc, NAUTILUS_SEARCH_ENGINE_MODEL_ENGINE); g_main_loop_run (loop); - - g_assert_cmpint (total_hits, ==, 3); - return 0; } Index: nautilus/test/automated/displayless/test-nautilus-search-engine-simple.c =================================================================== --- nautilus.orig/test/automated/displayless/test-nautilus-search-engine-simple.c +++ nautilus/test/automated/displayless/test-nautilus-search-engine-simple.c @@ -1,7 +1,5 @@ #include "test-utilities.h" -static guint total_hits = 0; - static void hits_added_cb (NautilusSearchEngine *engine, GSList *hits) @@ -10,7 +8,6 @@ hits_added_cb (NautilusSearchEngine *eng for (gint hit_number = 0; hits != NULL; hits = hits->next, hit_number++) { g_print ("Hit %i: %s\n", hit_number, nautilus_search_hit_get_uri (hits->data)); - total_hits += 1; } } @@ -67,8 +64,5 @@ main (int argc, NAUTILUS_SEARCH_ENGINE_SIMPLE_ENGINE); g_main_loop_run (loop); - - g_assert_cmpint (total_hits, ==, 3); - return 0; } Index: nautilus/test/automated/displayless/test-nautilus-search-engine-tracker.c =================================================================== --- nautilus.orig/test/automated/displayless/test-nautilus-search-engine-tracker.c +++ nautilus/test/automated/displayless/test-nautilus-search-engine-tracker.c @@ -1,106 +1,5 @@ #include "test-utilities.h" -/* Time in seconds we allow for Tracker Miners to index the file */ -#define TRACKER_MINERS_AWAIT_TIMEOUT 1000 - -static guint total_hits = 0; - -typedef struct -{ - GMainLoop *main_loop; - gchar *uri; - gboolean created; -} TrackerAwaitFileData; - -static TrackerAwaitFileData * -tracker_await_file_data_new (const char *uri, - GMainLoop *main_loop) -{ - TrackerAwaitFileData *data; - - data = g_slice_new0 (TrackerAwaitFileData); - data->uri = g_strdup (uri); - data->main_loop = g_main_loop_ref (main_loop); - - return data; -} - -static void -tracker_await_file_data_free (TrackerAwaitFileData *data) -{ - g_free (data->uri); - g_main_loop_unref (data->main_loop); - g_slice_free (TrackerAwaitFileData, data); -} - -static gboolean timeout_cb (gpointer user_data) -{ - TrackerAwaitFileData *data = user_data; - g_error ("Timeout waiting for %s to be indexed by Tracker.", data->uri); - return G_SOURCE_REMOVE; -} - -static void -tracker_events_cb (TrackerNotifier *self, - gchar *service, - gchar *graph, - GPtrArray *events, - gpointer user_data) -{ - TrackerAwaitFileData *data = user_data; - int i; - - for (i = 0; i < events->len; i++) - { - TrackerNotifierEvent *event = g_ptr_array_index (events, i); - - if (tracker_notifier_event_get_event_type (event) == TRACKER_NOTIFIER_EVENT_CREATE) - { - const gchar *urn = tracker_notifier_event_get_urn (event); - g_debug ("Got CREATED event for %s", urn); - if (strcmp (urn, data->uri) == 0) - { - data->created = TRUE; - g_main_loop_quit (data->main_loop); - } - } - } -} - -/* Create data that the Tracker indexer will find, and wait for the database to be updated. */ -static void -create_test_data (TrackerSparqlConnection *connection, - const gchar *indexed_tmpdir) -{ - g_autoptr (GFile) test_file = NULL; - g_autoptr (GMainLoop) main_loop = NULL; - g_autoptr (GError) error = NULL; - g_autoptr (TrackerNotifier) notifier = NULL; - TrackerAwaitFileData *await_data; - gulong signal_id, timeout_id; - - test_file = g_file_new_build_filename (indexed_tmpdir, "target_file.txt", NULL); - - main_loop = g_main_loop_new (NULL, 0); - await_data = tracker_await_file_data_new (g_file_get_uri (test_file), main_loop); - - notifier = tracker_sparql_connection_create_notifier (connection); - - signal_id = g_signal_connect (notifier, "events", G_CALLBACK (tracker_events_cb), await_data); - timeout_id = g_timeout_add_seconds (TRACKER_MINERS_AWAIT_TIMEOUT, timeout_cb, await_data); - - g_file_set_contents (g_file_peek_path (test_file), "Please show me in the search results", -1, &error); - g_assert_no_error (error); - - g_main_loop_run (main_loop); - - g_assert (await_data->created); - g_source_remove (timeout_id); - g_clear_signal_handler (&signal_id, notifier); - - tracker_await_file_data_free (await_data); -} - static void hits_added_cb (NautilusSearchEngine *engine, GSList *hits) @@ -109,7 +8,6 @@ hits_added_cb (NautilusSearchEngine *eng for (gint hit_number = 0; hits != NULL; hits = hits->next, hit_number++) { g_print ("Hit %i: %s\n", hit_number, nautilus_search_hit_get_uri (hits->data)); - total_hits += 1; } } @@ -118,10 +16,21 @@ finished_cb (NautilusSearchEngine NautilusSearchProviderStatus status, gpointer user_data) { + TrackerSparqlConnection *connection; + g_autofree gchar *sparql_query = NULL; + nautilus_search_provider_stop (NAUTILUS_SEARCH_PROVIDER (engine)); g_print ("\nNautilus search engine tracker finished!\n"); + connection = tracker_sparql_connection_get (NULL, NULL); + sparql_query = g_strdup_printf ("DELETE WHERE { ?p ?o }"); + tracker_sparql_connection_update (connection, + sparql_query, + 0, + NULL, + NULL); + g_main_loop_quit (user_data); } @@ -130,24 +39,14 @@ main (int argc, char *argv[]) { g_autoptr (GMainLoop) loop = NULL; - g_autoptr (TrackerSparqlConnection) connection = NULL; NautilusSearchEngine *engine; g_autoptr (NautilusDirectory) directory = NULL; g_autoptr (NautilusQuery) query = NULL; g_autoptr (GFile) location = NULL; - g_autoptr (GError) error = NULL; - const gchar *indexed_tmpdir; - - indexed_tmpdir = g_getenv ("TRACKER_INDEXED_TMPDIR"); - if (!indexed_tmpdir) - { - g_error ("This test must be inside the `tracker-sandbox` script " - "to ensure a private Tracker indexer daemon is used."); - } - - connection = tracker_sparql_connection_bus_new ("org.freedesktop.Tracker3.Miner.Files", NULL, NULL, &error); + TrackerSparqlConnection *connection; + g_autofree gchar *sparql_query = NULL; - g_assert_no_error (error); + connection = tracker_sparql_connection_get (NULL, NULL); loop = g_main_loop_new (NULL, FALSE); @@ -158,8 +57,6 @@ main (int argc, */ nautilus_global_preferences_init (); - create_test_data (connection, indexed_tmpdir); - engine = nautilus_search_engine_new (); g_signal_connect (engine, "hits-added", G_CALLBACK (hits_added_cb), NULL); @@ -170,16 +67,40 @@ main (int argc, nautilus_query_set_text (query, "target"); nautilus_search_provider_set_query (NAUTILUS_SEARCH_PROVIDER (engine), query); - location = g_file_new_for_path (indexed_tmpdir); + location = g_file_new_for_path (g_get_tmp_dir ()); directory = nautilus_directory_get (location); nautilus_query_set_location (query, location); + /* This sparql query with the update call create a virtual file + * in tracker, so it sees a file named "target_file" in /tmp. + * The file's MIME type is text/plain and the name tracker is + * using for search is "target". For the engine tracker to hit, + * we also need to set the last time the file was accessed and modified, + * which we set to 2001-01-01, at 00:00:01 (the date needs to be a full + * ISO 8601 date string) and tracker:available be set to true (in order + * for the file to be accessible). + */ + + sparql_query = g_strdup_printf ("INSERT DATA {\n "); + sparql_query = g_strconcat (sparql_query, "a nfo:FileDataObject ;", NULL); + sparql_query = g_strconcat (sparql_query, "\na nie:InformationElement ;", NULL); + sparql_query = g_strconcat (sparql_query, "\nnie:url 'file:///tmp/target_file';", NULL); + sparql_query = g_strconcat (sparql_query, "\nnie:mimeType 'text/plain';", NULL); + sparql_query = g_strconcat (sparql_query, "\nnfo:fileName 'target';", NULL); + sparql_query = g_strconcat (sparql_query, "\nnfo:fileLastModified '2001-01-01T00:00:01Z';", NULL); + sparql_query = g_strconcat (sparql_query, "\nnfo:fileLastAccessed '2001-01-01T00:00:01Z';", NULL); + sparql_query = g_strconcat (sparql_query, "\ntracker:available true", NULL); + sparql_query = g_strconcat (sparql_query, ".\n}\n", NULL); + + tracker_sparql_connection_update (connection, + sparql_query, + 0, + NULL, + NULL); + nautilus_search_engine_start_by_target (NAUTILUS_SEARCH_PROVIDER (engine), NAUTILUS_SEARCH_ENGINE_TRACKER_ENGINE); g_main_loop_run (loop); - - g_assert_cmpint (total_hits, ==, 1); - return 0; } Index: nautilus/test/automated/displayless/test-nautilus-search-engine.c =================================================================== --- nautilus.orig/test/automated/displayless/test-nautilus-search-engine.c +++ nautilus/test/automated/displayless/test-nautilus-search-engine.c @@ -1,7 +1,5 @@ #include "test-utilities.h" -static guint total_hits = 0; - static void hits_added_cb (NautilusSearchEngine *engine, GSList *hits) @@ -10,7 +8,6 @@ hits_added_cb (NautilusSearchEngine *eng for (gint hit_number = 0; hits != NULL; hits = hits->next, hit_number++) { g_print ("Hit %i: %s\n", hit_number, nautilus_search_hit_get_uri (hits->data)); - total_hits += 1; } } @@ -67,8 +64,5 @@ main (int argc, nautilus_search_provider_start (NAUTILUS_SEARCH_PROVIDER (engine)); g_main_loop_run (loop); - - g_assert_cmpint (total_hits, ==, 3); - return 0; }