mirror of
https://github.com/flatpak/flatpak.git
synced 2026-01-26 14:13:26 +00:00
install: Add --reinstall
If you're installing something and its already installed, we undeploy the old install first before deploying the new. This makes it very easy to switch an application from one remote to another, without having to uninstall first, which is both painful and could cause the download to be unnecessary large. Closes: #1241 Approved by: alexlarsson
This commit is contained in:
parent
97683cfbe1
commit
3ade86b292
@ -51,6 +51,7 @@ static gboolean opt_app;
|
||||
static gboolean opt_bundle;
|
||||
static gboolean opt_from;
|
||||
static gboolean opt_yes;
|
||||
static gboolean opt_reinstall;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "arch", 0, 0, G_OPTION_ARG_STRING, &opt_arch, N_("Arch to install for"), N_("ARCH") },
|
||||
@ -66,6 +67,7 @@ static GOptionEntry options[] = {
|
||||
{ "gpg-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_gpg_file, N_("Check bundle signatures with GPG key from FILE (- for stdin)"), N_("FILE") },
|
||||
{ "subpath", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_subpaths, N_("Only install this subpath"), N_("PATH") },
|
||||
{ "assumeyes", 'y', 0, G_OPTION_ARG_NONE, &opt_yes, N_("Automatically answer yes for all questions"), NULL },
|
||||
{ "reinstall", 0, 0, G_OPTION_ARG_NONE, &opt_reinstall, N_("Uninstall first if already installed"), NULL },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
@ -286,7 +288,7 @@ install_bundle (FlatpakDir *dir,
|
||||
return FALSE;
|
||||
|
||||
transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy,
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related, opt_reinstall);
|
||||
|
||||
if (!flatpak_transaction_add_install_bundle (transaction, file, gpg_data, error))
|
||||
return FALSE;
|
||||
@ -440,7 +442,7 @@ install_from (FlatpakDir *dir,
|
||||
g_print (_("Installing: %s\n"), slash + 1);
|
||||
|
||||
transaction = flatpak_transaction_new (clone, opt_yes, opt_no_pull, opt_no_deploy,
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related, opt_reinstall);
|
||||
|
||||
if (!flatpak_transaction_add_install (transaction, remote, ref, (const char **)opt_subpaths, error))
|
||||
return FALSE;
|
||||
@ -510,7 +512,7 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
|
||||
kinds = flatpak_kinds_from_bools (opt_app, opt_runtime);
|
||||
|
||||
transaction = flatpak_transaction_new (dir, opt_yes, opt_no_pull, opt_no_deploy,
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related, opt_reinstall);
|
||||
|
||||
for (i = 0; i < n_prefs; i++)
|
||||
{
|
||||
|
||||
@ -187,7 +187,7 @@ flatpak_builtin_update (int argc,
|
||||
{
|
||||
FlatpakTransaction *transaction = flatpak_transaction_new (g_ptr_array_index (dirs, k),
|
||||
opt_yes, opt_no_pull, opt_no_deploy,
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related);
|
||||
opt_no_static_deltas, !opt_no_deps, !opt_no_related, FALSE);
|
||||
g_ptr_array_add (transactions, transaction);
|
||||
}
|
||||
|
||||
|
||||
@ -60,6 +60,7 @@ struct FlatpakTransaction {
|
||||
gboolean no_static_deltas;
|
||||
gboolean add_deps;
|
||||
gboolean add_related;
|
||||
gboolean reinstall;
|
||||
};
|
||||
|
||||
|
||||
@ -170,7 +171,8 @@ flatpak_transaction_new (FlatpakDir *dir,
|
||||
gboolean no_deploy,
|
||||
gboolean no_static_deltas,
|
||||
gboolean add_deps,
|
||||
gboolean add_related)
|
||||
gboolean add_related,
|
||||
gboolean reinstall)
|
||||
{
|
||||
FlatpakTransaction *t = g_new0 (FlatpakTransaction, 1);
|
||||
|
||||
@ -183,6 +185,7 @@ flatpak_transaction_new (FlatpakDir *dir,
|
||||
t->no_static_deltas = no_static_deltas;
|
||||
t->add_deps = add_deps;
|
||||
t->add_related = add_related;
|
||||
t->reinstall = reinstall;
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -482,10 +485,20 @@ flatpak_transaction_add_ref (FlatpakTransaction *self,
|
||||
else if (kind == FLATPAK_TRANSACTION_OP_KIND_INSTALL)
|
||||
{
|
||||
g_assert (remote != NULL);
|
||||
if (dir_ref_is_installed (self->dir, ref, NULL, NULL))
|
||||
if (!self->reinstall &&
|
||||
dir_ref_is_installed (self->dir, ref, &origin, NULL))
|
||||
{
|
||||
g_printerr (_("%s already installed, skipping\n"), pref);
|
||||
return TRUE;
|
||||
if (strcmp (remote, origin) == 0)
|
||||
{
|
||||
g_printerr (_("%s already installed, skipping\n"), pref);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED,
|
||||
_("%s is already installed from other remote (%s)"), pref, origin);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -665,7 +678,7 @@ flatpak_transaction_run (FlatpakTransaction *self,
|
||||
{
|
||||
FlatpakTransactionOp *op = l->data;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
gboolean res;
|
||||
gboolean res = TRUE;
|
||||
const char *pref;
|
||||
const char *opname;
|
||||
FlatpakTransactionOpKind kind;
|
||||
@ -704,6 +717,7 @@ flatpak_transaction_run (FlatpakTransaction *self,
|
||||
self->no_pull,
|
||||
self->no_deploy,
|
||||
self->no_static_deltas,
|
||||
self->reinstall,
|
||||
op->ref, op->remote,
|
||||
(const char **)op->subpaths,
|
||||
progress,
|
||||
|
||||
@ -34,7 +34,8 @@ FlatpakTransaction *flatpak_transaction_new (FlatpakDir *dir,
|
||||
gboolean no_deploy,
|
||||
gboolean no_static_deltas,
|
||||
gboolean add_deps,
|
||||
gboolean add_related);
|
||||
gboolean add_related,
|
||||
gboolean reinstall);
|
||||
void flatpak_transaction_free (FlatpakTransaction *self);
|
||||
gboolean flatpak_transaction_update_metadata (FlatpakTransaction *self,
|
||||
gboolean all_remotes,
|
||||
|
||||
@ -5598,11 +5598,24 @@ flatpak_dir_deploy (FlatpakDir *self,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -origin remotes are deleted when the last ref refering to it is undeployed */
|
||||
static void
|
||||
maybe_prune_remote (FlatpakDir *self,
|
||||
const char *remote)
|
||||
{
|
||||
if (remote != NULL &&
|
||||
g_str_has_suffix (remote, "-origin") &&
|
||||
flatpak_dir_get_remote_noenumerate (self, remote) &&
|
||||
!flatpak_dir_remote_has_deploys (self, remote))
|
||||
ostree_repo_remote_delete (self->repo, remote, NULL, NULL);
|
||||
}
|
||||
|
||||
gboolean
|
||||
flatpak_dir_deploy_install (FlatpakDir *self,
|
||||
const char *ref,
|
||||
const char *origin,
|
||||
const char **subpaths,
|
||||
gboolean reinstall,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
@ -5613,6 +5626,7 @@ flatpak_dir_deploy_install (FlatpakDir *self,
|
||||
gboolean ret = FALSE;
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
g_auto(GStrv) ref_parts = g_strsplit (ref, "/", -1);
|
||||
g_autofree char *remove_ref_from_remote = NULL;
|
||||
|
||||
if (!flatpak_dir_lock (self, &lock,
|
||||
cancellable, error))
|
||||
@ -5621,9 +5635,33 @@ flatpak_dir_deploy_install (FlatpakDir *self,
|
||||
old_deploy_dir = flatpak_dir_get_if_deployed (self, ref, NULL, cancellable);
|
||||
if (old_deploy_dir != NULL)
|
||||
{
|
||||
g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED,
|
||||
_("%s branch %s already installed"), ref_parts[1], ref_parts[3]);
|
||||
goto out;
|
||||
if (reinstall)
|
||||
{
|
||||
g_autofree char *old_active = flatpak_dir_read_active (self, ref, cancellable);
|
||||
g_autoptr(GVariant) old_deploy = NULL;
|
||||
const char *old_origin;
|
||||
|
||||
old_deploy = flatpak_load_deploy_data (old_deploy_dir, cancellable, error);
|
||||
if (old_deploy == NULL)
|
||||
goto out;
|
||||
|
||||
/* If the old install was from a different remote, remove the ref */
|
||||
old_origin = flatpak_deploy_data_get_origin (old_deploy);
|
||||
if (strcmp (old_origin, origin) != 0)
|
||||
remove_ref_from_remote = g_strdup (old_origin);
|
||||
|
||||
g_debug ("Removing old deployment for reinstall");
|
||||
if (!flatpak_dir_undeploy (self, ref, old_active,
|
||||
TRUE, FALSE,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED,
|
||||
_("%s branch %s already installed"), ref_parts[1], ref_parts[3]);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
deploy_base = flatpak_dir_get_deploy_dir (self, ref);
|
||||
@ -5652,6 +5690,15 @@ flatpak_dir_deploy_install (FlatpakDir *self,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Remove old ref if the reinstalled was from a different remote */
|
||||
if (remove_ref_from_remote != NULL)
|
||||
{
|
||||
if (!flatpak_dir_remove_ref (self, remove_ref_from_remote, ref, cancellable, error))
|
||||
goto out;
|
||||
|
||||
maybe_prune_remote (self, remove_ref_from_remote);
|
||||
}
|
||||
|
||||
/* Release lock before doing possibly slow prune */
|
||||
glnx_release_lock_file (&lock);
|
||||
|
||||
@ -5898,6 +5945,7 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
gboolean no_pull,
|
||||
gboolean no_deploy,
|
||||
gboolean no_static_deltas,
|
||||
gboolean reinstall,
|
||||
const char *ref,
|
||||
const char *remote_name,
|
||||
const char **opt_subpaths,
|
||||
@ -6060,6 +6108,9 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
if (no_deploy)
|
||||
helper_flags |= FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY;
|
||||
|
||||
if (reinstall)
|
||||
helper_flags |= FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL;
|
||||
|
||||
g_debug ("Calling system helper: Deploy");
|
||||
if (!flatpak_system_helper_call_deploy_sync (system_helper,
|
||||
child_repo_path ? child_repo_path : "",
|
||||
@ -6089,7 +6140,7 @@ flatpak_dir_install (FlatpakDir *self,
|
||||
if (!no_deploy)
|
||||
{
|
||||
if (!flatpak_dir_deploy_install (self, ref, remote_name, opt_subpaths,
|
||||
cancellable, error))
|
||||
reinstall, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -6312,7 +6363,7 @@ flatpak_dir_install_bundle (FlatpakDir *self,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!flatpak_dir_deploy_install (self, ref, remote, NULL, cancellable, error))
|
||||
if (!flatpak_dir_deploy_install (self, ref, remote, NULL, FALSE, cancellable, error))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -6800,11 +6851,7 @@ flatpak_dir_uninstall (FlatpakDir *self,
|
||||
|
||||
glnx_release_lock_file (&lock);
|
||||
|
||||
if (repository != NULL &&
|
||||
g_str_has_suffix (repository, "-origin") &&
|
||||
flatpak_dir_get_remote_noenumerate (self, repository) &&
|
||||
!flatpak_dir_remote_has_deploys (self, repository))
|
||||
ostree_repo_remote_delete (self->repo, repository, NULL, NULL);
|
||||
maybe_prune_remote (self, repository);
|
||||
|
||||
if (!keep_ref)
|
||||
flatpak_dir_prune (self, cancellable, NULL);
|
||||
|
||||
@ -88,9 +88,10 @@ typedef enum {
|
||||
FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE = 1 << 0,
|
||||
FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY = 1 << 1,
|
||||
FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL = 1 << 2,
|
||||
FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL = 1 << 3,
|
||||
} FlatpakHelperDeployFlags;
|
||||
|
||||
#define FLATPAK_HELPER_DEPLOY_FLAGS_ALL (FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE|FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY|FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL)
|
||||
#define FLATPAK_HELPER_DEPLOY_FLAGS_ALL (FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE|FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY|FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL|FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL)
|
||||
|
||||
typedef enum {
|
||||
FLATPAK_HELPER_UNINSTALL_FLAGS_NONE = 0,
|
||||
@ -436,12 +437,14 @@ gboolean flatpak_dir_deploy_install (FlatpakDir *self,
|
||||
const char *ref,
|
||||
const char *origin,
|
||||
const char **subpaths,
|
||||
gboolean reinstall,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gboolean flatpak_dir_install (FlatpakDir *self,
|
||||
gboolean no_pull,
|
||||
gboolean no_deploy,
|
||||
gboolean no_static_deltas,
|
||||
gboolean reinstall,
|
||||
const char *ref,
|
||||
const char *remote_name,
|
||||
const char **subpaths,
|
||||
|
||||
@ -1434,6 +1434,7 @@ flatpak_installation_install_full (FlatpakInstallation *self,
|
||||
(flags & FLATPAK_INSTALL_FLAGS_NO_PULL) != 0,
|
||||
(flags & FLATPAK_INSTALL_FLAGS_NO_DEPLOY) != 0,
|
||||
(flags & FLATPAK_INSTALL_FLAGS_NO_STATIC_DELTAS) != 0,
|
||||
FALSE,
|
||||
ref, remote_name, (const char **)subpaths,
|
||||
ostree_progress, cancellable, error))
|
||||
goto out;
|
||||
|
||||
@ -159,6 +159,7 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
gboolean is_oci;
|
||||
gboolean no_deploy;
|
||||
gboolean local_pull;
|
||||
gboolean reinstall;
|
||||
g_autoptr(GMainContext) main_context = NULL;
|
||||
g_autofree char *url = NULL;
|
||||
|
||||
@ -187,6 +188,7 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
is_update = (arg_flags & FLATPAK_HELPER_DEPLOY_FLAGS_UPDATE) != 0;
|
||||
no_deploy = (arg_flags & FLATPAK_HELPER_DEPLOY_FLAGS_NO_DEPLOY) != 0;
|
||||
local_pull = (arg_flags & FLATPAK_HELPER_DEPLOY_FLAGS_LOCAL_PULL) != 0;
|
||||
reinstall = (arg_flags & FLATPAK_HELPER_DEPLOY_FLAGS_REINSTALL) != 0;
|
||||
|
||||
deploy_dir = flatpak_dir_get_if_deployed (system, arg_ref, NULL, NULL);
|
||||
|
||||
@ -195,18 +197,23 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
g_autofree char *real_origin = NULL;
|
||||
if (!is_update)
|
||||
{
|
||||
/* Can't install already installed app */
|
||||
g_dbus_method_invocation_return_error (invocation, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED,
|
||||
"%s is already installed", arg_ref);
|
||||
return TRUE;
|
||||
if (!reinstall)
|
||||
{
|
||||
/* Can't install already installed app */
|
||||
g_dbus_method_invocation_return_error (invocation, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED,
|
||||
"%s is already installed", arg_ref);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
real_origin = flatpak_dir_get_origin (system, arg_ref, NULL, NULL);
|
||||
if (g_strcmp0 (real_origin, arg_origin) != 0)
|
||||
else
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Wrong origin %s for update", arg_origin);
|
||||
return TRUE;
|
||||
real_origin = flatpak_dir_get_origin (system, arg_ref, NULL, NULL);
|
||||
if (g_strcmp0 (real_origin, arg_origin) != 0)
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
||||
"Wrong origin %s for update", arg_origin);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!deploy_dir && is_update)
|
||||
@ -389,6 +396,7 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
{
|
||||
if (!flatpak_dir_deploy_install (system, arg_ref, arg_origin,
|
||||
(const char **) arg_subpaths,
|
||||
reinstall,
|
||||
NULL, &error))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
|
||||
|
||||
@ -28,7 +28,7 @@ if [ x${USE_COLLECTIONS_IN_CLIENT-} == xyes ] || [ x${USE_COLLECTIONS_IN_SERVER-
|
||||
skip_without_p2p
|
||||
fi
|
||||
|
||||
echo "1..10"
|
||||
echo "1..12"
|
||||
|
||||
#Regular repo
|
||||
setup_repo
|
||||
@ -76,6 +76,14 @@ fi
|
||||
install_repo test-gpg2
|
||||
echo "ok with alternative gpg key"
|
||||
|
||||
if ${FLATPAK} ${U} install test-repo org.test.Platform 2> install-error-log; then
|
||||
assert_not_reached "Should not be able to install again from different remote without reinstall"
|
||||
fi
|
||||
echo "ok failed to install again from different remote"
|
||||
|
||||
${FLATPAK} ${U} install --reinstall test-repo org.test.Platform
|
||||
echo "ok re-install"
|
||||
|
||||
${FLATPAK} ${U} uninstall org.test.Platform org.test.Hello
|
||||
|
||||
if ${FLATPAK} ${U} install test-missing-gpg-repo org.test.Platform 2> install-error-log; then
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user