Merge pull request #345 from mariospr/issue221

Add server-side support for default-branch for remote repositories
tingping/wmclass
Alexander Larsson 2016-10-17 12:31:07 +02:00 committed by GitHub
commit 0abdcd3f03
12 changed files with 335 additions and 47 deletions

View File

@ -47,6 +47,7 @@ static gboolean opt_do_enumerate;
static gboolean opt_no_enumerate;
static gboolean opt_if_not_exists;
static gboolean opt_enable;
static gboolean opt_update_metadata;
static gboolean opt_disable;
static int opt_prio = -1;
static char *opt_title;
@ -67,6 +68,7 @@ static GOptionEntry modify_options[] = {
{ "enumerate", 0, 0, G_OPTION_ARG_NONE, &opt_do_enumerate, N_("Mark the remote as enumerate"), NULL },
{ "url", 0, 0, G_OPTION_ARG_STRING, &opt_url, N_("Set a new url"), N_("URL") },
{ "enable", 0, 0, G_OPTION_ARG_NONE, &opt_enable, N_("Enable the remote"), NULL },
{ "update-metadata", 0, 0, G_OPTION_ARG_NONE, &opt_update_metadata, N_("Update extra metadata from the summary file"), NULL },
{ NULL }
};
@ -259,6 +261,46 @@ load_options (char *filename,
}
}
static gboolean
update_remote_with_extra_metadata (FlatpakDir* dir,
const char *remote,
GBytes *gpg_data,
GCancellable *cancellable,
GError **error)
{
g_autofree char *title = NULL;
g_autofree char *default_branch = NULL;
g_autoptr(GKeyFile) config = NULL;
if (opt_title == NULL)
{
title = flatpak_dir_fetch_remote_title (dir,
remote,
NULL,
NULL);
if (title)
opt_title = title;
}
if (opt_default_branch == NULL)
{
default_branch = flatpak_dir_fetch_remote_default_branch (dir,
remote,
NULL,
NULL);
if (default_branch)
opt_default_branch = default_branch;
}
if (title != NULL || default_branch != NULL)
{
config = get_config_from_opts (dir, remote);
return flatpak_dir_modify_remote (dir, remote, config, gpg_data, cancellable, error);
}
return TRUE;
}
gboolean
flatpak_builtin_add_remote (int argc, char **argv,
GCancellable *cancellable, GError **error)
@ -267,7 +309,6 @@ flatpak_builtin_add_remote (int argc, char **argv,
g_autoptr(FlatpakDir) dir = NULL;
g_autoptr(GFile) file = NULL;
g_auto(GStrv) remotes = NULL;
g_autofree char *title = NULL;
g_autofree char *remote_url = NULL;
const char *remote_name;
const char *url_or_path = NULL;
@ -323,17 +364,6 @@ flatpak_builtin_add_remote (int argc, char **argv,
if (!opt_no_gpg_verify)
opt_do_gpg_verify = TRUE;
if (opt_title == NULL)
{
title = flatpak_dir_fetch_remote_title (dir,
remote_name,
NULL,
NULL);
if (title)
opt_title = title;
}
config = get_config_from_opts (dir, remote_name);
if (opt_gpg_import != NULL)
@ -343,7 +373,12 @@ flatpak_builtin_add_remote (int argc, char **argv,
return FALSE;
}
return flatpak_dir_modify_remote (dir, remote_name, config, gpg_data, cancellable, error);
if (!flatpak_dir_modify_remote (dir, remote_name, config, gpg_data, cancellable, error))
return FALSE;
/* We can't retrieve the extra metadata until the remote has been added locally, since
ostree_repo_remote_fetch_summary() works with the repository's name, not its URL. */
return update_remote_with_extra_metadata (dir, remote_name, gpg_data, cancellable, error);
}
gboolean
@ -397,6 +432,18 @@ flatpak_builtin_modify_remote (int argc, char **argv, GCancellable *cancellable,
if (!ostree_repo_remote_get_url (flatpak_dir_get_repo (dir), remote_name, NULL, NULL))
return flatpak_fail (error, _("No remote %s"), remote_name);
if (opt_update_metadata)
{
g_autoptr(GError) local_error = NULL;
g_print (_("Updating extra metadata from remote summary for %s\n"), remote_name);
if (!flatpak_dir_update_remote_configuration (dir, remote_name, cancellable, &local_error))
{
g_printerr (_("Error updating extra metadata for '%s': %s\n"), remote_name, local_error->message);
return flatpak_fail (error, _("Could not update extra metadata for %s"), remote_name);
}
}
config = get_config_from_opts (dir, remote_name);
if (opt_gpg_import != NULL)

View File

@ -293,7 +293,7 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
const char *repository;
char **prefs = NULL;
int i, n_prefs;
const char *default_branch = NULL;
g_autofree char *default_branch = NULL;
FlatpakKinds kinds;
g_autoptr(GPtrArray) refs = NULL;
@ -322,7 +322,7 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
/* Backwards compat for old "REPOSITORY NAME [BRANCH]" argument version */
if (argc == 4 && looks_like_branch (argv[3]))
{
default_branch = argv[3];
default_branch = g_strdup (argv[3]);
n_prefs = 1;
}
@ -343,7 +343,8 @@ flatpak_builtin_install (int argc, char **argv, GCancellable *cancellable, GErro
&matched_kinds, &id, &arch, &branch, error))
return FALSE;
ref = flatpak_dir_find_remote_ref (dir, repository, id, branch, arch,
default_branch = flatpak_dir_get_remote_default_branch (dir, repository);
ref = flatpak_dir_find_remote_ref (dir, repository, id, branch, default_branch, arch,
matched_kinds, &kind, cancellable, error);
if (ref == NULL)
return FALSE;

View File

@ -33,6 +33,7 @@
#include "flatpak-utils.h"
static char *opt_title;
static char *opt_default_branch;
static char *opt_gpg_homedir;
static char **opt_gpg_key_ids;
static gboolean opt_prune;
@ -41,6 +42,7 @@ static gint opt_prune_depth = -1;
static GOptionEntry options[] = {
{ "title", 0, 0, G_OPTION_ARG_STRING, &opt_title, N_("A nice name to use for this repository"), N_("TITLE") },
{ "default-branch", 0, 0, G_OPTION_ARG_STRING, &opt_default_branch, N_("Default branch to use for this repository"), N_("BRANCH") },
{ "gpg-sign", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_gpg_key_ids, N_("GPG Key ID to sign the summary with"), N_("KEY-ID") },
{ "gpg-homedir", 0, 0, G_OPTION_ARG_STRING, &opt_gpg_homedir, N_("GPG Homedir to use when looking for keyrings"), N_("HOMEDIR") },
{ "generate-static-deltas", 0, 0, G_OPTION_ARG_NONE, &opt_generate_deltas, N_("Generate delta files"), NULL },
@ -376,6 +378,10 @@ flatpak_builtin_build_update_repo (int argc, char **argv,
!flatpak_repo_set_title (repo, opt_title, error))
return FALSE;
if (opt_default_branch &&
!flatpak_repo_set_default_branch (repo, opt_default_branch, error))
return FALSE;
g_print (_("Updating appstream branch\n"));
if (!flatpak_repo_generate_appstream (repo, (const char **) opt_gpg_key_ids, opt_gpg_homedir, cancellable, error))
return FALSE;

View File

@ -4362,6 +4362,7 @@ static char *
find_matching_ref (GHashTable *refs,
const char *name,
const char *opt_branch,
const char *opt_default_branch,
const char *opt_arch,
FlatpakKinds kinds,
GError **error)
@ -4377,6 +4378,7 @@ find_matching_ref (GHashTable *refs,
for (i = 0; arches[i] != NULL; i++)
{
g_autoptr(GPtrArray) matched_refs = NULL;
int j;
matched_refs = find_matching_refs (refs, name, opt_branch, arches[i],
kinds, error);
@ -4386,25 +4388,36 @@ find_matching_ref (GHashTable *refs,
if (matched_refs->len == 0)
continue;
if (matched_refs->len > 1)
if (matched_refs->len == 1)
return g_strdup (g_ptr_array_index (matched_refs, 0));
/* Multiple refs found, see if some belongs to the default branch, if passed */
if (opt_default_branch != NULL)
{
int i;
g_autoptr(GString) err = g_string_new ("");
g_string_printf (err, "Multiple branches available for %s, you must specify one of: ", name);
for (i = 0; i < matched_refs->len; i++)
for (j = 0; j < matched_refs->len; j++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (g_ptr_array_index (matched_refs, i), NULL);
if (i != 0)
g_string_append (err, ", ");
char *current_ref = g_ptr_array_index (matched_refs, j);
g_auto(GStrv) parts = flatpak_decompose_ref (current_ref, NULL);
g_string_append (err, parts[3]);
if (g_strcmp0 (opt_default_branch, parts[3]) == 0)
return g_strdup (current_ref);
}
flatpak_fail (error, err->str);
return NULL;
}
return g_strdup (g_ptr_array_index (matched_refs, 0));
/* Nothing to do other than reporting the different choices */
g_autoptr(GString) err = g_string_new ("");
g_string_printf (err, "Multiple branches available for %s, you must specify one of: ", name);
for (j = 0; j < matched_refs->len; j++)
{
g_auto(GStrv) parts = flatpak_decompose_ref (g_ptr_array_index (matched_refs, j), NULL);
if (j != 0)
g_string_append (err, ", ");
g_string_append (err, parts[3]);
}
flatpak_fail (error, err->str);
return NULL;
}
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
@ -4446,6 +4459,7 @@ flatpak_dir_find_remote_ref (FlatpakDir *self,
const char *remote,
const char *name,
const char *opt_branch,
const char *opt_default_branch,
const char *opt_arch,
FlatpakKinds kinds,
FlatpakKinds *out_kind,
@ -4463,7 +4477,7 @@ flatpak_dir_find_remote_ref (FlatpakDir *self,
&remote_refs, cancellable, error))
return NULL;
remote_ref = find_matching_ref (remote_refs, name, opt_branch,
remote_ref = find_matching_ref (remote_refs, name, opt_branch, opt_default_branch,
opt_arch, kinds, &my_error);
if (remote_ref == NULL)
{
@ -4580,7 +4594,7 @@ flatpak_dir_find_installed_ref (FlatpakDir *self,
if (local_refs == NULL)
return NULL;
local_ref = find_matching_ref (local_refs, opt_name, opt_branch,
local_ref = find_matching_ref (local_refs, opt_name, opt_branch, NULL,
opt_arch, kinds, &my_error);
if (local_ref == NULL)
{
@ -5211,18 +5225,14 @@ flatpak_dir_list_remote_refs (FlatpakDir *self,
return TRUE;
}
char *
flatpak_dir_fetch_remote_title (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error)
static GVariant *
fetch_remote_summary_file (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GError) my_error = NULL;
g_autoptr(GBytes) summary_bytes = NULL;
g_autoptr(GVariant) summary = NULL;
g_autoptr(GVariant) extensions = NULL;
GVariantDict dict;
g_autofree char *title = NULL;
if (error == NULL)
error = &my_error;
@ -5233,17 +5243,35 @@ flatpak_dir_fetch_remote_title (FlatpakDir *self,
if (!flatpak_dir_remote_fetch_summary (self, remote,
&summary_bytes,
cancellable, error))
return FALSE;
return NULL;
if (summary_bytes == NULL)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
_("Remote title not available; server has no summary file"));
return FALSE;
_("Remote extra metadata not available; server has no summary file"));
return NULL;
}
summary = g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT,
summary_bytes, FALSE));
return g_variant_ref_sink (g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT,
summary_bytes, FALSE));
}
char *
flatpak_dir_fetch_remote_title (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GVariant) summary = NULL;
g_autoptr(GVariant) extensions = NULL;
GVariantDict dict;
g_autofree char *title = NULL;
summary = fetch_remote_summary_file (self, remote, cancellable, error);
if (summary == NULL)
return NULL;
extensions = g_variant_get_child_value (summary, 1);
g_variant_dict_init (&dict, extensions);
@ -5260,6 +5288,115 @@ flatpak_dir_fetch_remote_title (FlatpakDir *self,
return g_steal_pointer (&title);
}
char *
flatpak_dir_fetch_remote_default_branch (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error)
{
g_autoptr(GVariant) summary = NULL;
g_autoptr(GVariant) extensions = NULL;
GVariantDict dict;
g_autofree char *default_branch = NULL;
summary = fetch_remote_summary_file (self, remote, cancellable, error);
if (summary == NULL)
return NULL;
extensions = g_variant_get_child_value (summary, 1);
g_variant_dict_init (&dict, extensions);
g_variant_dict_lookup (&dict, "xa.default-branch", "s", &default_branch);
g_variant_dict_end (&dict);
if (default_branch == NULL)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
_("Remote default-branch not set"));
return FALSE;
}
return g_steal_pointer (&default_branch);
}
gboolean
flatpak_dir_update_remote_configuration (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error)
{
/* We only support those configuration parameters that can
be set in the server when building the repo (see the
flatpak_repo_set_* () family of functions) */
static const char *const supported_params[] = {
"xa.title",
"xa.default-branch", NULL
};
g_autoptr(GVariant) summary = NULL;
g_autoptr(GVariant) extensions = NULL;
g_autoptr(GPtrArray) updated_params = g_ptr_array_new_with_free_func (g_free);
GVariantIter iter;
summary = fetch_remote_summary_file (self, remote, cancellable, error);
if (summary == NULL)
return FALSE;
extensions = g_variant_get_child_value (summary, 1);
g_variant_iter_init (&iter, extensions);
if (g_variant_iter_n_children (&iter) > 0)
{
GVariant *value_var = NULL;
char *key = NULL;
while (g_variant_iter_next (&iter, "{sv}", &key, &value_var))
{
/* At the moment, every supported parameter are strings */
if (g_strv_contains (supported_params, key) &&
g_variant_get_type_string (value_var))
{
const char *value = g_variant_get_string(value_var, NULL);
if (value != NULL && *value != 0)
{
g_ptr_array_add (updated_params, g_strdup (key));
g_ptr_array_add (updated_params, g_strdup (value));
}
}
g_variant_unref (value_var);
g_free (key);
}
}
if (updated_params->len > 0)
{
g_autoptr(GKeyFile) config = NULL;
g_autofree char *group = NULL;
int i;
config = ostree_repo_copy_config (flatpak_dir_get_repo (self));
group = g_strdup_printf ("remote \"%s\"", remote);
i = 0;
while (i < (updated_params->len - 1))
{
/* This array should have an even number of elements with
keys in the odd positions and values on even ones. */
g_key_file_set_string (config, group,
g_ptr_array_index (updated_params, i),
g_ptr_array_index (updated_params, i+1));
i += 2;
}
/* Update the local remote configuration with the updated info. */
if (!flatpak_dir_modify_remote (self, remote, config, NULL, cancellable, error))
return FALSE;
}
return TRUE;
}
static gboolean
flatpak_dir_parse_summary_for_ref (FlatpakDir *self,
GVariant *summary,

View File

@ -157,6 +157,7 @@ char * flatpak_dir_find_remote_ref (FlatpakDir *self,
const char *remote,
const char *name,
const char *opt_branch,
const char *opt_default_branch,
const char *opt_arch,
FlatpakKinds kinds,
FlatpakKinds *out_kind,
@ -424,6 +425,14 @@ char * flatpak_dir_fetch_remote_title (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error);
char * flatpak_dir_fetch_remote_default_branch (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_update_remote_configuration (FlatpakDir *self,
const char *remote,
GCancellable *cancellable,
GError **error);
gboolean flatpak_dir_fetch_ref_cache (FlatpakDir *self,
const char *remote_name,
const char *ref,

View File

@ -2179,6 +2179,27 @@ flatpak_repo_set_title (OstreeRepo *repo,
return TRUE;
}
gboolean
flatpak_repo_set_default_branch (OstreeRepo *repo,
const char *branch,
GError **error)
{
g_autoptr(GKeyFile) config = NULL;
config = ostree_repo_copy_config (repo);
if (branch)
g_key_file_set_string (config, "flatpak", "default-branch", branch);
else
g_key_file_remove_key (config, "flatpak", "default-branch", NULL);
if (!ostree_repo_write_config (repo, config, error))
return FALSE;
return TRUE;
}
#define OSTREE_GIO_FAST_QUERYINFO ("standard::name,standard::type,standard::size,standard::is-symlink,standard::symlink-target," \
"unix::device,unix::inode,unix::mode,unix::uid,unix::gid,unix::rdev")
@ -2299,6 +2320,7 @@ flatpak_repo_update (OstreeRepo *repo,
GVariantBuilder ref_data_builder;
GKeyFile *config;
g_autofree char *title = NULL;
g_autofree char *default_branch = NULL;
g_autoptr(GVariant) old_summary = NULL;
g_autoptr(GHashTable) refs = NULL;
const char *prefixes[] = { "appstream", "app", "runtime", NULL };
@ -2312,12 +2334,18 @@ flatpak_repo_update (OstreeRepo *repo,
config = ostree_repo_get_config (repo);
if (config)
title = g_key_file_get_string (config, "flatpak", "title", NULL);
{
title = g_key_file_get_string (config, "flatpak", "title", NULL);
default_branch = g_key_file_get_string (config, "flatpak", "default-branch", NULL);
}
if (title)
g_variant_builder_add (&builder, "{sv}", "xa.title",
g_variant_new_string (title));
if (default_branch)
g_variant_builder_add (&builder, "{sv}", "xa.default-branch",
g_variant_new_string (default_branch));
g_variant_builder_init (&ref_data_builder, G_VARIANT_TYPE ("a{s(tts)}"));

View File

@ -229,6 +229,9 @@ void flatpak_table_printer_print (FlatpakTablePrinter *printer);
gboolean flatpak_repo_set_title (OstreeRepo *repo,
const char *title,
GError **error);
gboolean flatpak_repo_set_default_branch (OstreeRepo *repo,
const char *branch,
GError **error);
gboolean flatpak_repo_update (OstreeRepo *repo,
const char **gpg_key_ids,
const char *gpg_homedir,

View File

@ -158,6 +158,18 @@
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--update-metadata</option></term>
<listitem><para>
A default branch to for the remote, mainly for use in a UI.
</para></listitem>
<listitem><para>
Update the remote's extra metadata from the OSTree repository's summary
file. Only xa.title and xa.default-branch are supported at the moment.
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>--gpg-import=FILE</option></term>

View File

@ -29,6 +29,7 @@ flatpak_installation_install_bundle
flatpak_installation_drop_caches
flatpak_installation_modify_remote
flatpak_installation_remove_remote
flatpak_installation_update_remote_sync
flatpak_get_default_arch
FlatpakProgressCallback
FlatpakUpdateFlags

View File

@ -798,6 +798,45 @@ flatpak_installation_remove_remote (FlatpakInstallation *self,
return TRUE;
}
/**
* flatpak_installation_update_remote_sync:
* @self: a #FlatpakInstallation
* @name: the name of the remote to update
* @cancellable: (nullable): a #GCancellable
* @error: return location for a #GError
*
* Updates the local configuration of a remote repository by fetching
* the related information from the summary file in the remote OSTree
* repository and committing the changes to the local installation.
*
* Returns: %TRUE if the remote has been updated successfully
*
* Since: 0.6.13
*/
gboolean
flatpak_installation_update_remote_sync (FlatpakInstallation *self,
const char *name,
GCancellable *cancellable,
GError **error)
{
g_autoptr(FlatpakDir) dir = flatpak_installation_get_dir (self);
g_autoptr(FlatpakDir) dir_clone = NULL;
/* We clone the dir here to make sure we re-read the latest ostree repo config, in case
it has local changes */
dir_clone = flatpak_dir_clone (dir);
if (!flatpak_dir_ensure_repo (dir_clone, cancellable, error))
return FALSE;
if (!flatpak_dir_update_remote_configuration (dir, name, cancellable, error))
return FALSE;
/* Make sure we pick up the new config */
flatpak_installation_drop_caches (self, NULL, NULL);
return TRUE;
}
/**
* flatpak_installation_get_remote_by_name:
* @self: a #FlatpakInstallation

View File

@ -158,6 +158,10 @@ FLATPAK_EXTERN gboolean flatpak_installation_remove_remote (Flatpak
const char *name,
GCancellable *cancellable,
GError **error);
FLATPAK_EXTERN gboolean flatpak_installation_update_remote_sync (FlatpakInstallation *self,
const char *name,
GCancellable *cancellable,
GError **error);
FLATPAK_EXTERN char * flatpak_installation_load_app_overrides (FlatpakInstallation *self,
const char *app_id,
GCancellable *cancellable,

View File

@ -357,11 +357,12 @@ main (int argc, char *argv[])
{
FlatpakRemote *remote = g_ptr_array_index (remotes, i);
g_autoptr(GPtrArray) refs = NULL;
g_print ("\nRemote: %s %d %s %s %d %d %s\n",
g_print ("\nRemote: %s %d %s %s %s %d %d %s\n",
flatpak_remote_get_name (remote),
flatpak_remote_get_prio (remote),
flatpak_remote_get_url (remote),
flatpak_remote_get_title (remote),
flatpak_remote_get_default_branch (remote),
flatpak_remote_get_gpg_verify (remote),
flatpak_remote_get_noenumerate (remote),
g_file_get_path (flatpak_remote_get_appstream_dir (remote, NULL)));