diff options
author | Richard Hughes <richard@hughsie.com> | 2015-07-23 22:19:34 +0100 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2015-07-27 09:45:00 +0100 |
commit | 7fdc8c83f7ab463b1429b410efcb6627df2c91f4 (patch) | |
tree | ca302ae88b6963cacaee6863a60542b718602202 | |
parent | a228c324d8df884fc56c3464e373878e68139fa3 (diff) | |
download | appstream-glib-7fdc8c83f7ab463b1429b410efcb6627df2c91f4.tar.gz |
Emit the AsStore::changed signal if files or directories change
-rw-r--r-- | libappstream-glib/as-self-test.c | 148 | ||||
-rw-r--r-- | libappstream-glib/as-store.c | 374 | ||||
-rw-r--r-- | libappstream-glib/as-store.h | 19 |
3 files changed, 463 insertions, 78 deletions
diff --git a/libappstream-glib/as-self-test.c b/libappstream-glib/as-self-test.c index a117c92..2e93970 100644 --- a/libappstream-glib/as-self-test.c +++ b/libappstream-glib/as-self-test.c @@ -2447,6 +2447,152 @@ as_test_store_embedded_func (void) g_assert (g_file_test ("/tmp/origin/32x32/eog.png", G_FILE_TEST_EXISTS)); } +static void +store_changed_cb (AsStore *store, guint *cnt) +{ + as_test_loop_quit (); + (*cnt)++; + g_debug ("changed callback, now #%i", *cnt); +} + +/* automatically reload changed directories */ +static void +as_test_store_auto_reload_dir_func (void) +{ + AsApp *app; + gboolean ret; + guint cnt = 0; + _cleanup_error_free_ GError *error = NULL; + _cleanup_object_unref_ AsStore *store = NULL; + + /* add this file to a store */ + store = as_store_new (); + g_signal_connect (store, "changed", + G_CALLBACK (store_changed_cb), &cnt); + as_store_set_watch_flags (store, AS_STORE_WATCH_FLAG_ADDED | + AS_STORE_WATCH_FLAG_REMOVED); + + as_store_set_destdir (store, "/tmp/repo-tmp"); + g_mkdir_with_parents ("/tmp/repo-tmp/usr/share/app-info/xmls", 0700); + g_unlink ("/tmp/repo-tmp/usr/share/app-info/xmls/foo.xml"); + + /* load store */ + ret = as_store_load (store, AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpint (cnt, ==, 1); + + /* create file */ + ret = g_file_set_contents ("/tmp/repo-tmp/usr/share/app-info/xmls/foo.xml", + "<components version=\"0.6\">" + "<component type=\"desktop\">" + "<id>test.desktop</id>" + "</component>" + "</components>", + -1, &error); + g_assert_no_error (error); + g_assert (ret); + + as_test_loop_run_with_timeout (2000); + g_assert_cmpint (cnt, ==, 2); + + /* verify */ + app = as_store_get_app_by_id (store, "test.desktop"); + g_assert (app != NULL); + + /* remove file */ + g_unlink ("/tmp/repo-tmp/usr/share/app-info/xmls/foo.xml"); + as_test_loop_run_with_timeout (2000); + g_assert_cmpint (cnt, ==, 3); + app = as_store_get_app_by_id (store, "test.desktop"); + g_assert (app == NULL); +} + +/* automatically reload changed files */ +static void +as_test_store_auto_reload_file_func (void) +{ + AsApp *app; + AsRelease *rel; + gboolean ret; + guint cnt = 0; + _cleanup_error_free_ GError *error = NULL; + _cleanup_object_unref_ AsStore *store = NULL; + _cleanup_object_unref_ GFile *file = NULL; + + /* set initial file */ + ret = g_file_set_contents ("/tmp/foo.xml", + "<components version=\"0.6\">" + "<component type=\"desktop\">" + "<id>test.desktop</id>" + "<releases>" + "<release version=\"0.1.2\" timestamp=\"123\">" + "</release>" + "</releases>" + "</component>" + "</components>", + -1, &error); + g_assert_no_error (error); + g_assert (ret); + + /* add this file to a store */ + store = as_store_new (); + g_signal_connect (store, "changed", + G_CALLBACK (store_changed_cb), &cnt); + as_store_set_watch_flags (store, AS_STORE_WATCH_FLAG_ADDED | + AS_STORE_WATCH_FLAG_REMOVED); + file = g_file_new_for_path ("/tmp/foo.xml"); + ret = as_store_from_file (store, file, NULL, NULL, &error); + g_assert_no_error (error); + g_assert (ret); + g_assert_cmpint (cnt, ==, 1); + + /* verify */ + app = as_store_get_app_by_id (store, "test.desktop"); + g_assert (app != NULL); + rel = as_app_get_release_default (app); + g_assert_cmpstr (as_release_get_version (rel), ==, "0.1.2"); + g_assert_cmpstr (as_app_get_source_file (app), ==, "/tmp/foo.xml"); + + /* change the file, and ensure we get the callback */ + g_debug ("changing file"); + ret = g_file_set_contents ("/tmp/foo.xml", + "<components version=\"0.6\">" + "<component type=\"desktop\">" + "<id>test.desktop</id>" + "<releases>" + "<release version=\"0.1.0\" timestamp=\"100\">" + "</release>" + "</releases>" + "</component>" + "<component type=\"desktop\">" + "<id>baz.desktop</id>" + "</component>" + "</components>", + -1, &error); + g_assert_no_error (error); + g_assert (ret); + as_test_loop_run_with_timeout (2000); + g_assert_cmpint (cnt, ==, 2); + + /* verify */ + app = as_store_get_app_by_id (store, "baz.desktop"); + g_assert (app != NULL); + app = as_store_get_app_by_id (store, "test.desktop"); + g_assert (app != NULL); + rel = as_app_get_release_default (app); + g_assert_cmpstr (as_release_get_version (rel), ==, "0.1.0"); + + /* remove file */ + g_unlink ("/tmp/foo.xml"); + as_test_loop_run_with_timeout (2000); + g_assert_cmpint (cnt, ==, 3); + app = as_store_get_app_by_id (store, "baz.desktop"); + g_assert (app == NULL); + app = as_store_get_app_by_id (store, "test.desktop"); + g_assert (app == NULL); +} + /* demote the .desktop "application" to an addon */ static void as_test_store_demote_func (void) @@ -4039,6 +4185,8 @@ main (int argc, char **argv) g_test_add_func ("/AppStream/monitor{file}", as_test_monitor_file_func); g_test_add_func ("/AppStream/yaml", as_test_yaml_func); g_test_add_func ("/AppStream/store", as_test_store_func); + g_test_add_func ("/AppStream/store{auto-reload-dir}", as_test_store_auto_reload_dir_func); + g_test_add_func ("/AppStream/store{auto-reload-file}", as_test_store_auto_reload_file_func); g_test_add_func ("/AppStream/store{demote}", as_test_store_demote_func); g_test_add_func ("/AppStream/store{merges}", as_test_store_merges_func); g_test_add_func ("/AppStream/store{merges-local}", as_test_store_merges_local_func); diff --git a/libappstream-glib/as-store.c b/libappstream-glib/as-store.c index 2083ceb..52fb030 100644 --- a/libappstream-glib/as-store.c +++ b/libappstream-glib/as-store.c @@ -40,6 +40,7 @@ #include "as-cleanup.h" #include "as-node-private.h" #include "as-problem.h" +#include "as-monitor.h" #include "as-store.h" #include "as-utils-private.h" #include "as-yaml.h" @@ -62,11 +63,14 @@ struct _AsStorePrivate GPtrArray *array; /* of AsApp */ GHashTable *hash_id; /* of AsApp{id} */ GHashTable *hash_pkgname; /* of AsApp{pkgname} */ - GPtrArray *file_monitors; /* of GFileMonitor */ + AsMonitor *monitor; GHashTable *metadata_indexes; /* GHashTable{key} */ AsStoreAddFlags add_flags; + AsStoreWatchFlags watch_flags; AsStoreProblems problems; guint32 filter; + guint changed_block_refcnt; + gboolean is_pending_changed_signal; }; G_DEFINE_TYPE_WITH_PRIVATE (AsStore, as_store, G_TYPE_OBJECT) @@ -109,7 +113,7 @@ as_store_finalize (GObject *object) g_free (priv->origin); g_free (priv->builder_id); g_ptr_array_unref (priv->array); - g_ptr_array_unref (priv->file_monitors); + g_object_unref (priv->monitor); g_hash_table_unref (priv->hash_id); g_hash_table_unref (priv->hash_pkgname); g_hash_table_unref (priv->metadata_indexes); @@ -118,30 +122,6 @@ as_store_finalize (GObject *object) } /** - * as_store_init: - **/ -static void -as_store_init (AsStore *store) -{ - AsStorePrivate *priv = GET_PRIVATE (store); - priv->api_version = AS_API_VERSION_NEWEST; - priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); - priv->hash_id = g_hash_table_new_full (g_str_hash, - g_str_equal, - NULL, - NULL); - priv->hash_pkgname = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_object_unref); - priv->file_monitors = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); - priv->metadata_indexes = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) g_hash_table_unref); -} - -/** * as_store_class_init: **/ static void @@ -153,8 +133,8 @@ as_store_class_init (AsStoreClass *klass) * AsStore::changed: * @device: the #AsStore instance that emitted the signal * - * The ::changed signal is emitted when the files backing the store - * have changed. + * The ::changed signal is emitted when components have been added + * or removed from the store. * * Since: 0.1.2 **/ @@ -169,6 +149,64 @@ as_store_class_init (AsStoreClass *klass) } /** + * as_store_perhaps_emit_changed: + */ +static void +as_store_perhaps_emit_changed (AsStore *store, const gchar *details) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + if (priv->changed_block_refcnt > 0) { + priv->is_pending_changed_signal = TRUE; + return; + } + if (!priv->is_pending_changed_signal) { + priv->is_pending_changed_signal = TRUE; + return; + } + g_debug ("Emitting ::changed() [%s]", details); + g_signal_emit (store, signals[SIGNAL_CHANGED], 0); + priv->is_pending_changed_signal = FALSE; +} + +/** + * as_store_changed_inhibit: + */ +static guint32 * +as_store_changed_inhibit (AsStore *store) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + priv->changed_block_refcnt++; + return &priv->changed_block_refcnt; +} + +/** + * as_store_changed_uninhibit: + */ +static void +as_store_changed_uninhibit (guint32 **tok) +{ + if (tok == NULL || *tok == NULL) + return; + if (*(*tok) == 0) { + g_critical ("changed_block_refcnt already zero"); + return; + } + (*(*tok))--; + *tok = NULL; +} + +/** + * as_store_changed_uninhibit_cb: + */ +static void +as_store_changed_uninhibit_cb (void *v) +{ + as_store_changed_uninhibit ((guint32 **)v); +} + +#define _cleanup_uninhibit_ __attribute__ ((cleanup(as_store_changed_uninhibit_cb))) + +/** * as_store_add_filter: * @store: a #AsStore instance. * @kind: a #AsIdKind, e.g. %AS_ID_KIND_FIRMWARE @@ -562,6 +600,9 @@ as_store_remove_app (AsStore *store, AsApp *app) g_hash_table_remove (priv->hash_id, as_app_get_id (app)); g_ptr_array_remove (priv->array, app); g_hash_table_remove_all (priv->metadata_indexes); + + /* removed */ + as_store_perhaps_emit_changed (store, "remove-app"); } /** @@ -589,6 +630,9 @@ as_store_remove_app_by_id (AsStore *store, const gchar *id) g_ptr_array_remove (priv->array, app); } g_hash_table_remove_all (priv->metadata_indexes); + + /* removed */ + as_store_perhaps_emit_changed (store, "remove-app-by-id"); } /** @@ -713,6 +757,9 @@ as_store_add_app (AsStore *store, AsApp *app) g_strdup (pkgname), g_object_ref (app)); } + + /* added */ + as_store_perhaps_emit_changed (store, "add-app"); } /** @@ -765,9 +812,13 @@ as_store_from_root (AsStore *store, const gchar *tmp; _cleanup_free_ AsNodeContext *ctx = NULL; _cleanup_free_ gchar *icon_path = NULL; + _cleanup_uninhibit_ guint32 *tok = NULL; g_return_val_if_fail (AS_IS_STORE (store), FALSE); + /* emit once when finished */ + tok = as_store_changed_inhibit (store); + apps = as_node_find (root, "components"); if (apps == NULL) { apps = as_node_find (root, "applications"); @@ -843,6 +894,10 @@ as_store_from_root (AsStore *store, /* add addon kinds to their parent AsApp */ as_store_match_addons (store); + /* this store has changed */ + as_store_changed_uninhibit (&tok); + as_store_perhaps_emit_changed (store, "from-root"); + return TRUE; } @@ -863,6 +918,7 @@ as_store_load_yaml_file (AsStore *store, _cleanup_free_ AsNodeContext *ctx = NULL; _cleanup_free_ gchar *icon_path = NULL; _cleanup_yaml_unref_ GNode *root = NULL; + _cleanup_uninhibit_ guint32 *tok = NULL; /* load file */ root = as_yaml_from_file (file, cancellable, error); @@ -892,6 +948,9 @@ as_store_load_yaml_file (AsStore *store, NULL); } + /* emit once when finished */ + tok = as_store_changed_inhibit (store); + /* parse applications */ ctx = as_node_context_new (); for (app_n = root->children->next; app_n != NULL; app_n = app_n->next) { @@ -908,10 +967,113 @@ as_store_load_yaml_file (AsStore *store, if (as_app_get_id (app) != NULL) as_store_add_app (store, app); } + + /* emit changed */ + as_store_changed_uninhibit (&tok); + as_store_perhaps_emit_changed (store, "yaml-file"); + return TRUE; } /** + * as_store_remove_by_source_file: + */ +static void +as_store_remove_by_source_file (AsStore *store, const gchar *filename) +{ + AsApp *app; + GPtrArray *apps; + guint i; + const gchar *tmp; + _cleanup_ptrarray_unref_ GPtrArray *ids = NULL; + + /* find any applications in the store with this source file */ + ids = g_ptr_array_new_with_free_func (g_free); + apps = as_store_get_apps (store); + for (i = 0; i < apps->len; i++) { + app = g_ptr_array_index (apps, i); + if (g_strcmp0 (as_app_get_source_file (app), filename) != 0) + continue; + g_ptr_array_add (ids, g_strdup (as_app_get_id (app))); + } + + /* remove these from the store */ + for (i = 0; i < ids->len; i++) { + tmp = g_ptr_array_index (ids, i); + g_debug ("removing %s as %s invalid", tmp, filename); + as_store_remove_app_by_id (store, tmp); + } + + /* the store changed */ + as_store_perhaps_emit_changed (store, "remove-by-source-file"); +} + +/** + * as_store_monitor_changed_cb: + */ +static void +as_store_monitor_changed_cb (AsMonitor *monitor, + const gchar *filename, + AsStore *store) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + + /* reload, or emit a signal */ + if (priv->watch_flags & AS_STORE_WATCH_FLAG_ADDED) { + _cleanup_error_free_ GError *error = NULL; + _cleanup_object_unref_ GFile *file = NULL; + _cleanup_uninhibit_ guint32 *tok = NULL; + tok = as_store_changed_inhibit (store); + as_store_remove_by_source_file (store, filename); + g_debug ("rescanning %s", filename); + file = g_file_new_for_path (filename); + if (!as_store_from_file (store, file, NULL, NULL, &error)) + g_warning ("failed to rescan: %s", error->message); + } + as_store_perhaps_emit_changed (store, "file changed"); +} + +/** + * as_store_monitor_added_cb: + */ +static void +as_store_monitor_added_cb (AsMonitor *monitor, + const gchar *filename, + AsStore *store) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + + /* reload, or emit a signal */ + if (priv->watch_flags & AS_STORE_WATCH_FLAG_ADDED) { + _cleanup_error_free_ GError *error = NULL; + _cleanup_object_unref_ GFile *file = NULL; + g_debug ("scanning %s", filename); + file = g_file_new_for_path (filename); + if (!as_store_from_file (store, file, NULL, NULL, &error)) + g_warning ("failed to rescan: %s", error->message); + } else { + as_store_perhaps_emit_changed (store, "file added"); + } +} + +/** + * as_store_monitor_removed_cb: + */ +static void +as_store_monitor_removed_cb (AsMonitor *monitor, + const gchar *filename, + AsStore *store) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + /* remove, or emit a signal */ + if (priv->watch_flags & AS_STORE_WATCH_FLAG_REMOVED) { + as_store_remove_by_source_file (store, filename); + } else { + as_store_perhaps_emit_changed (store, "file removed"); + } +} + +/** * as_store_from_file: * @store: a #AsStore instance. * @file: a #GFile. @@ -937,6 +1099,7 @@ as_store_from_file (AsStore *store, GCancellable *cancellable, GError **error) { + AsStorePrivate *priv = GET_PRIVATE (store); _cleanup_free_ gchar *filename = NULL; _cleanup_error_free_ GError *error_local = NULL; _cleanup_node_unref_ GNode *root = NULL; @@ -962,6 +1125,16 @@ as_store_from_file (AsStore *store, filename, error_local->message); return FALSE; } + + /* watch for file changes */ + if (priv->watch_flags > 0) { + if (!as_monitor_add_file (priv->monitor, + filename, + cancellable, + error)) + return FALSE; + } + return as_store_from_root (store, root, icon_root, filename, error); } @@ -1375,6 +1548,39 @@ as_store_set_add_flags (AsStore *store, AsStoreAddFlags add_flags) } /** + * as_store_get_watch_flags: + * @store: a #AsStore instance. + * + * Gets the flags used for adding files to the store. + * + * Returns: the #AsStoreWatchFlags, or 0 if unset + * + * Since: 0.4.2 + **/ +AsStoreWatchFlags +as_store_get_watch_flags (AsStore *store) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + return priv->watch_flags; +} + +/** + * as_store_set_watch_flags: + * @store: a #AsStore instance. + * @watch_flags: the #AsStoreWatchFlags, e.g. %AS_STORE_WATCH_FLAG_NONE + * + * Sets the flags used when adding files to the store. + * + * Since: 0.4.2 + **/ +void +as_store_set_watch_flags (AsStore *store, AsStoreWatchFlags watch_flags) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + priv->watch_flags = watch_flags; +} + +/** * as_store_guess_origin_fallback: */ static gboolean @@ -1436,53 +1642,6 @@ as_store_load_app_info_file (AsStore *store, } /** - * as_store_cache_changed_cb: - */ -static void -as_store_cache_changed_cb (GFileMonitor *monitor, - GFile *file, GFile *other_file, - GFileMonitorEvent event_type, - AsStore *store) -{ - g_debug ("Emitting ::changed()"); - g_signal_emit (store, signals[SIGNAL_CHANGED], 0); -} - -/** - * as_store_monitor_directory: - **/ -static gboolean -as_store_monitor_directory (AsStore *store, - const gchar *path, - GCancellable *cancellable, - GError **error) -{ - AsStorePrivate *priv = GET_PRIVATE (store); - _cleanup_error_free_ GError *error_local = NULL; - _cleanup_object_unref_ GFile *file = NULL; - _cleanup_object_unref_ GFileMonitor *monitor = NULL; - - file = g_file_new_for_path (path); - monitor = g_file_monitor_directory (file, - G_FILE_MONITOR_NONE, - cancellable, - &error_local); - if (monitor == NULL) { - g_set_error (error, - AS_STORE_ERROR, - AS_STORE_ERROR_FAILED, - "Failed to monitor %s: %s", - path, error_local->message); - return FALSE; - } - g_signal_connect (monitor, "changed", - G_CALLBACK (as_store_cache_changed_cb), - store); - g_ptr_array_add (priv->file_monitors, g_object_ref (monitor)); - return TRUE; -} - -/** * as_store_load_app_info: **/ static gboolean @@ -1492,11 +1651,16 @@ as_store_load_app_info (AsStore *store, GCancellable *cancellable, GError **error) { + AsStorePrivate *priv = GET_PRIVATE (store); const gchar *tmp; _cleanup_dir_close_ GDir *dir = NULL; _cleanup_error_free_ GError *error_local = NULL; _cleanup_free_ gchar *icon_root = NULL; _cleanup_free_ gchar *path_md = NULL; + _cleanup_uninhibit_ guint32 *tok = NULL; + + /* emit once when finished */ + tok = as_store_changed_inhibit (store); /* search all files */ path_md = g_build_filename (path, format, NULL); @@ -1524,11 +1688,16 @@ as_store_load_app_info (AsStore *store, } /* watch the directories for changes */ - if (!as_store_monitor_directory (store, path_md, cancellable, error)) - return FALSE; - if (!as_store_monitor_directory (store, icon_root, cancellable, error)) + if (!as_monitor_add_directory (priv->monitor, + path_md, + cancellable, + error)) return FALSE; + /* emit changed */ + as_store_changed_uninhibit (&tok); + as_store_perhaps_emit_changed (store, "load-app-info"); + return TRUE; } @@ -1676,11 +1845,15 @@ as_store_load_installed (AsStore *store, GError *error_local = NULL; const gchar *tmp; _cleanup_dir_close_ GDir *dir = NULL; + _cleanup_uninhibit_ guint32 *tok = NULL; dir = g_dir_open (path, 0, error); if (dir == NULL) return FALSE; + /* emit once when finished */ + tok = as_store_changed_inhibit (store); + /* relax the checks when parsing */ if (flags & AS_STORE_LOAD_FLAG_ALLOW_VETO) parse_flags |= AS_APP_PARSE_FLAG_ALLOW_VETO; @@ -1726,6 +1899,11 @@ as_store_load_installed (AsStore *store, as_app_set_state (app, AS_APP_STATE_INSTALLED); as_store_add_app (store, app); } + + /* emit changed */ + as_store_changed_uninhibit (&tok); + as_store_perhaps_emit_changed (store, "load-installed"); + return TRUE; } @@ -1769,6 +1947,7 @@ as_store_load (AsStore *store, GCancellable *cancellable, GError **error) { + /* load from multiple locations */ AsStorePrivate *priv = GET_PRIVATE (store); const gchar * const * data_dirs; const gchar *tmp; @@ -1776,6 +1955,7 @@ as_store_load (AsStore *store, guint i; _cleanup_ptrarray_unref_ GPtrArray *app_info = NULL; _cleanup_ptrarray_unref_ GPtrArray *installed = NULL; + _cleanup_uninhibit_ guint32 *tok = NULL; /* system locations */ app_info = g_ptr_array_new_with_free_func (g_free); @@ -1825,6 +2005,7 @@ as_store_load (AsStore *store, } /* load each app-info path if it exists */ + tok = as_store_changed_inhibit (store); for (i = 0; i < app_info->len; i++) { _cleanup_free_ gchar *dest = NULL; tmp = g_ptr_array_index (app_info, i); @@ -1860,6 +2041,9 @@ as_store_load (AsStore *store, /* match again, for applications extended from different roots */ as_store_match_addons (store); + /* emit changed */ + as_store_changed_uninhibit (&tok); + as_store_perhaps_emit_changed (store, "store-load"); return TRUE; } @@ -2103,6 +2287,40 @@ as_store_validate (AsStore *store, AsAppValidateFlags flags, GError **error) } /** + * as_store_init: + **/ +static void +as_store_init (AsStore *store) +{ + AsStorePrivate *priv = GET_PRIVATE (store); + priv->api_version = AS_API_VERSION_NEWEST; + priv->array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref); + priv->watch_flags = AS_STORE_WATCH_FLAG_NONE; + priv->hash_id = g_hash_table_new_full (g_str_hash, + g_str_equal, + NULL, + NULL); + priv->hash_pkgname = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_object_unref); + priv->monitor = as_monitor_new (); + g_signal_connect (priv->monitor, "changed", + G_CALLBACK (as_store_monitor_changed_cb), + store); + g_signal_connect (priv->monitor, "added", + G_CALLBACK (as_store_monitor_added_cb), + store); + g_signal_connect (priv->monitor, "removed", + G_CALLBACK (as_store_monitor_removed_cb), + store); + priv->metadata_indexes = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify) g_hash_table_unref); +} + +/** * as_store_new: * * Creates a new #AsStore. diff --git a/libappstream-glib/as-store.h b/libappstream-glib/as-store.h index cb85fa7..b289c7d 100644 --- a/libappstream-glib/as-store.h +++ b/libappstream-glib/as-store.h @@ -102,6 +102,22 @@ typedef enum { } AsStoreAddFlags; /** + * AsStoreWatchFlags: + * @AS_STORE_WATCH_FLAG_NONE: No extra flags to use + * @AS_STORE_WATCH_FLAG_ADDED: Add applications if files change or are added + * @AS_STORE_WATCH_FLAG_REMOVED: Remove applications if files are changed or deleted + * + * The flags to use when local files are added or removed from the store. + **/ +typedef enum { + AS_STORE_WATCH_FLAG_NONE = 0, /* Since: 0.4.2 */ + AS_STORE_WATCH_FLAG_ADDED = 1, /* Since: 0.4.2 */ + AS_STORE_WATCH_FLAG_REMOVED = 2, /* Since: 0.4.2 */ + /*< private >*/ + AS_STORE_WATCH_FLAG_LAST +} AsStoreWatchFlags; + +/** * AsStoreError: * @AS_STORE_ERROR_FAILED: Generic failure * @@ -185,6 +201,9 @@ void as_store_set_api_version (AsStore *store, AsStoreAddFlags as_store_get_add_flags (AsStore *store); void as_store_set_add_flags (AsStore *store, AsStoreAddFlags add_flags); +AsStoreWatchFlags as_store_get_watch_flags (AsStore *store); +void as_store_set_watch_flags (AsStore *store, + AsStoreWatchFlags watch_flags); GPtrArray *as_store_validate (AsStore *store, AsAppValidateFlags flags, GError **error); |