summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2017-12-11 16:49:40 +0100
committerAtomic Bot <atomic-devel@projectatomic.io>2017-12-14 09:04:38 +0000
commit3ade86b29268945da2610f42e9907ba74a24ada8 (patch)
tree8e16a6cd0802c9fd44ff3e021edfa91fd2958014
parent97683cfbe14c47a82aaac06e547d96c6d52bdc12 (diff)
downloadflatpak-3ade86b29268945da2610f42e9907ba74a24ada8.tar.gz
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
-rw-r--r--app/flatpak-builtins-install.c8
-rw-r--r--app/flatpak-builtins-update.c2
-rw-r--r--app/flatpak-transaction.c24
-rw-r--r--app/flatpak-transaction.h3
-rw-r--r--common/flatpak-dir.c67
-rw-r--r--common/flatpak-dir.h5
-rw-r--r--lib/flatpak-installation.c1
-rw-r--r--system-helper/flatpak-system-helper.c28
-rwxr-xr-xtests/test-repo.sh10
9 files changed, 116 insertions, 32 deletions
diff --git a/app/flatpak-builtins-install.c b/app/flatpak-builtins-install.c
index 95d98606..505ec5e0 100644
--- a/app/flatpak-builtins-install.c
+++ b/app/flatpak-builtins-install.c
@@ -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++)
{
diff --git a/app/flatpak-builtins-update.c b/app/flatpak-builtins-update.c
index fe73d955..68f0e7f7 100644
--- a/app/flatpak-builtins-update.c
+++ b/app/flatpak-builtins-update.c
@@ -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);
}
diff --git a/app/flatpak-transaction.c b/app/flatpak-transaction.c
index 080fc792..dc722d3d 100644
--- a/app/flatpak-transaction.c
+++ b/app/flatpak-transaction.c
@@ -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,
diff --git a/app/flatpak-transaction.h b/app/flatpak-transaction.h
index 5eaf7d13..4e51572f 100644
--- a/app/flatpak-transaction.h
+++ b/app/flatpak-transaction.h
@@ -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,
diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c
index 2ac25e6a..ee2315e4 100644
--- a/common/flatpak-dir.c
+++ b/common/flatpak-dir.c
@@ -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);
diff --git a/common/flatpak-dir.h b/common/flatpak-dir.h
index 8e3f3244..19dc0ad8 100644
--- a/common/flatpak-dir.h
+++ b/common/flatpak-dir.h
@@ -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,
diff --git a/lib/flatpak-installation.c b/lib/flatpak-installation.c
index f7de69ee..d12f116f 100644
--- a/lib/flatpak-installation.c
+++ b/lib/flatpak-installation.c
@@ -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;
diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c
index 6c26fd1e..dc069b91 100644
--- a/system-helper/flatpak-system-helper.c
+++ b/system-helper/flatpak-system-helper.c
@@ -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,
diff --git a/tests/test-repo.sh b/tests/test-repo.sh
index f588ce5b..2628c87b 100755
--- a/tests/test-repo.sh
+++ b/tests/test-repo.sh
@@ -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