mirror of
https://github.com/flatpak/flatpak.git
synced 2026-04-15 12:29:40 -04:00
installation: Make fetching remote refs work offline
Currently flatpak_installation_fetch_remote_ref_sync() does not work offline. It returns an error when it fails to fetch the remote's summary in flatpak_dir_get_remote_state(). This is a problem since GNOME Software (or at least the Endless fork) uses this library function to display apps it finds on a USB drive (see gs_plugin_refine_item_origin() in gs-flatpak.c) and that's something that should work even offline. So this commit changes flatpak_dir_get_remote_state_optional() so that it accepts the only_cached option, and updates the call sites. Also have fetch_remote_ref_sync() use flatpak_dir_get_remote_state_optional(), which means that when we're offline we will use the xa.cache data in the ostree-metadata ref as a list of refs list instead of using a summary. However since the commit checksums are not in xa.cache, we don't have enough information to form a FlatpakRemoteRef. So also call ostree_repo_find_remotes_async() to get the commit from any LAN or USB sources that may be available. This may not be very performant but at least it only happens if the ref wasn't found in a remote summary; see https://github.com/flatpak/flatpak/issues/1862 It's sad this code is so long-winded but it's difficult to break out a helper function that could be shared with list_remotes_for_configured_remote() above. Longer term we could improve the ostree_repo_find_remotes_async() API and add options to remove the need to manually handle OstreeRepoFinder objects. Closes: #3114 Approved by: alexlarsson
This commit is contained in:
committed by
Atomic Bot
parent
ed766dc6db
commit
d647bc105e
@@ -664,7 +664,7 @@ flatpak_builtin_create_usb (int argc, char **argv, GCancellable *cancellable, GE
|
||||
|
||||
/* Try to update the repo metadata by creating a FlatpakRemoteState object,
|
||||
* but don't fail on error because we want this to work offline. */
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, &local_error);
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, FALSE, cancellable, &local_error);
|
||||
if (state == NULL)
|
||||
{
|
||||
g_printerr (_("Warning: Couldn't update repo metadata for remote ‘%s’: %s\n"),
|
||||
|
||||
@@ -882,6 +882,7 @@ gboolean flatpak_dir_remote_make_oci_summary (FlatpakDir *self,
|
||||
GError **error);
|
||||
FlatpakRemoteState * flatpak_dir_get_remote_state_optional (FlatpakDir *self,
|
||||
const char *remote,
|
||||
gboolean only_cached,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
FlatpakRemoteState * flatpak_dir_get_remote_state_local_only (FlatpakDir *self,
|
||||
|
||||
@@ -4153,7 +4153,7 @@ flatpak_dir_update_appstream (FlatpakDir *self,
|
||||
|
||||
is_oci = flatpak_dir_get_remote_oci (self, remote);
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -10876,10 +10876,11 @@ flatpak_dir_get_remote_state_for_summary (FlatpakDir *self,
|
||||
FlatpakRemoteState *
|
||||
flatpak_dir_get_remote_state_optional (FlatpakDir *self,
|
||||
const char *remote,
|
||||
gboolean only_cached,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return _flatpak_dir_get_remote_state (self, remote, TRUE, FALSE, FALSE, NULL, NULL, cancellable, error);
|
||||
return _flatpak_dir_get_remote_state (self, remote, TRUE, FALSE, only_cached, NULL, NULL, cancellable, error);
|
||||
}
|
||||
|
||||
|
||||
@@ -10902,7 +10903,7 @@ flatpak_dir_remote_has_ref (FlatpakDir *self,
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
g_autoptr(FlatpakRemoteState) state = NULL;
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, NULL, &local_error);
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, FALSE, NULL, &local_error);
|
||||
if (state == NULL)
|
||||
{
|
||||
g_debug ("Can't get state for remote %s: %s", remote, local_error->message);
|
||||
@@ -11275,7 +11276,7 @@ flatpak_dir_find_remote_refs (FlatpakDir *self,
|
||||
g_autoptr(FlatpakRemoteState) state = NULL;
|
||||
GPtrArray *matched_refs;
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -11372,7 +11373,7 @@ flatpak_dir_find_remote_ref (FlatpakDir *self,
|
||||
g_autoptr(FlatpakRemoteState) state = NULL;
|
||||
g_autoptr(GError) my_error = NULL;
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (self, remote, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -1995,7 +1995,7 @@ flatpak_installation_install_full (FlatpakInstallation *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -2158,7 +2158,7 @@ flatpak_installation_update_full (FlatpakInstallation *self,
|
||||
if (remote_name == NULL)
|
||||
return NULL;
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -2392,7 +2392,7 @@ flatpak_installation_fetch_remote_size_sync (FlatpakInstallation *self,
|
||||
if (dir == NULL)
|
||||
return FALSE;
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -2433,7 +2433,7 @@ flatpak_installation_fetch_remote_metadata_sync (FlatpakInstallation *self,
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return FALSE;
|
||||
|
||||
@@ -2598,7 +2598,7 @@ flatpak_installation_fetch_remote_ref_sync_full (FlatpakInstallation *self,
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
|
||||
state = flatpak_dir_get_remote_state (dir, remote_name, (flags & FLATPAK_QUERY_FLAGS_ONLY_CACHED) != 0, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, (flags & FLATPAK_QUERY_FLAGS_ONLY_CACHED) != 0, cancellable, error);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
@@ -2624,6 +2624,77 @@ flatpak_installation_fetch_remote_ref_sync_full (FlatpakInstallation *self,
|
||||
coll_ref = flatpak_collection_ref_new (collection_id, ref);
|
||||
checksum = g_hash_table_lookup (ht, coll_ref);
|
||||
|
||||
/* Check LAN/USB sources too in case we're offline */
|
||||
if (checksum == NULL && collection_id != NULL && *collection_id != '\0')
|
||||
{
|
||||
OstreeRepo *repo;
|
||||
const char * const *default_repo_finders;
|
||||
g_autoptr(GAsyncResult) result = NULL;
|
||||
OstreeCollectionRef ostree_coll_ref;
|
||||
const OstreeCollectionRef *refs[2] = { NULL, };
|
||||
OstreeRepoFinder *finders[3] = { NULL, };
|
||||
guint finder_index = 0;
|
||||
gsize i;
|
||||
g_autoptr(GMainContextPopDefault) context = NULL;
|
||||
g_autoptr(OstreeRepoFinder) finder_mount = NULL, finder_avahi = NULL;
|
||||
|
||||
context = flatpak_main_context_new_default ();
|
||||
|
||||
ostree_coll_ref.collection_id = collection_id;
|
||||
ostree_coll_ref.ref_name = ref;
|
||||
refs[0] = &ostree_coll_ref;
|
||||
|
||||
if (!flatpak_dir_ensure_repo (dir, cancellable, error))
|
||||
return NULL;
|
||||
repo = flatpak_dir_get_repo (dir);
|
||||
default_repo_finders = ostree_repo_get_default_repo_finders (repo);
|
||||
if (default_repo_finders == NULL || g_strv_contains (default_repo_finders, "mount"))
|
||||
{
|
||||
finder_mount = OSTREE_REPO_FINDER (ostree_repo_finder_mount_new (NULL));
|
||||
finders[finder_index++] = finder_mount;
|
||||
}
|
||||
|
||||
if (default_repo_finders == NULL || g_strv_contains (default_repo_finders, "lan"))
|
||||
{
|
||||
g_autoptr(GError) local_error = NULL;
|
||||
finder_avahi = OSTREE_REPO_FINDER (ostree_repo_finder_avahi_new (context));
|
||||
finders[finder_index++] = finder_avahi;
|
||||
|
||||
/* The Avahi finder may fail to start on, for example, a CI server. */
|
||||
ostree_repo_finder_avahi_start (OSTREE_REPO_FINDER_AVAHI (finder_avahi), &local_error);
|
||||
if (local_error != NULL)
|
||||
{
|
||||
finders[--finder_index] = NULL;
|
||||
g_clear_object (&finder_avahi);
|
||||
}
|
||||
}
|
||||
|
||||
if (finders[0] != NULL)
|
||||
{
|
||||
g_auto(OstreeRepoFinderResultv) results = NULL;
|
||||
|
||||
ostree_repo_find_remotes_async (repo, (const OstreeCollectionRef * const *)refs,
|
||||
NULL, finders, NULL, cancellable, async_result_cb, &result);
|
||||
while (result == NULL)
|
||||
g_main_context_iteration (context, TRUE);
|
||||
|
||||
results = ostree_repo_find_remotes_finish (repo, result, error);
|
||||
|
||||
if (finder_avahi != NULL)
|
||||
ostree_repo_finder_avahi_stop (OSTREE_REPO_FINDER_AVAHI (finder_avahi));
|
||||
|
||||
if (results == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; results[i] != NULL; i++)
|
||||
{
|
||||
checksum = g_hash_table_lookup (results[i]->ref_to_checksum, &ostree_coll_ref);
|
||||
if (checksum != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If there was not a match, it may be because the collection ID is
|
||||
* not set in the local configuration, or it is wrong, so we resort to
|
||||
* trying to match just the ref name */
|
||||
@@ -2814,7 +2885,7 @@ flatpak_installation_list_remote_related_refs_sync (FlatpakInstallation *self,
|
||||
if (dir == NULL)
|
||||
return NULL;
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, cancellable, error);
|
||||
state = flatpak_dir_get_remote_state_optional (dir, remote_name, FALSE, cancellable, error);
|
||||
if (state == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
@@ -1412,7 +1412,7 @@ flatpak_transaction_ensure_remote_state (FlatpakTransaction *self,
|
||||
if (state)
|
||||
return flatpak_remote_state_ref (state);
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (priv->dir, remote, NULL, error);
|
||||
state = flatpak_dir_get_remote_state_optional (priv->dir, remote, FALSE, NULL, error);
|
||||
|
||||
if (state)
|
||||
g_hash_table_insert (priv->remote_states, state->remote_name, flatpak_remote_state_ref (state));
|
||||
|
||||
@@ -645,7 +645,7 @@ handle_deploy (FlatpakSystemHelper *object,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (system, arg_origin, NULL, &error);
|
||||
state = flatpak_dir_get_remote_state_optional (system, arg_origin, FALSE, NULL, &error);
|
||||
if (state == NULL)
|
||||
{
|
||||
flatpak_invocation_return_error (invocation, error, "Error getting remote state");
|
||||
@@ -885,7 +885,7 @@ handle_deploy_appstream (FlatpakSystemHelper *object,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
state = flatpak_dir_get_remote_state_optional (system, arg_origin, NULL, &error);
|
||||
state = flatpak_dir_get_remote_state_optional (system, arg_origin, FALSE, NULL, &error);
|
||||
if (state == NULL)
|
||||
{
|
||||
flatpak_invocation_return_error (invocation, error, "Error getting remote state");
|
||||
|
||||
Reference in New Issue
Block a user