forked from Mirrors/flatpak-builder
lib: Add xdg_app_installation_install_bundle
parent
cd13e9e21d
commit
382ae396b3
|
@ -122,7 +122,6 @@ install_bundle (XdgAppDir *dir,
|
|||
OstreeRepo *repo;
|
||||
g_auto(GLnxLockFile) lock = GLNX_LOCK_FILE_INIT;
|
||||
g_autoptr(GVariant) metadata = NULL;
|
||||
g_autoptr(GVariant) gpg_value = NULL;
|
||||
g_autofree char *basename = NULL;
|
||||
|
||||
if (argc < 2)
|
||||
|
@ -132,30 +131,16 @@ install_bundle (XdgAppDir *dir,
|
|||
|
||||
repo = xdg_app_dir_get_repo (dir);
|
||||
|
||||
if (!xdg_app_supports_bundles (repo))
|
||||
return xdg_app_fail (error, "Your version of ostree is too old to support single-file bundles");
|
||||
|
||||
file = g_file_new_for_commandline_arg (filename);
|
||||
|
||||
metadata = xdg_app_bundle_load (file, &to_checksum, error);
|
||||
metadata = xdg_app_bundle_load (file, &to_checksum,
|
||||
&ref,
|
||||
&origin,
|
||||
&gpg_data,
|
||||
error);
|
||||
if (metadata == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!g_variant_lookup (metadata, "ref", "s", &ref))
|
||||
return xdg_app_fail (error, "Invalid bundle, no ref in metadata");
|
||||
|
||||
if (!g_variant_lookup (metadata, "origin", "s", &origin))
|
||||
origin = NULL;
|
||||
|
||||
gpg_value = g_variant_lookup_value (metadata, "gpg-keys", G_VARIANT_TYPE("ay"));
|
||||
if (gpg_value)
|
||||
{
|
||||
gsize n_elements;
|
||||
const char *data = g_variant_get_fixed_array (gpg_value, &n_elements, 1);
|
||||
|
||||
gpg_data = g_bytes_new (data, n_elements);
|
||||
}
|
||||
|
||||
if (opt_gpg_file != NULL)
|
||||
{
|
||||
/* Override gpg_data from file */
|
||||
|
|
|
@ -875,7 +875,7 @@ xdg_app_dir_pull_from_bundle (XdgAppDir *self,
|
|||
if (!xdg_app_supports_bundles (self->repo))
|
||||
return xdg_app_fail (error, "Your version of ostree is too old to support single-file bundles");
|
||||
|
||||
metadata = xdg_app_bundle_load (file, &to_checksum, error);
|
||||
metadata = xdg_app_bundle_load (file, &to_checksum, NULL, NULL, NULL, error);
|
||||
if (metadata == NULL)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
@ -2335,6 +2335,9 @@ xdg_app_xml_parse (GInputStream *in,
|
|||
GVariant *
|
||||
xdg_app_bundle_load (GFile *file,
|
||||
char **commit,
|
||||
char **ref,
|
||||
char **origin,
|
||||
GBytes **gpg_keys,
|
||||
GError **error)
|
||||
{
|
||||
g_autoptr(GVariant) delta = NULL;
|
||||
|
@ -2362,6 +2365,35 @@ xdg_app_bundle_load (GFile *file,
|
|||
|
||||
metadata = g_variant_get_child_value (delta, 0);
|
||||
|
||||
if (ref != NULL)
|
||||
{
|
||||
if (!g_variant_lookup (metadata, "ref", "s", ref))
|
||||
{
|
||||
xdg_app_fail (error, "Invalid bundle, no ref in metadata");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (origin != NULL)
|
||||
{
|
||||
if (!g_variant_lookup (metadata, "origin", "s", origin))
|
||||
*origin = NULL;
|
||||
}
|
||||
|
||||
if (gpg_keys != NULL)
|
||||
{
|
||||
g_autoptr(GVariant) gpg_value = g_variant_lookup_value (metadata, "gpg-keys",
|
||||
G_VARIANT_TYPE("ay"));
|
||||
if (gpg_value)
|
||||
{
|
||||
gsize n_elements;
|
||||
const char *data = g_variant_get_fixed_array (gpg_value, &n_elements, 1);
|
||||
*gpg_keys = g_bytes_new (data, n_elements);
|
||||
}
|
||||
else
|
||||
*gpg_keys = NULL;
|
||||
}
|
||||
|
||||
/* Make a copy of the data so we can return it after freeing the file */
|
||||
return g_variant_new_from_bytes (g_variant_get_type (metadata),
|
||||
g_bytes_new (g_variant_get_data (metadata),
|
||||
|
|
|
@ -186,6 +186,9 @@ gboolean xdg_app_repo_generate_appstream (OstreeRepo *repo,
|
|||
|
||||
GVariant * xdg_app_bundle_load (GFile *file,
|
||||
char **commit,
|
||||
char **ref,
|
||||
char **origin,
|
||||
GBytes **gpg_keys,
|
||||
GError **error);
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -715,6 +715,144 @@ progress_cb (OstreeAsyncProgress *progress, gpointer user_data)
|
|||
g_string_free (buf, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue