mirror of
https://github.com/flatpak/flatpak.git
synced 2026-10-22 23:55:34 -04:00
lib: Add xdg_app_installation_install
This commit is contained in:
1 parent
1a2b5adffe
commit
9285d055ab
7 files changed
+285
-10
No files matched your search
@@ -144,7 +144,7 @@ xdg_app_builtin_install_runtime (int argc, char **argv, GCancellable *cancellabl
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!xdg_app_dir_pull (dir, repository, ref,
|
||||
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
@@ -219,7 +219,7 @@ xdg_app_builtin_install_app (int argc, char **argv, GCancellable *cancellable, G
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!xdg_app_dir_pull (dir, repository, ref,
|
||||
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ xdg_app_builtin_update_runtime (int argc, char **argv, GCancellable *cancellable
|
||||
if (repository == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!xdg_app_dir_pull (dir, repository, ref,
|
||||
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
@@ -148,7 +148,7 @@ xdg_app_builtin_update_app (int argc, char **argv, GCancellable *cancellable, GE
|
||||
if (repository == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!xdg_app_dir_pull (dir, repository, ref,
|
||||
if (!xdg_app_dir_pull (dir, repository, ref, NULL,
|
||||
cancellable, error))
|
||||
return FALSE;
|
||||
|
||||
|
||||
+16
-5
@@ -556,22 +556,27 @@ gboolean
|
||||
xdg_app_dir_pull (XdgAppDir *self,
|
||||
const char *repository,
|
||||
const char *ref,
|
||||
OstreeAsyncProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GSConsole *console = NULL;
|
||||
g_autoptr(OstreeAsyncProgress) progress = NULL;
|
||||
g_autoptr(OstreeAsyncProgress) console_progress = NULL;
|
||||
const char *refs[2];
|
||||
|
||||
if (!xdg_app_dir_ensure_repo (self, cancellable, error))
|
||||
goto out;
|
||||
|
||||
console = gs_console_get ();
|
||||
if (console)
|
||||
if (progress == NULL)
|
||||
{
|
||||
gs_console_begin_status_line (console, "", NULL, NULL);
|
||||
progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
|
||||
console = gs_console_get ();
|
||||
if (console)
|
||||
{
|
||||
gs_console_begin_status_line (console, "", NULL, NULL);
|
||||
console_progress = ostree_async_progress_new_and_connect (ostree_repo_pull_default_console_progress_changed, console);
|
||||
progress = console_progress;
|
||||
}
|
||||
}
|
||||
|
||||
refs[0] = ref;
|
||||
@@ -1986,6 +1991,12 @@ xdg_app_dir_new (GFile *path, gboolean user)
|
||||
return g_object_new (XDG_APP_TYPE_DIR, "path", path, "user", user, NULL);
|
||||
}
|
||||
|
||||
XdgAppDir*
|
||||
xdg_app_dir_clone (XdgAppDir *self)
|
||||
{
|
||||
return xdg_app_dir_new (self->basedir, self->user);
|
||||
}
|
||||
|
||||
XdgAppDir *
|
||||
xdg_app_dir_get_system (void)
|
||||
{
|
||||
|
||||
@@ -70,6 +70,7 @@ GKeyFile * xdg_app_deploy_get_metadata (XdgAppDeploy *deploy);
|
||||
|
||||
XdgAppDir* xdg_app_dir_new (GFile *basedir,
|
||||
gboolean user);
|
||||
XdgAppDir* xdg_app_dir_clone (XdgAppDir *self);
|
||||
XdgAppDir *xdg_app_dir_get (gboolean user);
|
||||
XdgAppDir *xdg_app_dir_get_system (void);
|
||||
XdgAppDir *xdg_app_dir_get_user (void);
|
||||
@@ -111,6 +112,7 @@ gboolean xdg_app_dir_ensure_repo (XdgAppDir *self,
|
||||
gboolean xdg_app_dir_pull (XdgAppDir *self,
|
||||
const char *repository,
|
||||
const char *ref,
|
||||
OstreeAsyncProgress *progress,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean xdg_app_dir_list_refs_for_name (XdgAppDir *self,
|
||||
|
||||
+29
-1
@@ -4,6 +4,16 @@
|
||||
|
||||
#include <xdg-app.h>
|
||||
|
||||
|
||||
static void
|
||||
progress_cb (const char *status,
|
||||
guint progress,
|
||||
gboolean estimating,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_print ("status: %s, progress: %d estimating: %d, user_data: %p\n", status, progress, estimating, user_data);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
@@ -15,10 +25,29 @@ main (int argc, char *argv[])
|
||||
XdgAppInstalledRef **runtimes;
|
||||
XdgAppRemoteRef *remote_ref;
|
||||
XdgAppRemote **remotes;
|
||||
GError *error = NULL;
|
||||
int i, j;
|
||||
|
||||
installation = xdg_app_installation_new_user ();
|
||||
|
||||
if (argc == 3)
|
||||
{
|
||||
app1 = xdg_app_installation_install (installation,
|
||||
argv[1],
|
||||
XDG_APP_REF_KIND_APP,
|
||||
argv[2],
|
||||
NULL, NULL,
|
||||
progress_cb, (gpointer)0xdeadbeef,
|
||||
NULL, &error);
|
||||
if (app1 == NULL)
|
||||
g_print ("Error: %s\n", error->message);
|
||||
else
|
||||
g_print ("Installed %s: %s\n", argv[2],
|
||||
xdg_app_ref_get_commit (XDG_APP_REF (app1)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_print ("**** Listing all installed apps\n");
|
||||
apps = xdg_app_installation_list_installed_refs (installation,
|
||||
XDG_APP_REF_KIND_APP,
|
||||
@@ -97,7 +126,6 @@ main (int argc, char *argv[])
|
||||
|
||||
for (i = 0; remotes[i] != NULL; i++)
|
||||
{
|
||||
GError *error = NULL;
|
||||
g_print ("\nRemote: %s %s %s %d %d\n",
|
||||
xdg_app_remote_get_name (remotes[i]),
|
||||
xdg_app_remote_get_url (remotes[i]),
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libgsystem.h"
|
||||
#include "xdg-app-utils.h"
|
||||
#include "xdg-app-installation.h"
|
||||
#include "xdg-app-installed-ref-private.h"
|
||||
@@ -345,3 +346,221 @@ xdg_app_installation_load_app_overrides (XdgAppInstallation *self,
|
||||
|
||||
return metadata_contents;
|
||||
}
|
||||
|
||||
static void
|
||||
progress_cb (OstreeAsyncProgress *progress, gpointer user_data)
|
||||
{
|
||||
XdgAppProgressCallback progress_cb = g_object_get_data (G_OBJECT (progress), "callback");
|
||||
guint last_progress = GPOINTER_TO_UINT(g_object_get_data (G_OBJECT (progress), "last_progress"));
|
||||
GString *buf;
|
||||
g_autofree char *status = NULL;
|
||||
guint outstanding_fetches;
|
||||
guint outstanding_metadata_fetches;
|
||||
guint outstanding_writes;
|
||||
guint n_scanned_metadata;
|
||||
guint fetched_delta_parts;
|
||||
guint total_delta_parts;
|
||||
guint64 bytes_transferred;
|
||||
guint64 total_delta_part_size;
|
||||
guint fetched;
|
||||
guint metadata_fetched;
|
||||
guint requested;
|
||||
guint64 ellapsed_time;
|
||||
guint new_progress = 0;
|
||||
gboolean estimating = FALSE;
|
||||
|
||||
buf = g_string_new ("");
|
||||
|
||||
status = ostree_async_progress_get_status (progress);
|
||||
outstanding_fetches = ostree_async_progress_get_uint (progress, "outstanding-fetches");
|
||||
outstanding_metadata_fetches = ostree_async_progress_get_uint (progress, "outstanding-metadata-fetches");
|
||||
outstanding_writes = ostree_async_progress_get_uint (progress, "outstanding-writes");
|
||||
n_scanned_metadata = ostree_async_progress_get_uint (progress, "scanned-metadata");
|
||||
fetched_delta_parts = ostree_async_progress_get_uint (progress, "fetched-delta-parts");
|
||||
total_delta_parts = ostree_async_progress_get_uint (progress, "total-delta-parts");
|
||||
total_delta_part_size = ostree_async_progress_get_uint64 (progress, "total-delta-part-size");
|
||||
bytes_transferred = ostree_async_progress_get_uint64 (progress, "bytes-transferred");
|
||||
fetched = ostree_async_progress_get_uint (progress, "fetched");
|
||||
metadata_fetched = ostree_async_progress_get_uint (progress, "metadata-fetched");
|
||||
requested = ostree_async_progress_get_uint (progress, "requested");
|
||||
ellapsed_time = (g_get_monotonic_time () - ostree_async_progress_get_uint64 (progress, "start-time")) / G_USEC_PER_SEC;
|
||||
|
||||
if (status)
|
||||
{
|
||||
g_string_append (buf, status);
|
||||
}
|
||||
else if (outstanding_fetches)
|
||||
{
|
||||
guint64 bytes_sec = bytes_transferred / ellapsed_time;
|
||||
g_autofree char *formatted_bytes_transferred =
|
||||
g_format_size_full (bytes_transferred, 0);
|
||||
g_autofree char *formatted_bytes_sec = NULL;
|
||||
|
||||
if (!bytes_sec) // Ignore first second
|
||||
formatted_bytes_sec = g_strdup ("-");
|
||||
else
|
||||
{
|
||||
formatted_bytes_sec = g_format_size (bytes_sec);
|
||||
}
|
||||
|
||||
if (total_delta_parts > 0)
|
||||
{
|
||||
g_autofree char *formatted_total =
|
||||
g_format_size (total_delta_part_size);
|
||||
g_string_append_printf (buf, "Receiving delta parts: %u/%u %s/s %s/%s",
|
||||
fetched_delta_parts, total_delta_parts,
|
||||
formatted_bytes_sec, formatted_bytes_transferred,
|
||||
formatted_total);
|
||||
|
||||
new_progress = (100 * bytes_transferred) / total_delta_part_size;
|
||||
}
|
||||
else if (outstanding_metadata_fetches)
|
||||
{
|
||||
/* At this point we don't really know how much data there is, so we have to make a guess.
|
||||
* Since its really hard to figure out early how much data there is we report 1% until
|
||||
* all objects are scanned. */
|
||||
|
||||
new_progress = 1;
|
||||
estimating = TRUE;
|
||||
|
||||
g_string_append_printf (buf, "Receiving metadata objects: %u/(estimating) %s/s %s",
|
||||
metadata_fetched, formatted_bytes_sec, formatted_bytes_transferred);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_progress = (100 * fetched) / requested;
|
||||
g_string_append_printf (buf, "Receiving objects: %u%% (%u/%u) %s/s %s",
|
||||
(guint)((((double)fetched) / requested) * 100),
|
||||
fetched, requested, formatted_bytes_sec, formatted_bytes_transferred);
|
||||
}
|
||||
}
|
||||
else if (outstanding_writes)
|
||||
{
|
||||
g_string_append_printf (buf, "Writing objects: %u", outstanding_writes);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_printf (buf, "Scanning metadata: %u", n_scanned_metadata);
|
||||
}
|
||||
|
||||
if (new_progress < last_progress)
|
||||
new_progress = last_progress;
|
||||
g_object_set_data (G_OBJECT (progress), "last_progress", GUINT_TO_POINTER(new_progress));
|
||||
|
||||
progress_cb (buf->str, new_progress, estimating, user_data);
|
||||
|
||||
g_string_free (buf, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* xdg_app_installation_install:
|
||||
* @self: a #XdgAppInstallation
|
||||
* @progress: (scope call): the callback
|
||||
* @cancellable: (nullable): a #GCancellable
|
||||
* @error: return location for a #GError
|
||||
*
|
||||
* Lists the remotes.
|
||||
*
|
||||
* Returns: (transfer full): The ref for the newly installed app or %null on failure
|
||||
*/
|
||||
XdgAppInstalledRef *
|
||||
xdg_app_installation_install (XdgAppInstallation *self,
|
||||
const char *remote_name,
|
||||
XdgAppRefKind kind,
|
||||
const char *name,
|
||||
const char *arch,
|
||||
const char *version,
|
||||
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;
|
||||
g_autoptr(GFile) deploy_base = NULL;
|
||||
g_autoptr(XdgAppDir) dir_clone = NULL;
|
||||
g_autoptr(GMainContext) main_context = NULL;
|
||||
g_autoptr(OstreeAsyncProgress) ostree_progress = NULL;
|
||||
XdgAppInstalledRef *result = NULL;
|
||||
|
||||
if (version == NULL)
|
||||
version = "master";
|
||||
|
||||
if (arch == NULL)
|
||||
arch = xdg_app_get_arch ();
|
||||
|
||||
if (!xdg_app_is_valid_name (name))
|
||||
{
|
||||
xdg_app_fail (error, "'%s' is not a valid name", name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!xdg_app_is_valid_branch (version))
|
||||
{
|
||||
xdg_app_fail (error, "'%s' is not a valid branch name", version);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (kind == XDG_APP_REF_KIND_APP)
|
||||
ref = xdg_app_build_app_ref (name, version, arch);
|
||||
else
|
||||
ref = xdg_app_build_runtime_ref (name, version, arch);
|
||||
|
||||
deploy_base = xdg_app_dir_get_deploy_dir (priv->dir, ref);
|
||||
if (g_file_query_exists (deploy_base, cancellable))
|
||||
{
|
||||
xdg_app_fail (error, "%s branch %s already installed", name, version);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Pull, etc are not threadsafe, so we work on a copy */
|
||||
dir_clone = xdg_app_dir_clone (priv->dir);
|
||||
|
||||
/* Work around ostree-pull spinning the default main context for the sync calls */
|
||||
main_context = g_main_context_new ();
|
||||
g_main_context_push_thread_default (main_context);
|
||||
|
||||
if (progress)
|
||||
{
|
||||
ostree_progress = ostree_async_progress_new_and_connect (progress_cb, progress_data);
|
||||
g_object_set_data (G_OBJECT (ostree_progress), "callback", progress);
|
||||
g_object_set_data (G_OBJECT (ostree_progress), "last_progress", GUINT_TO_POINTER(0));
|
||||
}
|
||||
|
||||
if (!xdg_app_dir_pull (dir_clone, remote_name, ref,
|
||||
ostree_progress, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!g_file_make_directory_with_parents (deploy_base, cancellable, error))
|
||||
goto out;
|
||||
created_deploy_base = TRUE;
|
||||
|
||||
if (!xdg_app_dir_set_origin (priv->dir, ref, remote_name, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!xdg_app_dir_deploy (priv->dir, ref, NULL, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (kind == XDG_APP_REF_KIND_APP)
|
||||
{
|
||||
if (!xdg_app_dir_make_current_ref (priv->dir, ref, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!xdg_app_dir_update_exports (priv->dir, name, cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
xdg_app_dir_cleanup_removed (priv->dir, cancellable, NULL);
|
||||
|
||||
result = get_ref (self, ref, cancellable);
|
||||
|
||||
out:
|
||||
if (main_context)
|
||||
g_main_context_pop_thread_default (main_context);
|
||||
|
||||
if (created_deploy_base && result == NULL)
|
||||
gs_shutil_rm_rf (deploy_base, cancellable, NULL);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -55,6 +55,11 @@ XDG_APP_EXTERN XdgAppInstallation *xdg_app_installation_new_user (void);
|
||||
XDG_APP_EXTERN XdgAppInstallation *xdg_app_installation_new_for_path (GFile *path,
|
||||
gboolean user);
|
||||
|
||||
typedef void (*XdgAppProgressCallback)(const char *status,
|
||||
guint progress,
|
||||
gboolean estimating,
|
||||
gpointer user_data);
|
||||
|
||||
XDG_APP_EXTERN gboolean xdg_app_installation_get_is_user (XdgAppInstallation *self);
|
||||
XDG_APP_EXTERN XdgAppInstalledRef **xdg_app_installation_list_installed_refs (XdgAppInstallation *self,
|
||||
XdgAppRefKind kind,
|
||||
@@ -78,5 +83,15 @@ XDG_APP_EXTERN char * xdg_app_installation_load_app_overrides
|
||||
const char *app_id,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
XDG_APP_EXTERN XdgAppInstalledRef * xdg_app_installation_install (XdgAppInstallation *self,
|
||||
const char *remote_name,
|
||||
XdgAppRefKind kind,
|
||||
const char *name,
|
||||
const char *arch,
|
||||
const char *version,
|
||||
XdgAppProgressCallback progress,
|
||||
gpointer progress_data,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
#endif /* __XDG_APP_INSTALLATION_H__ */
|
||||
Reference in new issue
Block a user