common: Support collections in check_for_updates() and forward the results

Search for updates on peer to peer sources as well as the internet in
check_for_updates(), and pass the resulting OstreeRepoFinderResult array
to the pull() calls, so a consistent set of checksums are pulled.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
tingping/wmclass
Philip Withnall 2017-06-30 11:07:45 +01:00 committed by Alexander Larsson
parent 0d6455aa5f
commit 30a5cf8136
6 changed files with 209 additions and 32 deletions

View File

@ -715,10 +715,13 @@ flatpak_transaction_run (FlatpakTransaction *self,
}
else if (kind == FLATPAK_TRANSACTION_OP_KIND_UPDATE)
{
g_auto(OstreeRepoFinderResultv) check_results = NULL;
opname = _("update");
g_autofree char *target_commit = flatpak_dir_check_for_update (self->dir, op->ref, op->remote, op->commit,
(const char **)op->subpaths,
self->no_pull,
&check_results,
cancellable, &local_error);
if (target_commit != NULL)
{
@ -730,6 +733,7 @@ flatpak_transaction_run (FlatpakTransaction *self,
self->no_static_deltas,
op->commit != NULL, /* Allow downgrade if we specify commit */
op->ref, op->remote, target_commit,
(const OstreeRepoFinderResult * const *) check_results,
(const char **)op->subpaths,
progress,
cancellable, &local_error);

View File

@ -1758,7 +1758,9 @@ flatpak_dir_update_appstream (FlatpakDir *self,
cancellable, error))
return FALSE;
if (!flatpak_dir_pull (self, remote, branch, NULL, NULL,
/* No need to use an existing OstreeRepoFinderResult array, since
* appstream updates do not need to be atomic wrt other updates. */
if (!flatpak_dir_pull (self, remote, branch, NULL, NULL, NULL,
child_repo, FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_MIRROR,
progress, cancellable, error))
return FALSE;
@ -1802,7 +1804,9 @@ flatpak_dir_update_appstream (FlatpakDir *self,
return TRUE;
}
if (!flatpak_dir_pull (self, remote, branch, NULL, NULL, NULL, FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_NONE, progress,
/* No need to use an existing OstreeRepoFinderResult array, since
* appstream updates do not need to be atomic wrt other updates. */
if (!flatpak_dir_pull (self, remote, branch, NULL, NULL, NULL, NULL, FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_NONE, progress,
cancellable, error))
return FALSE;
@ -1861,6 +1865,7 @@ repo_pull_one_dir (OstreeRepo *self,
const char **dirs_to_pull,
const char *ref_to_fetch,
const char *rev_to_fetch,
const OstreeRepoFinderResult * const *results_to_fetch,
FlatpakPullFlags flatpak_flags,
OstreeRepoPullFlags flags,
OstreeAsyncProgress *progress,
@ -1879,6 +1884,9 @@ repo_pull_one_dir (OstreeRepo *self,
g_autofree gchar *collection_id = NULL;
#endif /* FLATPAK_ENABLE_P2P */
/* If @results_to_fetch is set, @rev_to_fetch must be. */
g_assert (results_to_fetch == NULL || rev_to_fetch != NULL);
/* We always want this on for every type of pull */
flags |= OSTREE_REPO_PULL_FLAGS_BAREUSERONLY_FILES;
@ -1927,11 +1935,6 @@ repo_pull_one_dir (OstreeRepo *self,
collection_refs_to_fetch[0] = &collection_ref;
collection_refs_to_fetch[1] = NULL;
revs_to_fetch[0] = rev_to_fetch;
revs_to_fetch[1] = NULL;
g_variant_builder_add (&find_builder, "{s@v}", "override-commit-ids",
g_variant_new_variant (g_variant_new_strv ((const char * const *) revs_to_fetch, -1)));
if (progress != NULL)
update_freq = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (progress), "update-frequency"));
if (update_freq == 0)
@ -1948,19 +1951,23 @@ repo_pull_one_dir (OstreeRepo *self,
context = g_main_context_new ();
g_main_context_push_thread_default (context);
ostree_repo_find_remotes_async (self, (const OstreeCollectionRef * const *) collection_refs_to_fetch,
find_options,
NULL /* default finders */, progress, cancellable,
async_result_cb, &find_result);
while (find_result == NULL)
g_main_context_iteration (context, TRUE);
results = ostree_repo_find_remotes_finish (self, find_result, error);
if (results != NULL)
if (results_to_fetch == NULL)
{
ostree_repo_pull_from_remotes_async (self, (const OstreeRepoFinderResult * const *) results,
ostree_repo_find_remotes_async (self, (const OstreeCollectionRef * const *) collection_refs_to_fetch,
find_options,
NULL /* default finders */, progress, cancellable,
async_result_cb, &find_result);
while (find_result == NULL)
g_main_context_iteration (context, TRUE);
results = ostree_repo_find_remotes_finish (self, find_result, error);
results_to_fetch = (const OstreeRepoFinderResult * const *) results;
}
if (results_to_fetch != NULL)
{
ostree_repo_pull_from_remotes_async (self, results_to_fetch,
pull_options, progress,
cancellable, async_result_cb,
&pull_result);
@ -2101,6 +2108,7 @@ flatpak_dir_setup_extra_data (FlatpakDir *self,
const char *repository,
const char *ref,
const char *rev,
const OstreeRepoFinderResult * const *results,
FlatpakPullFlags flatpak_flags,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
@ -2111,6 +2119,9 @@ flatpak_dir_setup_extra_data (FlatpakDir *self,
gsize n_extra_data;
guint64 total_download_size;
/* If @results is set, @rev must be. */
g_assert (results == NULL || rev != NULL);
extra_data_sources = flatpak_repo_get_extra_data_sources (repo, rev, cancellable, NULL);
if (extra_data_sources == NULL)
{
@ -2121,6 +2132,7 @@ flatpak_dir_setup_extra_data (FlatpakDir *self,
NULL,
ref,
rev,
results,
flatpak_flags,
OSTREE_REPO_PULL_FLAGS_COMMIT_ONLY,
NULL,
@ -2641,6 +2653,7 @@ flatpak_dir_pull (FlatpakDir *self,
const char *repository,
const char *ref,
const char *opt_rev,
const OstreeRepoFinderResult * const *opt_results,
const char **subpaths,
OstreeRepo *repo,
FlatpakPullFlags flatpak_flags,
@ -2655,6 +2668,11 @@ flatpak_dir_pull (FlatpakDir *self,
g_auto(GLnxConsoleRef) console = { 0, };
g_autoptr(OstreeAsyncProgress) console_progress = NULL;
g_autoptr(GPtrArray) subdirs_arg = NULL;
g_auto(OstreeRepoFinderResultv) allocated_results = NULL;
const OstreeRepoFinderResult * const *results;
/* If @opt_results is set, @opt_rev must be. */
g_return_val_if_fail (opt_results == NULL || opt_rev != NULL, FALSE);
if (!flatpak_dir_ensure_repo (self, cancellable, error))
return FALSE;
@ -2687,12 +2705,91 @@ flatpak_dir_pull (FlatpakDir *self,
and to make sure we're atomically using a single rev if we happen to do multiple
pulls (e.g. with subpaths) */
if (opt_rev != NULL)
rev = opt_rev;
{
rev = opt_rev;
results = opt_results;
}
else
{
rev = flatpak_dir_lookup_ref_from_summary (self, repository, ref, NULL, cancellable, error);
g_autofree char *collection_id = NULL;
#ifdef FLATPAK_ENABLE_P2P
if (!repo_get_remote_collection_id (self->repo, repository, &collection_id, NULL))
collection_id = NULL;
if (collection_id != NULL && *collection_id != '\0')
{
GVariantBuilder find_builder;
g_autoptr(GVariant) find_options = NULL;
g_autoptr(GMainContext) context = NULL;
g_autoptr(GAsyncResult) find_result = NULL;
OstreeCollectionRef collection_ref;
OstreeCollectionRef *collection_refs_to_fetch[2];
gboolean force_disable_deltas = (flatpak_flags & FLATPAK_PULL_FLAGS_NO_STATIC_DELTAS) != 0;
guint update_freq = 0;
gsize i;
g_variant_builder_init (&find_builder, G_VARIANT_TYPE ("a{sv}"));
if (force_disable_deltas)
{
g_variant_builder_add (&find_builder, "{s@v}", "disable-static-deltas",
g_variant_new_variant (g_variant_new_boolean (TRUE)));
}
collection_ref.collection_id = collection_id;
collection_ref.ref_name = (char *) ref;
collection_refs_to_fetch[0] = &collection_ref;
collection_refs_to_fetch[1] = NULL;
if (progress != NULL)
update_freq = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (progress), "update-frequency"));
if (update_freq == 0)
update_freq = FLATPAK_DEFAULT_UPDATE_FREQUENCY;
g_variant_builder_add (&find_builder, "{s@v}", "update-frequency",
g_variant_new_variant (g_variant_new_uint32 (update_freq)));
find_options = g_variant_ref_sink (g_variant_builder_end (&find_builder));
context = g_main_context_new ();
g_main_context_push_thread_default (context);
ostree_repo_find_remotes_async (self->repo, (const OstreeCollectionRef * const *) collection_refs_to_fetch,
find_options,
NULL /* default finders */, progress, cancellable,
async_result_cb, &find_result);
while (find_result == NULL)
g_main_context_iteration (context, TRUE);
allocated_results = ostree_repo_find_remotes_finish (self->repo, find_result, error);
g_main_context_pop_thread_default (context);
results = (const OstreeRepoFinderResult * const *) allocated_results;
if (results == NULL)
return FALSE;
for (i = 0, rev = NULL; results[i] != NULL && rev == NULL; i++)
rev = g_hash_table_lookup (results[i]->ref_to_checksum, &collection_ref);
if (rev == NULL)
return flatpak_fail (error, "No such ref '%s' in remote %s", ref, repository);
}
else
#endif /* FLATPAK_ENABLE_P2P */
{
rev = flatpak_dir_lookup_ref_from_summary (self, repository, ref, NULL, cancellable, error);
results = NULL;
}
if (rev == NULL)
return FALSE;
{
g_assert (error == NULL || *error != NULL);
return FALSE;
}
}
if (repo == NULL)
@ -2718,7 +2815,7 @@ flatpak_dir_pull (FlatpakDir *self,
/* Setup extra data information before starting to pull, so we can have precise
* progress reports */
if (!flatpak_dir_setup_extra_data (self, repo, repository,
ref, rev,
ref, rev, results,
flatpak_flags,
progress,
cancellable,
@ -2727,7 +2824,7 @@ flatpak_dir_pull (FlatpakDir *self,
if (!repo_pull_one_dir (repo, repository,
subdirs_arg ? (const char **)subdirs_arg->pdata : NULL,
ref, rev, flatpak_flags, flags,
ref, rev, results, flatpak_flags, flags,
progress,
cancellable, error))
{
@ -5314,7 +5411,9 @@ flatpak_dir_install (FlatpakDir *self,
cancellable, error))
return FALSE;
if (!flatpak_dir_pull (self, remote_name, ref, NULL, subpaths,
/* Dont resolve a rev or OstreeRepoFinderResult set early; the pull
* code will do this. */
if (!flatpak_dir_pull (self, remote_name, ref, NULL, NULL, subpaths,
child_repo,
flatpak_flags,
OSTREE_REPO_PULL_FLAGS_MIRROR,
@ -5359,7 +5458,9 @@ flatpak_dir_install (FlatpakDir *self,
if (!no_pull)
{
if (!flatpak_dir_pull (self, remote_name, ref, NULL, opt_subpaths, NULL,
/* Dont resolve a rev or OstreeRepoFinderResult set early; the pull
* code will do this. */
if (!flatpak_dir_pull (self, remote_name, ref, NULL, NULL, opt_subpaths, NULL,
flatpak_flags, OSTREE_REPO_PULL_FLAGS_NONE,
progress, cancellable, error))
return FALSE;
@ -5627,6 +5728,7 @@ flatpak_dir_check_for_update (FlatpakDir *self,
const char *checksum_or_latest,
const char **opt_subpaths,
gboolean no_pull,
OstreeRepoFinderResult ***out_results,
GCancellable *cancellable,
GError **error)
{
@ -5639,6 +5741,7 @@ flatpak_dir_check_for_update (FlatpakDir *self,
const char *target_rev = NULL;
const char *installed_commit;
const char *installed_alt_id;
g_autofree char *collection_id = NULL;
deploy_data = flatpak_dir_get_deploy_data (self, ref,
cancellable, NULL);
@ -5668,6 +5771,12 @@ flatpak_dir_check_for_update (FlatpakDir *self,
return NULL;
}
#ifdef FLATPAK_ENABLE_P2P
if (!ostree_repo_get_remote_option (self->repo, remote_name, "collection-id", NULL,
&collection_id, NULL))
g_clear_pointer (&collection_id, g_free);
#endif /* FLATPAK_ENABLE_P2P */
if (no_pull)
{
remote_and_branch = g_strdup_printf ("%s:%s", remote_name, ref);
@ -5678,6 +5787,49 @@ flatpak_dir_check_for_update (FlatpakDir *self,
return NULL; /* No update, because nothing to update to */
}
}
else if (collection_id != NULL)
{
#ifdef FLATPAK_ENABLE_P2P
/* Find the latest rev from the remote and its available mirrors, including
* LAN and USB sources. */
g_autoptr(GMainContext) context = NULL;
g_autoptr(GAsyncResult) find_result = NULL;
g_auto(OstreeRepoFinderResultv) results = NULL;
OstreeCollectionRef collection_ref = { collection_id, (char *) ref };
OstreeCollectionRef *collection_refs_to_fetch[2] = { &collection_ref, NULL };
gsize i;
context = g_main_context_new ();
g_main_context_push_thread_default (context);
ostree_repo_find_remotes_async (self->repo, (const OstreeCollectionRef * const *) collection_refs_to_fetch,
NULL /* no options */,
NULL /* default finders */,
NULL /* no progress reporting */,
cancellable, async_result_cb, &find_result);
while (find_result == NULL)
g_main_context_iteration (context, TRUE);
results = ostree_repo_find_remotes_finish (self->repo, find_result, error);
if (results == NULL)
return NULL;
for (i = 0; results[i] != NULL && latest_rev == NULL; i++)
latest_rev = g_strdup (g_hash_table_lookup (results[i]->ref_to_checksum, &collection_ref));
if (latest_rev == NULL)
{
flatpak_fail (error, "No such ref '%s' in remote %s", ref, remote_name);
return NULL;
}
if (out_results != NULL)
*out_results = g_steal_pointer (&results);
#else /* if !FLATPAK_ENABLE_P2P */
g_assert_not_reached ();
#endif /* !FLATPAK_ENABLE_P2P */
}
else
{
latest_rev = flatpak_dir_lookup_ref_from_summary (self, remote_name, ref, NULL, NULL, error);
@ -5719,6 +5871,7 @@ flatpak_dir_update (FlatpakDir *self,
const char *ref,
const char *remote_name,
const char *commit,
const OstreeRepoFinderResult * const *results,
const char **opt_subpaths,
OstreeAsyncProgress *progress,
GCancellable *cancellable,
@ -5730,7 +5883,8 @@ flatpak_dir_update (FlatpakDir *self,
FlatpakPullFlags flatpak_flags;
gboolean is_oci;
/* This is calculated in check_for_update */
/* This and @results are calculated in check_for_update. @results will be
* %NULL if we dont support collections. */
g_assert (commit != NULL);
flatpak_flags = FLATPAK_PULL_FLAGS_DOWNLOAD_EXTRA_DATA;
@ -5840,7 +5994,7 @@ flatpak_dir_update (FlatpakDir *self,
return FALSE;
flatpak_flags |= FLATPAK_PULL_FLAGS_SIDELOAD_EXTRA_DATA;
if (!flatpak_dir_pull (self, remote_name, ref, commit, subpaths,
if (!flatpak_dir_pull (self, remote_name, ref, commit, results, subpaths,
child_repo,
flatpak_flags, OSTREE_REPO_PULL_FLAGS_MIRROR,
progress, cancellable, error))
@ -5884,8 +6038,7 @@ flatpak_dir_update (FlatpakDir *self,
if (!no_pull)
{
if (!flatpak_dir_pull (self, remote_name, ref, commit, subpaths,
if (!flatpak_dir_pull (self, remote_name, ref, commit, results, subpaths,
NULL, flatpak_flags, OSTREE_REPO_PULL_FLAGS_NONE,
progress, cancellable, error))
return FALSE;

View File

@ -120,6 +120,17 @@ typedef enum {
GQuark flatpak_dir_error_quark (void);
#ifndef FLATPAK_ENABLE_P2P
/* Rather than putting #ifdefs around all the function arguments for result sets,
* define away OstreeRepoFinderResult if were compiling without P2P support.
* The surrounding code should always pass in NULL if P2P support is disabled. */
typedef void OstreeRepoFinderResult;
typedef void** OstreeRepoFinderResultv;
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, void)
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, void, NULL)
#endif /* !FLATPAK_ENABLE_P2P */
/**
* FLATPAK_DEPLOY_DATA_GVARIANT_FORMAT:
*
@ -292,6 +303,7 @@ gboolean flatpak_dir_pull (FlatpakDir *self,
const char *repository,
const char *ref,
const char *opt_rev,
const OstreeRepoFinderResult * const *results,
const char **subpaths,
OstreeRepo *repo,
FlatpakPullFlags flatpak_flags,
@ -402,6 +414,7 @@ char * flatpak_dir_check_for_update (FlatpakDir *self,
const char *checksum_or_latest,
const char **opt_subpaths,
gboolean no_pull,
OstreeRepoFinderResult ***out_results,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update (FlatpakDir *self,
@ -412,6 +425,7 @@ gboolean flatpak_dir_update (FlatpakDir *self,
const char *ref,
const char *remote_name,
const char *checksum_or_latest,
const OstreeRepoFinderResult * const *results,
const char **opt_subpaths,
OstreeAsyncProgress *progress,
GCancellable *cancellable,

View File

@ -4863,6 +4863,8 @@ flatpak_pull_from_oci (OstreeRepo *repo,
else
full_ref = g_strdup (ref);
/* Dont need to set the collection ID here, since the ref is bound to a
* collection via its remote. */
ostree_repo_transaction_set_ref (repo, NULL, full_ref, commit_checksum);
if (!ostree_repo_commit_transaction (repo, NULL, cancellable, error))

View File

@ -1355,6 +1355,7 @@ flatpak_installation_update_full (FlatpakInstallation *self,
g_autofree char *remote_name = NULL;
FlatpakInstalledRef *result = NULL;
g_autofree char *target_commit = NULL;
g_auto(OstreeRepoFinderResultv) check_results = NULL;
ref = flatpak_compose_ref (kind == FLATPAK_REF_KIND_APP, name, branch, arch, error);
if (ref == NULL)
@ -1376,6 +1377,7 @@ flatpak_installation_update_full (FlatpakInstallation *self,
target_commit = flatpak_dir_check_for_update (dir, ref, remote_name, NULL,
(const char **)subpaths,
(flags & FLATPAK_UPDATE_FLAGS_NO_PULL) != 0,
&check_results,
cancellable, error);
if (target_commit == NULL)
return NULL;
@ -1399,7 +1401,9 @@ flatpak_installation_update_full (FlatpakInstallation *self,
(flags & FLATPAK_UPDATE_FLAGS_NO_DEPLOY) != 0,
(flags & FLATPAK_UPDATE_FLAGS_NO_STATIC_DELTAS) != 0,
FALSE,
ref, remote_name, target_commit, (const char **)subpaths,
ref, remote_name, target_commit,
(const OstreeRepoFinderResult * const *) check_results,
(const char **)subpaths,
ostree_progress, cancellable, error))
goto out;

View File

@ -319,7 +319,7 @@ handle_deploy (FlatpakSystemHelper *object,
main_context = g_main_context_new ();
g_main_context_push_thread_default (main_context);
if (!flatpak_dir_pull (system, arg_origin, arg_ref, NULL, (const char **)arg_subpaths, NULL,
if (!flatpak_dir_pull (system, arg_origin, arg_ref, NULL, NULL, (const char **)arg_subpaths, NULL,
FLATPAK_PULL_FLAGS_NONE, OSTREE_REPO_PULL_FLAGS_UNTRUSTED, NULL,
NULL, &error))
{