summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2016-02-25 16:05:13 +0100
committerAlexander Larsson <alexl@redhat.com>2016-02-25 16:05:13 +0100
commit382ae396b3b2b2f91ea988571d5908bfc16dc01b (patch)
treee6da24a448cb0e418a917f1cfb557773e3dc6a43 /lib
parentcd13e9e21dc6931d0d7c485ba9d952eff1c19c3a (diff)
downloadxdg-app-382ae396b3b2b2f91ea988571d5908bfc16dc01b.tar.gz
lib: Add xdg_app_installation_install_bundle
Diffstat (limited to 'lib')
-rw-r--r--lib/xdg-app-bundle-ref.c8
-rw-r--r--lib/xdg-app-installation.c138
-rw-r--r--lib/xdg-app-installation.h6
3 files changed, 145 insertions, 7 deletions
diff --git a/lib/xdg-app-bundle-ref.c b/lib/xdg-app-bundle-ref.c
index 571c722..e370745 100644
--- a/lib/xdg-app-bundle-ref.c
+++ b/lib/xdg-app-bundle-ref.c
@@ -163,16 +163,10 @@ xdg_app_bundle_ref_new (GFile *file,
g_autofree char *full_ref = NULL;
g_autofree char *metadata_contents = NULL;
- metadata = xdg_app_bundle_load (file, &commit, error);
+ metadata = xdg_app_bundle_load (file, &commit, &full_ref, NULL, NULL, error);
if (metadata == NULL)
return NULL;
- if (!g_variant_lookup (metadata, "ref", "s", &full_ref))
- {
- xdg_app_fail (error, "Invalid bundle, no ref in metadata");
- return NULL;
- }
-
parts = xdg_app_decompose_ref (full_ref, error);
if (parts == NULL)
return NULL;
diff --git a/lib/xdg-app-installation.c b/lib/xdg-app-installation.c
index 63ad4ec..722c7f2 100644
--- a/lib/xdg-app-installation.c
+++ b/lib/xdg-app-installation.c
@@ -716,6 +716,144 @@ progress_cb (OstreeAsyncProgress *progress, gpointer user_data)
}
/**
+ * xdg_app_installation_install_bundle:
+ * @self: a #XdgAppInstallation
+ * @file: a #GFile that is an xdg-app bundle
+ * @progress: (scope call): progress callback
+ * @progress_data: user data passed to @progress
+ * @cancellable: (nullable): a #GCancellable
+ * @error: return location for a #GError
+ *
+ * Install a new ref from a bundle.
+ *
+ * Returns: (transfer full): The ref for the newly installed app or %NULL on failure
+ */
+XdgAppInstalledRef *
+xdg_app_installation_install_bundle (XdgAppInstallation *self,
+ GFile *file,
+ XdgAppProgressCallback progress,
+ gpointer progress_data,
+ GCancellable *cancellable,
+ GError **error)
+{
+ XdgAppInstallationPrivate *priv = xdg_app_installation_get_instance_private (self);
+ g_autofree char *ref = NULL;
+ gboolean created_deploy_base = FALSE;
+ gboolean added_remote = FALSE;
+ g_autoptr(GFile) deploy_base = NULL;
+ g_autoptr(XdgAppDir) dir_clone = NULL;
+ XdgAppInstalledRef *result = NULL;
+ g_autoptr(GError) local_error = NULL;
+ g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
+ g_autoptr(GVariant) metadata = NULL;
+ g_autofree char *origin = NULL;
+ g_auto(GStrv) parts = NULL;
+ g_autofree char *basename = NULL;
+ g_autoptr(GBytes) gpg_data = NULL;
+ g_autofree char *to_checksum = NULL;
+ g_autofree char *remote = NULL;
+
+ metadata = xdg_app_bundle_load (file, &to_checksum,
+ &ref,
+ &origin,
+ &gpg_data,
+ error);
+ if (metadata == NULL)
+ return FALSE;
+
+ parts = xdg_app_decompose_ref (ref, error);
+ if (parts == NULL)
+ return FALSE;
+
+ deploy_base = xdg_app_dir_get_deploy_dir (priv->dir, ref);
+
+ if (g_file_query_exists (deploy_base, cancellable))
+ {
+ g_set_error (error,
+ XDG_APP_ERROR, XDG_APP_ERROR_ALREADY_INSTALLED,
+ "%s branch %s already installed", parts[1], parts[3]);
+ return NULL;
+ }
+
+ /* Add a remote for later updates */
+ basename = g_file_get_basename (file);
+ remote = xdg_app_dir_create_origin_remote (priv->dir,
+ origin,
+ parts[1],
+ basename,
+ gpg_data,
+ cancellable,
+ error);
+ if (remote == NULL)
+ return FALSE;
+
+ /* From here we need to goto out on error, to clean up */
+ added_remote = TRUE;
+
+ /* Pull, prune, etc are not threadsafe, so we work on a copy */
+ dir_clone = xdg_app_dir_clone (priv->dir);
+
+ if (!xdg_app_dir_pull_from_bundle (dir_clone,
+ file,
+ remote,
+ ref,
+ gpg_data != NULL,
+ cancellable,
+ error))
+ goto out;
+
+ if (!xdg_app_dir_lock (dir_clone, &lock,
+ cancellable, error))
+ goto out;
+
+ if (!g_file_make_directory_with_parents (deploy_base, cancellable, &local_error))
+ {
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ g_set_error (error,
+ XDG_APP_ERROR, XDG_APP_ERROR_ALREADY_INSTALLED,
+ "%s branch %s already installed", parts[1], parts[3]);
+ else
+ g_propagate_error (error, g_steal_pointer (&local_error));
+ goto out;
+ }
+
+ created_deploy_base = TRUE;
+
+ if (!xdg_app_dir_set_origin (dir_clone, ref, remote, cancellable, error))
+ goto out;
+
+ if (!xdg_app_dir_deploy (dir_clone, ref, NULL, cancellable, error))
+ goto out;
+
+ if (strcmp (parts[0], "app") == 0)
+ {
+ if (!xdg_app_dir_make_current_ref (dir_clone, ref, cancellable, error))
+ goto out;
+
+ if (!xdg_app_dir_update_exports (dir_clone, parts[1], cancellable, error))
+ goto out;
+ }
+
+ result = get_ref (self, ref, cancellable);
+
+ glnx_release_lock_file (&lock);
+
+ xdg_app_dir_cleanup_removed (dir_clone, cancellable, NULL);
+
+ if (!xdg_app_dir_mark_changed (dir_clone, error))
+ goto out;
+
+ out:
+ if (created_deploy_base && result == NULL)
+ gs_shutil_rm_rf (deploy_base, cancellable, NULL);
+
+ if (added_remote && result == NULL)
+ ostree_repo_remote_delete (xdg_app_dir_get_repo (priv->dir), remote, NULL, NULL);
+
+ return result;
+}
+
+/**
* xdg_app_installation_install:
* @self: a #XdgAppInstallation
* @remote_name: name of the remote to use
diff --git a/lib/xdg-app-installation.h b/lib/xdg-app-installation.h
index 0958974..343ecf7 100644
--- a/lib/xdg-app-installation.h
+++ b/lib/xdg-app-installation.h
@@ -142,6 +142,12 @@ XDG_APP_EXTERN XdgAppInstalledRef * xdg_app_installation_update
gpointer progress_data,
GCancellable *cancellable,
GError **error);
+XDG_APP_EXTERN XdgAppInstalledRef * xdg_app_installation_install_bundle (XdgAppInstallation *self,
+ GFile *file,
+ XdgAppProgressCallback progress,
+ gpointer progress_data,
+ GCancellable *cancellable,
+ GError **error);
XDG_APP_EXTERN gboolean xdg_app_installation_uninstall (XdgAppInstallation *self,
XdgAppRefKind kind,
const char *name,