diff --git a/app/xdg-app-builtins-update.c b/app/xdg-app-builtins-update.c index a5aa0d85..42802878 100644 --- a/app/xdg-app-builtins-update.c +++ b/app/xdg-app-builtins-update.c @@ -106,7 +106,7 @@ do_update (XdgAppDir* dir, if (!opt_no_deploy) { - if (!xdg_app_dir_deploy_update (dir, ref, opt_commit, cancellable, error)) + if (!xdg_app_dir_deploy_update (dir, ref, repository, opt_commit, cancellable, error)) return FALSE; } diff --git a/common/xdg-app-dir.c b/common/xdg-app-dir.c index cedeb8cf..a2bf8b3c 100644 --- a/common/xdg-app-dir.c +++ b/common/xdg-app-dir.c @@ -79,6 +79,8 @@ enum { PROP_PATH }; +G_DEFINE_AUTOPTR_CLEANUP_FUNC(XdgAppSystemHelper, g_object_unref) + #define OSTREE_GIO_FAST_QUERYINFO ("standard::name,standard::type,standard::size,standard::is-symlink,standard::symlink-target," \ "unix::device,unix::inode,unix::mode,unix::uid,unix::gid,unix::rdev") @@ -2541,6 +2543,41 @@ xdg_app_dir_deploy_install (XdgAppDir *self, g_autoptr(GError) local_error = NULL; g_auto(GStrv) ref_parts = g_strsplit (ref, "/", -1); + if (self->child_repo) + { + char *empty_subpaths[] = {NULL}; + g_autoptr(XdgAppSystemHelper) helper = NULL; + + helper = xdg_app_system_helper_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + "org.freedesktop.XdgApp.SystemHelper", + "/org/freedesktop/XdgApp/SystemHelper", + cancellable, + error); + if (helper == NULL) + return FALSE; + + if (!xdg_app_system_helper_call_deploy_sync (helper, + gs_file_get_path_cached (ostree_repo_get_path (self->child_repo)), + XDG_APP_HELPER_DEPLOY_FLAGS_NONE, + ref, + origin, + (const char *const *)(subpaths ? subpaths : empty_subpaths), + cancellable, + error)) + return FALSE; + + (void) glnx_shutil_rm_rf_at (AT_FDCWD, + gs_file_get_path_cached (ostree_repo_get_path (self->child_repo)), + NULL, NULL); + + g_clear_object (&self->child_repo); + glnx_release_lock_file (&self->child_repo_lock); + + return TRUE; + } + if (!xdg_app_dir_lock (self, &lock, cancellable, error)) goto out; @@ -2603,6 +2640,7 @@ xdg_app_dir_deploy_install (XdgAppDir *self, gboolean xdg_app_dir_deploy_update (XdgAppDir *self, const char *ref, + const char *remote_name, const char *checksum_or_latest, GCancellable *cancellable, GError **error) @@ -2611,6 +2649,54 @@ xdg_app_dir_deploy_update (XdgAppDir *self, g_autoptr(GError) my_error = NULL; g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT; + if (self->child_repo) + { + char *empty_subpaths[] = {NULL}; + g_autofree char *pulled_checksum = NULL; + g_autofree char *active_checksum = NULL; + g_autofree char *remote_and_ref = NULL; + g_autoptr(XdgAppSystemHelper) helper = NULL; + + if (checksum_or_latest != NULL) + return xdg_app_fail (error, "Can't update to a specific commit without root permissions"); + + if (!ostree_repo_resolve_rev (self->child_repo, ref, FALSE, &pulled_checksum, error)) + return FALSE; + + active_checksum = xdg_app_dir_read_active (self, ref, NULL); + if (active_checksum == NULL || strcmp (active_checksum, pulled_checksum) != 0) + { + helper = xdg_app_system_helper_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, + "org.freedesktop.XdgApp.SystemHelper", + "/org/freedesktop/XdgApp/SystemHelper", + cancellable, + error); + if (helper == NULL) + return FALSE; + + if (!xdg_app_system_helper_call_deploy_sync (helper, + gs_file_get_path_cached (ostree_repo_get_path (self->child_repo)), + XDG_APP_HELPER_DEPLOY_FLAGS_UPDATE, + ref, + remote_name, + (const char *const *)empty_subpaths, + cancellable, + error)) + return FALSE; + } + + (void) glnx_shutil_rm_rf_at (AT_FDCWD, + gs_file_get_path_cached (ostree_repo_get_path (self->child_repo)), + NULL, NULL); + + g_clear_object (&self->child_repo); + glnx_release_lock_file (&self->child_repo_lock); + + return TRUE; + } + if (!xdg_app_dir_lock (self, &lock, cancellable, error)) return FALSE; @@ -3189,7 +3275,7 @@ xdg_app_dir_find_remote_ref (XdgAppDir *self, return NULL; } - summary = g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT, summary_bytes, FALSE); + summary = g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT, summary_bytes, FALSE)); refs = g_variant_get_child_value (summary, 0); if (app_ref && xdg_app_summary_lookup_ref (summary, app_ref, NULL)) diff --git a/common/xdg-app-dir.h b/common/xdg-app-dir.h index f94f59fa..9a6bd473 100644 --- a/common/xdg-app-dir.h +++ b/common/xdg-app-dir.h @@ -48,6 +48,13 @@ typedef enum { XDG_APP_DIR_ERROR_NOT_DEPLOYED, } XdgAppDirErrorEnum; +typedef enum { + XDG_APP_HELPER_DEPLOY_FLAGS_NONE = 0, + XDG_APP_HELPER_DEPLOY_FLAGS_UPDATE = 1<<0, +} XdgAppHelperDeployFlags; + +#define XDG_APP_HELPER_DEPLOY_FLAGS_ALL (XDG_APP_HELPER_DEPLOY_FLAGS_UPDATE) + GQuark xdg_app_dir_error_quark (void); GFile * xdg_app_get_system_base_dir_location (void); @@ -220,6 +227,7 @@ gboolean xdg_app_dir_deploy (XdgAppDir *self, GError **error); gboolean xdg_app_dir_deploy_update (XdgAppDir *self, const char *ref, + const char *origin, const char *checksum, GCancellable *cancellable, GError **error); diff --git a/data/org.freedesktop.XdgApp.xml b/data/org.freedesktop.XdgApp.xml index 6f77efc6..d90a6e0a 100644 --- a/data/org.freedesktop.XdgApp.xml +++ b/data/org.freedesktop.XdgApp.xml @@ -84,7 +84,11 @@ - + + + + + diff --git a/lib/xdg-app-installation.c b/lib/xdg-app-installation.c index d642b4a6..3da464f4 100644 --- a/lib/xdg-app-installation.c +++ b/lib/xdg-app-installation.c @@ -1061,7 +1061,7 @@ xdg_app_installation_update (XdgAppInstallation *self, if ((flags & XDG_APP_UPDATE_FLAGS_NO_DEPLOY) == 0) { - if (!xdg_app_dir_deploy_update (dir_clone, ref, NULL, + if (!xdg_app_dir_deploy_update (dir_clone, ref, remote_name, NULL, cancellable, error)) goto out; } diff --git a/system-helper/Makefile.am.inc b/system-helper/Makefile.am.inc index 0bd2c6c5..b14822a0 100644 --- a/system-helper/Makefile.am.inc +++ b/system-helper/Makefile.am.inc @@ -30,5 +30,5 @@ xdg_app_system_helper_SOURCES = \ system-helper/xdg-app-resources.c \ $(NULL) -xdg_app_system_helper_LDADD = $(BASE_LIBS) libxdgapp-common.la -xdg_app_system_helper_CFLAGS = $(BASE_CFLAGS) +xdg_app_system_helper_LDADD = $(BASE_LIBS) $(OSTREE_LIBS) libxdgapp-common.la +xdg_app_system_helper_CFLAGS = $(BASE_CFLAGS) $(OSTREE_CFLAGS) diff --git a/system-helper/xdg-app-system-helper.c b/system-helper/xdg-app-system-helper.c index 8f17a49d..67321d3e 100644 --- a/system-helper/xdg-app-system-helper.c +++ b/system-helper/xdg-app-system-helper.c @@ -26,13 +26,115 @@ #include #include "xdg-app-dbus.h" +#include "xdg-app-dir.h" static GDBusNodeInfo *introspection_data = NULL; -void -handle_deploy (void) +static gboolean +handle_deploy (XdgAppSystemHelper *object, + GDBusMethodInvocation *invocation, + const gchar *arg_repo_path, + guint32 arg_flags, + const gchar *arg_ref, + const gchar *arg_origin, + const gchar *const *arg_subpaths) { - g_print ("deploy!"); + g_autoptr(XdgAppDir) system = xdg_app_dir_get_system (); + g_autoptr(GFile) path = g_file_new_for_path (arg_repo_path); + g_autoptr(GError) error = NULL; + g_autoptr(GFile) deploy_dir = NULL; + gboolean is_update; + + is_update = (arg_flags & XDG_APP_HELPER_DEPLOY_FLAGS_UPDATE) != 0; + + if ((arg_flags & ~XDG_APP_HELPER_DEPLOY_FLAGS_ALL) != 0) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Unsupported flags enabled: 0x%x", (arg_flags & ~XDG_APP_HELPER_DEPLOY_FLAGS_ALL)); + } + + if (!g_file_query_exists (path, NULL)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "Path does not exist"); + return TRUE; + } + + deploy_dir = xdg_app_dir_get_if_deployed (system, arg_ref, + NULL, NULL); + + if (deploy_dir) + { + g_autofree char *real_origin = NULL; + if (!is_update) + { + /* Can't install already installed app */ + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "%s is already installed", arg_ref); + return TRUE; + } + + real_origin = xdg_app_dir_get_origin (system, arg_ref, NULL, NULL); + if (real_origin == NULL || strcmp (real_origin, arg_origin) != 0) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Wrong origin %s for update", arg_origin); + return TRUE; + } + } + else if (!deploy_dir && is_update) + { + /* Can't update not installed app */ + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "%s is not installed", arg_ref); + return TRUE; + } + + if (!xdg_app_dir_ensure_repo (system, NULL, &error)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Can't open system repo %s", error->message); + return TRUE; + } + + if (!xdg_app_dir_pull_untrusted_local (system, arg_repo_path, + arg_origin, + arg_ref, + (char **)arg_subpaths, + NULL, + NULL, &error)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Error pulling from repo: %s", error->message); + return TRUE; + } + + if (is_update) + { + /* TODO: This doesn't support a custom subpath */ + if (!xdg_app_dir_deploy_update (system, arg_ref, arg_origin, + NULL, + NULL, &error)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Error deploying: %s", error->message); + return TRUE; + } + } + else + { + if (!xdg_app_dir_deploy_install (system, arg_ref, arg_origin, + (char **)arg_subpaths, + NULL, &error)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED, + "Error deploying: %s", error->message); + return TRUE; + } + } + + xdg_app_system_helper_complete_deploy (object, invocation); + + return TRUE; } static void