summaryrefslogtreecommitdiffstats
path: root/debian/patches/revert_tracker_update.patch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--debian/patches/revert_tracker_update.patch2516
1 files changed, 2516 insertions, 0 deletions
diff --git a/debian/patches/revert_tracker_update.patch b/debian/patches/revert_tracker_update.patch
new file mode 100644
index 0000000..b04ad2b
--- /dev/null
+++ b/debian/patches/revert_tracker_update.patch
@@ -0,0 +1,2516 @@
+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: <http://tracker.api.gnome.org/ontology/v3/dsc#> .
+-
+-<virtual-ontology-uri:nautilus.ontology> 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: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+-@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+-@prefix nrl: <http://tracker.api.gnome.org/ontology/v3/nrl#> .
+-@prefix nautilus: <https://gitlab.gnome.org/GNOME/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 <glib.h>
+ #include <gtk/gtk.h>
+@@ -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 <alexandru.pandelea@gmail.com>
+- * Copyright (C) 2020 Sam Thursfield <sam@afuera.me.uk>
+ *
+ * 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 <gio/gunixinputstream.h>
+ #include <tracker-sparql.h>
+
+-#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 "<urn:gnome:nautilus:starred>"
+
+ 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 <gio/gio.h>
+-#include <libtracker-sparql/tracker-sparql.h>
+
+-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 { <nautilus-test-tracker> ?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<nautilus-test-tracker> ");
++ 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;
+ }