From 451acac02822a6190992a8faeaf5af1dabd42675 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 6 Jun 2018 00:18:25 +0100 Subject: [PATCH] lib/repo-pull: Retry pulls without static deltas if they fail If pulling a static delta fails (due to one part of it missing from a mirror, for example), retry the entire pull operation with disable-static-deltas=true. This is a functional, but ugly approach to fixing the problem, and a neater solution may be adopted upstream in future. If so, this commit should be dropped and replaced with the upstream solution: https://github.com/ostreedev/ostree/pull/1612 Signed-off-by: Philip Withnall https://phabricator.endlessm.com/T22873 Rebase 2018.6 (T23138): Fix a minor merge conflict due to "#ifdef OSTREE_ENABLE_EXPERIMENTAL_API" being gone now. --- src/libostree/ostree-repo-pull.c | 58 ++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/src/libostree/ostree-repo-pull.c b/src/libostree/ostree-repo-pull.c index ba6e72891..45c9eb645 100644 --- a/src/libostree/ostree-repo-pull.c +++ b/src/libostree/ostree-repo-pull.c @@ -3547,13 +3547,13 @@ initiate_request (OtPullData *pull_data, * will be verified with the keyring of the remote being pulled from. * Since: 2019.2 */ -gboolean -ostree_repo_pull_with_options (OstreeRepo *self, - const char *remote_name_or_baseurl, - GVariant *options, - OstreeAsyncProgress *progress, - GCancellable *cancellable, - GError **error) +static gboolean +ostree_repo_pull_with_options_internal (OstreeRepo *self, + const char *remote_name_or_baseurl, + GVariant *options, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error) { gboolean ret = FALSE; g_autoptr(GBytes) bytes_summary = NULL; @@ -4774,6 +4774,50 @@ ostree_repo_pull_with_options (OstreeRepo *self, return ret; } +gboolean +ostree_repo_pull_with_options (OstreeRepo *self, + const char *remote_name_or_baseurl, + GVariant *options, + OstreeAsyncProgress *progress, + GCancellable *cancellable, + GError **error) +{ + g_autoptr(GError) local_error = NULL; + + if (!ostree_repo_pull_with_options_internal (self, remote_name_or_baseurl, + options, progress, cancellable, + &local_error)) + { + gboolean disable_static_deltas = FALSE, require_static_deltas = FALSE; + + if (options != NULL) + { + g_variant_lookup (options, "disable-static-deltas", "b", &disable_static_deltas); + g_variant_lookup (options, "require-static-deltas", "b", &require_static_deltas); + } + + if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && + !disable_static_deltas && !require_static_deltas) + { + g_autoptr(GVariant) modified_options = NULL; + g_auto(GVariantDict) modified_options_dict; + g_variant_dict_init (&modified_options_dict, options); + g_variant_dict_insert (&modified_options_dict, "disable-static-deltas", + "b", TRUE); + modified_options = g_variant_dict_end (&modified_options_dict); + + return ostree_repo_pull_with_options_internal (self, remote_name_or_baseurl, + modified_options, progress, + cancellable, error); + } + + g_propagate_error (error, g_steal_pointer (&local_error)); + return FALSE; + } + + return TRUE; +} + /* Structure used in ostree_repo_find_remotes_async() which stores metadata * about a given OSTree commit. This includes the metadata from the commit * #GVariant, plus some working state which is used to work out which remotes