* Pass the results to ostree_repo_pull_from_remotes_async() to pull the given @refs
* from those remotes.
*
- * No @options are currently supported.
+ * The following @options are currently defined:
+ *
+ * * `override-commit-ids` (`as`): Array of specific commit IDs to fetch. The nth
+ * commit ID applies to the nth ref, so this must be the same length as @refs, if
+ * provided.
*
* @finders must be a non-empty %NULL-terminated array of the #OstreeRepoFinder
* instances to use, or %NULL to use the system default set of finders, which
g_autoptr(OstreeRepoFinder) finder_config = NULL;
g_autoptr(OstreeRepoFinder) finder_mount = NULL;
g_autoptr(OstreeRepoFinder) finder_avahi = NULL;
+ g_autofree char **override_commit_ids = NULL;
g_return_if_fail (OSTREE_IS_REPO (self));
g_return_if_fail (is_valid_collection_ref_array (refs));
g_return_if_fail (progress == NULL || OSTREE_IS_ASYNC_PROGRESS (progress));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+ if (options)
+ {
+ (void) g_variant_lookup (options, "override-commit-ids", "^a&s", &override_commit_ids);
+ g_return_if_fail (override_commit_ids == NULL || g_strv_length ((gchar **) refs) == g_strv_length (override_commit_ids));
+ }
+
/* Set up a task for the whole operation. */
task = g_task_new (self, cancellable, callback, user_data);
g_task_set_source_tag (task, ostree_repo_find_remotes_async);
g_autoptr(OstreeFetcher) fetcher = NULL;
g_autofree const gchar **ref_to_latest_commit = NULL; /* indexed as @refs; (element-type commit-checksum) */
gsize n_refs;
+ g_autofree char **override_commit_ids = NULL;
g_autoptr(GPtrArray) remotes_to_remove = NULL; /* (element-type OstreeRemote) */
g_autoptr(GPtrArray) final_results = NULL; /* (element-type OstreeRepoFinderResult) */
* to be %NULL-safe. */
g_ptr_array_set_free_func (results, (GDestroyNotify) repo_finder_result_free0);
- /* FIXME: Add support for options:
- * - override-commit-ids (allow downgrades)
- *
- * Use case: multiple pulls of separate subdirs; want them to use the same
- * configuration.
- * Use case: downgrading a flatpak app.
- */
+ if (data->options)
+ {
+ (void) g_variant_lookup (data->options, "override-commit-ids", "^a&s", &override_commit_ids);
+ }
/* FIXME: In future, we also want to pull static delta superblocks in this
* phase, so that we have all the metadata we need for accurate size
* differences between remotes: two remotes could both contain ref R, but one
* remote could be outdated compared to the other, and point to an older
* commit. For each ref, we want to find the most recent commit any remote
- * points to for it.
+ * points to for it (unless override-commit-ids was used).
*
* @ref_to_latest_commit is indexed by @ref_index, and its values are the
- * latest checksum for each ref. */
+ * latest checksum for each ref. If override-commit-ids was used,
+ * @ref_to_latest_commit won't be initialized or used.*/
ref_to_latest_commit = g_new0 (const gchar *, n_refs);
for (i = 0; i < n_refs; i++)
const CommitMetadata *latest_commit_metadata = NULL;
g_autofree gchar *latest_commit_timestamp_str = NULL;
+ if (override_commit_ids)
+ {
+ g_debug ("%s: Using specified commit ‘%s’ for ref (%s, %s).",
+ G_STRFUNC, override_commit_ids[i], refs[i]->collection_id, refs[i]->ref_name);
+ continue;
+ }
+
for (j = 0; j < results->len; j++)
{
const CommitMetadata *candidate_commit_metadata;
ostree_collection_ref_equal,
(GDestroyNotify) ostree_collection_ref_free,
g_free);
- n_latest_refs = 0;
- for (j = 0; refs[j] != NULL; j++)
+ if (override_commit_ids)
{
- const gchar *latest_commit_for_ref = ref_to_latest_commit[j];
+ for (j = 0; refs[j] != NULL; j++)
+ g_hash_table_insert (validated_ref_to_checksum, ostree_collection_ref_dup (refs[j]),
+ g_strdup (override_commit_ids[j]));
+ }
+ else
+ {
+ n_latest_refs = 0;
- if (pointer_table_get (refs_and_remotes_table, j, i) != latest_commit_for_ref)
- latest_commit_for_ref = NULL;
- if (latest_commit_for_ref != NULL)
- n_latest_refs++;
+ for (j = 0; refs[j] != NULL; j++)
+ {
+ const gchar *latest_commit_for_ref = ref_to_latest_commit[j];
- g_hash_table_insert (validated_ref_to_checksum, ostree_collection_ref_dup (refs[j]), g_strdup (latest_commit_for_ref));
- }
+ if (pointer_table_get (refs_and_remotes_table, j, i) != latest_commit_for_ref)
+ latest_commit_for_ref = NULL;
+ if (latest_commit_for_ref != NULL)
+ n_latest_refs++;
- if (n_latest_refs == 0)
- {
- g_debug ("%s: Omitting remote ‘%s’ from results as none of its refs are new enough.",
- G_STRFUNC, result->remote->name);
- ostree_repo_finder_result_free (g_steal_pointer (&g_ptr_array_index (results, i)));
- continue;
+ g_hash_table_insert (validated_ref_to_checksum, ostree_collection_ref_dup (refs[j]),
+ g_strdup (latest_commit_for_ref));
+ }
+
+ if (n_latest_refs == 0)
+ {
+ g_debug ("%s: Omitting remote ‘%s’ from results as none of its refs are new enough.",
+ G_STRFUNC, result->remote->name);
+ ostree_repo_finder_result_free (g_steal_pointer (&g_ptr_array_index (results, i)));
+ continue;
+ }
}
result->ref_to_checksum = g_steal_pointer (&validated_ref_to_checksum);