diff options
-rw-r--r-- | app/xdg-app-builtins-install.c | 8 | ||||
-rw-r--r-- | app/xdg-app-builtins-update.c | 11 | ||||
-rw-r--r-- | common/xdg-app-dir.c | 234 | ||||
-rw-r--r-- | common/xdg-app-dir.h | 10 | ||||
-rw-r--r-- | doc/xdg-app-install.xml | 9 | ||||
-rw-r--r-- | doc/xdg-app-update.xml | 10 | ||||
-rw-r--r-- | lib/xdg-app-installation.c | 14 | ||||
-rw-r--r-- | lib/xdg-app-installed-ref-private.h | 1 | ||||
-rw-r--r-- | lib/xdg-app-installed-ref.c | 27 | ||||
-rw-r--r-- | lib/xdg-app-installed-ref.h | 13 |
10 files changed, 305 insertions, 32 deletions
diff --git a/app/xdg-app-builtins-install.c b/app/xdg-app-builtins-install.c index 73ec2bc..e8634a6 100644 --- a/app/xdg-app-builtins-install.c +++ b/app/xdg-app-builtins-install.c @@ -36,6 +36,7 @@ static char *opt_arch; static char **opt_gpg_file; +static char **opt_subpaths; static gboolean opt_no_pull; static gboolean opt_no_deploy; static gboolean opt_runtime; @@ -50,6 +51,7 @@ static GOptionEntry options[] = { { "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, "Look for app with the specified name", }, { "bundle", 0, 0, G_OPTION_ARG_NONE, &opt_bundle, "Install from local bundle file", }, { "gpg-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, "Check bundle signatures with GPG key from FILE (- for stdin)", "FILE" }, + { "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only install this subpath", "path" }, { NULL } }; @@ -286,7 +288,7 @@ xdg_app_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro if (!opt_no_pull) { - if (!xdg_app_dir_pull (dir, repository, ref, NULL, + if (!xdg_app_dir_pull (dir, repository, ref, opt_subpaths, NULL, cancellable, error)) return FALSE; } @@ -306,6 +308,10 @@ xdg_app_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro if (!xdg_app_dir_set_origin (dir, ref, repository, cancellable, error)) goto out; + if (!xdg_app_dir_set_subpaths (dir, ref, (const char **)opt_subpaths, + cancellable, error)) + goto out; + if (!xdg_app_dir_deploy (dir, ref, NULL, cancellable, error)) goto out; diff --git a/app/xdg-app-builtins-update.c b/app/xdg-app-builtins-update.c index 5903973..15a1475 100644 --- a/app/xdg-app-builtins-update.c +++ b/app/xdg-app-builtins-update.c @@ -33,6 +33,7 @@ static char *opt_arch; static char *opt_commit; +static char **opt_subpaths; static gboolean opt_force_remove; static gboolean opt_no_pull; static gboolean opt_no_deploy; @@ -49,6 +50,7 @@ static GOptionEntry options[] = { { "runtime", 0, 0, G_OPTION_ARG_NONE, &opt_runtime, "Look for runtime with the specified name", }, { "app", 0, 0, G_OPTION_ARG_NONE, &opt_app, "Look for app with the specified name", }, { "appstream", 0, 0, G_OPTION_ARG_NONE, &opt_appstream, "Update appstream for remote", }, + { "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, "Only update this subpath", "path" }, { NULL } }; @@ -75,6 +77,7 @@ do_update (XdgAppDir* dir, { g_autofree char *ref = NULL; g_autofree char *repository = NULL; + g_auto(GStrv) subpaths = NULL; gboolean was_updated = FALSE; gboolean is_app; g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT; @@ -92,10 +95,14 @@ do_update (XdgAppDir* dir, if (repository == NULL) return FALSE; + subpaths = xdg_app_dir_get_subpaths (dir, ref, cancellable, error); + if (subpaths == NULL) + return FALSE; + if (!opt_no_pull) { - if (!xdg_app_dir_pull (dir, repository, ref, NULL, - cancellable, error)) + if (!xdg_app_dir_pull (dir, repository, ref, opt_subpaths ? opt_subpaths : subpaths, + NULL, cancellable, error)) return FALSE; } diff --git a/common/xdg-app-dir.c b/common/xdg-app-dir.c index 6d3ce82..6cb2672 100644 --- a/common/xdg-app-dir.c +++ b/common/xdg-app-dir.c @@ -521,6 +521,80 @@ xdg_app_dir_set_origin (XdgAppDir *self, return TRUE; } +char ** +xdg_app_dir_get_subpaths (XdgAppDir *self, + const char *ref, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GFile) deploy_base = NULL; + g_autoptr(GFile) file = NULL; + g_autofree char *data = NULL; + g_autoptr(GError) my_error = NULL; + g_autoptr(GPtrArray) subpaths = NULL; + g_auto(GStrv) lines = NULL; + int i; + + deploy_base = xdg_app_dir_get_deploy_dir (self, ref); + if (!g_file_query_exists (deploy_base, cancellable)) + { + xdg_app_fail (error, "%s is not installed", ref); + return NULL; + } + + file = g_file_get_child (deploy_base, "subpaths"); + if (!g_file_load_contents (file, cancellable, &data, NULL, NULL, &my_error)) + { + if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) + data = g_strdup (""); + else + g_propagate_error (error, g_steal_pointer (&my_error)); + + return NULL; + } + + lines = g_strsplit (data, "\n", 0); + + subpaths = g_ptr_array_new (); + for (i = 0; lines[i] != NULL; i++) + { + lines[i] = g_strstrip (lines[i]); + if (lines[i][0] == '/') + g_ptr_array_add (subpaths, g_strdup (lines[i])); + } + + g_ptr_array_add (subpaths, NULL); + return (char **)g_ptr_array_free (subpaths, FALSE); +} + +gboolean +xdg_app_dir_set_subpaths (XdgAppDir *self, + const char *ref, + const char **subpaths, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GFile) deploy_base = NULL; + g_autoptr(GFile) file = NULL; + g_autofree char *data = NULL; + + deploy_base = xdg_app_dir_get_deploy_dir (self, ref); + if (!g_file_query_exists (deploy_base, cancellable)) + { + xdg_app_fail (error, "%s is not installed", ref); + return FALSE; + } + + data = g_strjoinv ("\n", (char **)subpaths); + + file = g_file_get_child (deploy_base, "subpaths"); + if (!g_file_replace_contents (file, data, strlen (data), NULL, FALSE, + G_FILE_CREATE_NONE, NULL, cancellable, error)) + return FALSE; + + return TRUE; +} + gboolean xdg_app_dir_ensure_path (XdgAppDir *self, GCancellable *cancellable, @@ -690,7 +764,7 @@ xdg_app_dir_update_appstream (XdgAppDir *self, if (!ostree_repo_resolve_rev (self->repo, remote_and_branch, TRUE, &old_checksum, error)) return FALSE; - if (!xdg_app_dir_pull (self, remote, branch, progress, + if (!xdg_app_dir_pull (self, remote, branch, NULL, progress, cancellable, error)) return FALSE; @@ -785,10 +859,45 @@ xdg_app_dir_update_appstream (XdgAppDir *self, return TRUE; } +/* This is a copy of ostree_repo_pull_one_dir that always disables + static deltas if subdir is used */ +static gboolean +repo_pull_one_dir (OstreeRepo *self, + const char *remote_name, + const char *dir_to_pull, + char **refs_to_fetch, + OstreeRepoPullFlags flags, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error) +{ + GVariantBuilder builder; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + if (dir_to_pull) + { + g_variant_builder_add (&builder, "{s@v}", "subdir", + g_variant_new_variant (g_variant_new_string (dir_to_pull))); + g_variant_builder_add (&builder, "{s@v}", "disable-static-deltas", + g_variant_new_variant (g_variant_new_boolean (TRUE))); + } + + g_variant_builder_add (&builder, "{s@v}", "flags", + g_variant_new_variant (g_variant_new_int32 (flags))); + if (refs_to_fetch) + g_variant_builder_add (&builder, "{s@v}", "refs", + g_variant_new_variant (g_variant_new_strv ((const char *const*) refs_to_fetch, -1))); + + return ostree_repo_pull_with_options (self, remote_name, g_variant_builder_end (&builder), + progress, cancellable, error); +} + + gboolean xdg_app_dir_pull (XdgAppDir *self, const char *repository, const char *ref, + char **subpaths, OstreeAsyncProgress *progress, GCancellable *cancellable, GError **error) @@ -825,13 +934,46 @@ xdg_app_dir_pull (XdgAppDir *self, refs[0] = ref; refs[1] = NULL; - if (!ostree_repo_pull (self->repo, repository, - (char **)refs, OSTREE_REPO_PULL_FLAGS_NONE, - progress, - cancellable, error)) + if (subpaths == NULL || subpaths[0] == NULL) { - g_prefix_error (error, "While pulling %s from remote %s: ", ref, repository); - goto out; + if (!ostree_repo_pull (self->repo, repository, + (char **)refs, OSTREE_REPO_PULL_FLAGS_NONE, + progress, + cancellable, error)) + { + g_prefix_error (error, "While pulling %s from remote %s: ", ref, repository); + goto out; + } + } + else + { + int i; + + if (!repo_pull_one_dir (self->repo, repository, + "/metadata", + (char **)refs, OSTREE_REPO_PULL_FLAGS_NONE, + progress, + cancellable, error)) + { + g_prefix_error (error, "While pulling %s from remote %s, metadata: ", + ref, repository); + goto out; + } + + for (i = 0; subpaths[i] != NULL; i++) + { + g_autofree char *subpath = g_build_filename ("/files", subpaths[i], NULL); + if (!repo_pull_one_dir (self->repo, repository, + subpath, + (char **)refs, OSTREE_REPO_PULL_FLAGS_NONE, + progress, + cancellable, error)) + { + g_prefix_error (error, "While pulling %s from remote %s, subpath %s: ", + ref, repository, subpaths[i]); + goto out; + } + } } ret = TRUE; @@ -1916,6 +2058,7 @@ xdg_app_dir_deploy (XdgAppDir *self, g_autoptr(GFile) export = NULL; g_autoptr(OstreeAsyncProgress) progress = NULL; g_autoptr(GKeyFile) keyfile = NULL; + g_auto(GStrv) subpaths = NULL; if (!xdg_app_dir_ensure_repo (self, cancellable, error)) return FALSE; @@ -1969,20 +2112,73 @@ xdg_app_dir_deploy (XdgAppDir *self, if (file_info == NULL) return FALSE; - if (!ostree_repo_checkout_tree (self->repo, - OSTREE_REPO_CHECKOUT_MODE_USER, - OSTREE_REPO_CHECKOUT_OVERWRITE_NONE, - checkoutdir, - OSTREE_REPO_FILE (root), file_info, - cancellable, error)) + subpaths = xdg_app_dir_get_subpaths (self, ref, cancellable, error); + if (subpaths == NULL) + return FALSE; + + if (*subpaths == NULL) { - g_autofree char *rootpath = NULL; - g_autofree char *checkoutpath = NULL; + if (!ostree_repo_checkout_tree (self->repo, + OSTREE_REPO_CHECKOUT_MODE_USER, + OSTREE_REPO_CHECKOUT_OVERWRITE_NONE, + checkoutdir, + OSTREE_REPO_FILE (root), file_info, + cancellable, error)) + { + g_autofree char *rootpath = NULL; + g_autofree char *checkoutpath = NULL; - rootpath = g_file_get_path (root); - checkoutpath = g_file_get_path (checkoutdir); - g_prefix_error (error, "While trying to checkout %s into %s: ", rootpath, checkoutpath); - return FALSE; + rootpath = g_file_get_path (root); + checkoutpath = g_file_get_path (checkoutdir); + g_prefix_error (error, "While trying to checkout %s into %s: ", rootpath, checkoutpath); + return FALSE; + } + } + else + { + OstreeRepoCheckoutOptions options = { 0, }; + g_autofree char *checkoutdirpath = g_file_get_path (checkoutdir); + g_autoptr(GFile) files = g_file_get_child (checkoutdir, "files"); + int i; + + if (!g_file_make_directory_with_parents (files, cancellable, error)) + return FALSE; + + options.mode = OSTREE_REPO_CHECKOUT_MODE_USER; + options.overwrite_mode = OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES; + options.subpath = "/metadata"; + + access ("checkout metadata", 0); + if (!ostree_repo_checkout_tree_at (self->repo, &options, + AT_FDCWD, checkoutdirpath, + checksum, + cancellable, error)) + { + g_prefix_error (error, "While trying to checkout metadata subpath: "); + return FALSE; + } + + for (i = 0; subpaths[i] != NULL; i++) + { + g_autofree char *subpath = g_build_filename ("/files", subpaths[i], NULL); + g_autofree char *dstpath = g_build_filename (checkoutdirpath, "/files", subpaths[i], NULL); + g_autofree char *dstpath_parent = g_path_get_dirname (dstpath); + if (g_mkdir_with_parents (dstpath_parent, 0755)) + { + glnx_set_error_from_errno (error); + return FALSE; + } + + options.subpath = subpath; + if (!ostree_repo_checkout_tree_at (self->repo, &options, + AT_FDCWD, dstpath, + checksum, + cancellable, error)) + { + g_prefix_error (error, "While trying to checkout metadata subpath: "); + return FALSE; + } + } } dotref = g_file_resolve_relative_path (checkoutdir, "files/.ref"); diff --git a/common/xdg-app-dir.h b/common/xdg-app-dir.h index 8d73df1..6319921 100644 --- a/common/xdg-app-dir.h +++ b/common/xdg-app-dir.h @@ -88,6 +88,15 @@ gboolean xdg_app_dir_set_origin (XdgAppDir *self, const char *remote, GCancellable *cancellable, GError **error); +char ** xdg_app_dir_get_subpaths (XdgAppDir *self, + const char *ref, + GCancellable *cancellable, + GError **error); +gboolean xdg_app_dir_set_subpaths (XdgAppDir *self, + const char *ref, + const char **subpaths, + GCancellable *cancellable, + GError **error); GFile * xdg_app_dir_get_exports_dir (XdgAppDir *self); GFile * xdg_app_dir_get_removed_dir (XdgAppDir *self); GFile * xdg_app_dir_get_if_deployed (XdgAppDir *self, @@ -144,6 +153,7 @@ gboolean xdg_app_dir_update_appstream(XdgAppDir *self, gboolean xdg_app_dir_pull (XdgAppDir *self, const char *repository, const char *ref, + char **subpaths, OstreeAsyncProgress *progress, GCancellable *cancellable, GError **error); diff --git a/doc/xdg-app-install.xml b/doc/xdg-app-install.xml index d15016f..0803a9c 100644 --- a/doc/xdg-app-install.xml +++ b/doc/xdg-app-install.xml @@ -105,6 +105,15 @@ </varlistentry> <varlistentry> + <term><option>--subpath=PATH</option></term> + + <listitem><para> + Install only a subpath of the ref. This is mainly used to install a subset of locales. + This can be added multiple times to install multiple subpaths., + </para></listitem> + </varlistentry> + + <varlistentry> <term><option>--no-deploy</option></term> <listitem><para> diff --git a/doc/xdg-app-update.xml b/doc/xdg-app-update.xml index f665160..8c29342 100644 --- a/doc/xdg-app-update.xml +++ b/doc/xdg-app-update.xml @@ -112,6 +112,16 @@ </varlistentry> <varlistentry> + <term><option>--subpath=PATH</option></term> + + <listitem><para> + Install only a subpath of the ref. This is mainly used to install a subset of locales. + This can be added multiple times to install multiple subpaths. + If this is not specified the subpaths specified at install time are reused. + </para></listitem> + </varlistentry> + + <varlistentry> <term><option>--commit=COMMIT</option></term> <listitem><para> diff --git a/lib/xdg-app-installation.c b/lib/xdg-app-installation.c index 3ca83b5..0219be4 100644 --- a/lib/xdg-app-installation.c +++ b/lib/xdg-app-installation.c @@ -290,6 +290,7 @@ get_ref (XdgAppInstallation *self, g_autoptr(GFile) deploy_subdir = NULL; g_autofree char *deploy_path = NULL; g_autofree char *latest_commit = NULL; + g_auto(GStrv) subpaths = NULL; gboolean is_current = FALSE; guint64 installed_size = 0; @@ -297,6 +298,8 @@ get_ref (XdgAppInstallation *self, origin = xdg_app_dir_get_origin (priv->dir, full_ref, NULL, NULL); commit = xdg_app_dir_read_active (priv->dir, full_ref, cancellable); + subpaths = xdg_app_dir_get_subpaths (priv->dir, full_ref, cancellable, NULL); + deploy_dir = xdg_app_dir_get_deploy_dir (priv->dir, full_ref); if (deploy_dir && commit) { @@ -323,7 +326,7 @@ get_ref (XdgAppInstallation *self, return xdg_app_installed_ref_new (full_ref, commit, latest_commit, - origin, + origin, subpaths, deploy_path, installed_size, is_current); @@ -992,7 +995,7 @@ xdg_app_installation_install (XdgAppInstallation *self, g_object_set_data (G_OBJECT (ostree_progress), "last_progress", GUINT_TO_POINTER(0)); } - if (!xdg_app_dir_pull (dir_clone, remote_name, ref, + if (!xdg_app_dir_pull (dir_clone, remote_name, ref, NULL, ostree_progress, cancellable, error)) goto out; @@ -1088,6 +1091,7 @@ xdg_app_installation_update (XdgAppInstallation *self, XdgAppInstalledRef *result = NULL; gboolean was_updated = FALSE; g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT; + g_auto(GStrv) subpaths = NULL; ref = xdg_app_compose_ref (kind == XDG_APP_REF_KIND_APP, name, branch, arch, error); if (ref == NULL) @@ -1106,6 +1110,10 @@ xdg_app_installation_update (XdgAppInstallation *self, if (remote_name == NULL) return NULL; + subpaths = xdg_app_dir_get_subpaths (priv->dir, ref, cancellable, error); + if (subpaths == NULL) + return FALSE; + /* Pull, prune, etc are not threadsafe, so we work on a copy */ dir_clone = xdg_app_dir_clone (priv->dir); @@ -1122,7 +1130,7 @@ xdg_app_installation_update (XdgAppInstallation *self, if ((flags & XDG_APP_UPDATE_FLAGS_NO_PULL) == 0) { - if (!xdg_app_dir_pull (dir_clone, remote_name, ref, + if (!xdg_app_dir_pull (dir_clone, remote_name, ref, subpaths, ostree_progress, cancellable, error)) goto out; } diff --git a/lib/xdg-app-installed-ref-private.h b/lib/xdg-app-installed-ref-private.h index c192aa6..3b7bb59 100644 --- a/lib/xdg-app-installed-ref-private.h +++ b/lib/xdg-app-installed-ref-private.h @@ -32,6 +32,7 @@ XdgAppInstalledRef *xdg_app_installed_ref_new (const char *full_ref, const char *commit, const char *latest_commit, const char *origin, + char **subpaths, const char *deploy_dir, guint64 installed_size, gboolean current); diff --git a/lib/xdg-app-installed-ref.c b/lib/xdg-app-installed-ref.c index da29742..853dc7b 100644 --- a/lib/xdg-app-installed-ref.c +++ b/lib/xdg-app-installed-ref.c @@ -44,6 +44,7 @@ struct _XdgAppInstalledRefPrivate char *origin; char *latest_commit; char *deploy_dir; + char **subpaths; guint64 installed_size; }; @@ -56,7 +57,8 @@ enum { PROP_ORIGIN, PROP_LATEST_COMMIT, PROP_DEPLOY_DIR, - PROP_INSTALLED_SIZE + PROP_INSTALLED_SIZE, + PROP_SUBPATHS }; static void @@ -67,6 +69,7 @@ xdg_app_installed_ref_finalize (GObject *object) g_free (priv->origin); g_free (priv->deploy_dir); + g_strfreev (priv->subpaths); G_OBJECT_CLASS (xdg_app_installed_ref_parent_class)->finalize (object); } @@ -105,6 +108,11 @@ xdg_app_installed_ref_set_property (GObject *object, priv->deploy_dir = g_value_dup_string (value); break; + case PROP_SUBPATHS: + g_clear_pointer (&priv->subpaths, g_strfreev); + priv->subpaths = g_strdupv (g_value_get_boxed (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -142,6 +150,10 @@ xdg_app_installed_ref_get_property (GObject *object, g_value_set_string (value, priv->deploy_dir); break; + case PROP_SUBPATHS: + g_value_set_boxed (value, priv->subpaths); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -192,6 +204,13 @@ xdg_app_installed_ref_class_init (XdgAppInstalledRefClass *klass) "Where the application is installed", NULL, G_PARAM_READWRITE)); + g_object_class_install_property (object_class, + PROP_SUBPATHS, + g_param_spec_boxed ("subpaths", + "", + "", + G_TYPE_STRV, + G_PARAM_READWRITE)); } static void @@ -319,6 +338,7 @@ xdg_app_installed_ref_new (const char *full_ref, const char *commit, const char *latest_commit, const char *origin, + char **subpaths, const char *deploy_dir, guint64 installed_size, gboolean is_current) @@ -332,6 +352,10 @@ xdg_app_installed_ref_new (const char *full_ref, if (strcmp (parts[0], "app") != 0) kind = XDG_APP_REF_KIND_RUNTIME; + /* Canonicalize the "no subpaths" case */ + if (subpaths && *subpaths == NULL) + subpaths = NULL; + ref = g_object_new (XDG_APP_TYPE_INSTALLED_REF, "kind", kind, "name", parts[1], @@ -340,6 +364,7 @@ xdg_app_installed_ref_new (const char *full_ref, "commit", commit, "latest-commit", latest_commit, "origin", origin, + "subpaths", subpaths, "is-current", is_current, "installed-size", installed_size, "deploy-dir", deploy_dir, diff --git a/lib/xdg-app-installed-ref.h b/lib/xdg-app-installed-ref.h index 624bf8a..3fdf069 100644 --- a/lib/xdg-app-installed-ref.h +++ b/lib/xdg-app-installed-ref.h @@ -48,12 +48,13 @@ typedef struct { G_DEFINE_AUTOPTR_CLEANUP_FUNC(XdgAppInstalledRef, g_object_unref) #endif -XDG_APP_EXTERN const char *xdg_app_installed_ref_get_origin (XdgAppInstalledRef *self); -XDG_APP_EXTERN guint64 xdg_app_installed_ref_get_installed_size (XdgAppInstalledRef *self); -XDG_APP_EXTERN const char *xdg_app_installed_ref_get_deploy_dir (XdgAppInstalledRef *self); -XDG_APP_EXTERN const char *xdg_app_installed_ref_get_latest_commit (XdgAppInstalledRef *self); -XDG_APP_EXTERN gboolean xdg_app_installed_ref_get_is_current (XdgAppInstalledRef *self); -XDG_APP_EXTERN GBytes *xdg_app_installed_ref_load_metadata (XdgAppInstalledRef *self, +XDG_APP_EXTERN const char *xdg_app_installed_ref_get_origin (XdgAppInstalledRef *self); +XDG_APP_EXTERN const char **xdg_app_installed_ref_get_subpaths (XdgAppInstalledRef *self); +XDG_APP_EXTERN guint64 xdg_app_installed_ref_get_installed_size (XdgAppInstalledRef *self); +XDG_APP_EXTERN const char *xdg_app_installed_ref_get_deploy_dir (XdgAppInstalledRef *self); +XDG_APP_EXTERN const char *xdg_app_installed_ref_get_latest_commit (XdgAppInstalledRef *self); +XDG_APP_EXTERN gboolean xdg_app_installed_ref_get_is_current (XdgAppInstalledRef *self); +XDG_APP_EXTERN GBytes *xdg_app_installed_ref_load_metadata (XdgAppInstalledRef *self, GCancellable *cancellable, GError **error); |