summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoaquim Rocha <jrocha@endlessm.com>2016-10-18 17:30:31 +0200
committerJoaquim Rocha <jrocha@endlessm.com>2016-10-18 17:30:31 +0200
commitf6e551fa6a8224c5267affa12c8286648f2358db (patch)
tree4952eb8182319ee892214789a1b80cd6d403f29d
parent210988cc41ae81f1f59847475602be016dc5b12a (diff)
downloadappstream-glib-wip/jrocha/monitor-missing-dirs.tar.gz
Monitor missing directorieswip/jrocha/monitor-missing-dirs
These changes introduce a new AS_STORE_LOAD flag to monitor directories that do not exist and use it when adding the cached app-info ones. The reason is that these directories can be more volatile than others in some systems and be added while a client is already running.
-rw-r--r--libappstream-glib/as-monitor.c16
-rw-r--r--libappstream-glib/as-store.c137
-rw-r--r--libappstream-glib/as-store.h2
3 files changed, 101 insertions, 54 deletions
diff --git a/libappstream-glib/as-monitor.c b/libappstream-glib/as-monitor.c
index bec94f7..58cd356 100644
--- a/libappstream-glib/as-monitor.c
+++ b/libappstream-glib/as-monitor.c
@@ -412,14 +412,14 @@ as_monitor_add_directory (AsMonitor *monitor,
g_autoptr(GDir) dir = NULL;
/* find the files already in the directory */
- dir = g_dir_open (filename, 0, error);
- if (dir == NULL)
- return FALSE;
- while ((tmp = g_dir_read_name (dir)) != NULL) {
- g_autofree gchar *fn = NULL;
- fn = g_build_filename (filename, tmp, NULL);
- g_debug ("adding existing file: %s", fn);
- _g_ptr_array_str_add (priv->files, fn);
+ dir = g_dir_open (filename, 0, NULL);
+ if (dir != NULL) {
+ while ((tmp = g_dir_read_name (dir)) != NULL) {
+ g_autofree gchar *fn = NULL;
+ fn = g_build_filename (filename, tmp, NULL);
+ g_debug ("adding existing file: %s", fn);
+ _g_ptr_array_str_add (priv->files, fn);
+ }
}
/* create new file monitor */
diff --git a/libappstream-glib/as-store.c b/libappstream-glib/as-store.c
index 467adef..43dc368 100644
--- a/libappstream-glib/as-store.c
+++ b/libappstream-glib/as-store.c
@@ -114,6 +114,14 @@ static gboolean as_store_from_file_internal (AsStore *store,
GCancellable *cancellable,
GError **error);
+static gboolean as_store_load_app_info_file (AsStore *store,
+ AsAppScope scope,
+ const gchar *path_xml,
+ const gchar *arch,
+ AsStoreLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error);
+
static void
as_store_finalize (GObject *object)
{
@@ -1547,6 +1555,61 @@ as_store_remove_by_source_file (AsStore *store, const gchar *filename)
as_store_perhaps_emit_changed (store, "remove-by-source-file");
}
+static gboolean
+as_store_search_dir (AsStore *store,
+ AsAppScope scope,
+ const gchar *path,
+ const gchar *arch,
+ AsStoreLoadFlags flags,
+ GCancellable *cancellable,
+ GError **error)
+{
+ AsStorePrivate *priv = GET_PRIVATE (store);
+ const gchar *tmp;
+ g_autoptr(GDir) dir = NULL;
+ g_autoptr(GError) error_local = NULL;
+
+ dir = g_dir_open (path, 0, &error_local);
+ if (dir == NULL) {
+ if (flags & AS_STORE_LOAD_FLAG_IGNORE_INVALID) {
+ g_warning ("ignoring invalid AppStream path %s: %s",
+ path, error_local->message);
+ return TRUE;
+ }
+ g_set_error (error,
+ AS_STORE_ERROR,
+ AS_STORE_ERROR_FAILED,
+ "Failed to open %s: %s",
+ path, error_local->message);
+ return FALSE;
+ }
+
+ while ((tmp = g_dir_read_name (dir)) != NULL) {
+ GError *error_store = NULL;
+ g_autofree gchar *filename_md = NULL;
+ if (g_strcmp0 (tmp, "icons") == 0)
+ continue;
+ filename_md = g_build_filename (path, tmp, NULL);
+ if (!as_store_load_app_info_file (store,
+ scope,
+ filename_md,
+ arch,
+ flags,
+ cancellable,
+ &error_store)) {
+ if (flags & AS_STORE_LOAD_FLAG_IGNORE_INVALID) {
+ g_warning ("Ignoring invalid AppStream file %s: %s",
+ filename_md, error_store->message);
+ g_clear_error (&error_store);
+ } else {
+ g_propagate_error (error, error_store);
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
static void
as_store_watch_source_added (AsStore *store, const gchar *filename)
{
@@ -1556,9 +1619,26 @@ as_store_watch_source_added (AsStore *store, const gchar *filename)
g_autoptr(GError) error = NULL;
g_autoptr(GFile) file = NULL;
- /* ignore directories */
- if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+ /* search added directories */
+ if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR)) {
+ g_debug ("parsing files from directory %s", filename);
+ path_data = g_hash_table_lookup (priv->appinfo_dirs, filename);
+ if (path_data == NULL) {
+ g_warning ("no path data for %s", filename);
+ return;
+ }
+
+ if (!as_store_search_dir (store, path_data->scope,
+ filename,
+ path_data->arch,
+ AS_STORE_LOAD_FLAG_IGNORE_INVALID,
+ NULL, /* cancellable */
+ &error)) {
+ g_warning ("failed to search dir: %s", error->message);
+ }
+
return;
+ }
/* we helpfully saved this */
dirname = g_path_get_dirname (filename);
@@ -1655,11 +1735,6 @@ as_store_add_path_data (AsStore *store,
AsStorePrivate *priv = GET_PRIVATE (store);
AsStorePathData *path_data;
- /* don't scan non-existent directories */
- if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
- return;
- }
-
/* check not already exists */
path_data = g_hash_table_lookup (priv->appinfo_dirs, path);
if (path_data != NULL) {
@@ -2455,45 +2530,12 @@ as_store_load_app_info (AsStore *store,
tok = as_store_changed_inhibit (store);
/* search all files */
- if (!g_file_test (path, G_FILE_TEST_EXISTS))
+ if (g_file_test (path, G_FILE_TEST_EXISTS)) {
+ if (!as_store_search_dir (store, scope, path, arch, flags,
+ cancellable, error))
+ return FALSE;
+ } else if ((flags & AS_STORE_LOAD_FLAG_WATCH_MISSING_PATHS) == 0) {
return TRUE;
- dir = g_dir_open (path, 0, &error_local);
- if (dir == NULL) {
- if (flags & AS_STORE_LOAD_FLAG_IGNORE_INVALID) {
- g_warning ("ignoring invalid AppStream path %s: %s",
- path, error_local->message);
- return TRUE;
- }
- g_set_error (error,
- AS_STORE_ERROR,
- AS_STORE_ERROR_FAILED,
- "Failed to open %s: %s",
- path, error_local->message);
- return FALSE;
- }
-
- while ((tmp = g_dir_read_name (dir)) != NULL) {
- GError *error_store = NULL;
- g_autofree gchar *filename_md = NULL;
- if (g_strcmp0 (tmp, "icons") == 0)
- continue;
- filename_md = g_build_filename (path, tmp, NULL);
- if (!as_store_load_app_info_file (store,
- scope,
- filename_md,
- arch,
- flags,
- cancellable,
- &error_store)) {
- if (flags & AS_STORE_LOAD_FLAG_IGNORE_INVALID) {
- g_warning ("Ignoring invalid AppStream file %s: %s",
- filename_md, error_store->message);
- g_clear_error (&error_store);
- } else {
- g_propagate_error (error, error_store);
- return FALSE;
- }
- }
}
/* watch the directories for changes */
@@ -2715,7 +2757,8 @@ as_store_search_app_info (AsStore *store,
path,
supported_kinds[i],
NULL);
- if (!g_file_test (dest, G_FILE_TEST_EXISTS))
+ if (!g_file_test (dest, G_FILE_TEST_EXISTS) &&
+ (flags & AS_STORE_LOAD_FLAG_WATCH_MISSING_PATHS) == 0)
continue;
if (!as_store_load_app_info (store, scope, dest, NULL,
flags, cancellable, error))
@@ -2783,6 +2826,8 @@ as_store_search_per_system (AsStore *store,
if ((flags & AS_STORE_LOAD_FLAG_APP_INFO_SYSTEM) > 0) {
g_autofree gchar *dest1 = NULL;
g_autofree gchar *dest2 = NULL;
+ /* watch these paths even if they do not exist */
+ flags |= AS_STORE_LOAD_FLAG_WATCH_MISSING_PATHS;
dest1 = g_build_filename (LOCALSTATEDIR, "lib", "app-info", NULL);
if (!as_store_search_app_info (store, flags, AS_APP_SCOPE_SYSTEM, dest1,
cancellable, error))
diff --git a/libappstream-glib/as-store.h b/libappstream-glib/as-store.h
index 55338e4..0ecf524 100644
--- a/libappstream-glib/as-store.h
+++ b/libappstream-glib/as-store.h
@@ -65,6 +65,7 @@ struct _AsStoreClass
* @AS_STORE_LOAD_FLAG_IGNORE_INVALID: Ignore invalid files
* @AS_STORE_LOAD_FLAG_ONLY_UNCOMPRESSED: Ignore compressed files
* @AS_STORE_LOAD_FLAG_ONLY_MERGE_APPS: Ignore non-wildcard matches
+ * @AS_STORE_LOAD_FLAG_WATCH_MISSING_PATHS: Monitor paths even if they do not exist
*
* The flags to use when loading the store.
**/
@@ -81,6 +82,7 @@ typedef enum {
AS_STORE_LOAD_FLAG_IGNORE_INVALID = 1 << 8, /* Since: 0.5.8 */
AS_STORE_LOAD_FLAG_ONLY_UNCOMPRESSED = 1 << 9, /* Since: 0.6.4 */
AS_STORE_LOAD_FLAG_ONLY_MERGE_APPS = 1 << 10, /* Since: 0.6.4 */
+ AS_STORE_LOAD_FLAG_WATCH_MISSING_PATHS = 1 << 11, /* Since: 0.6.45 */
/*< private >*/
AS_STORE_LOAD_FLAG_LAST
} AsStoreLoadFlags;