lib: List dynamic remotes in flatpak_installation_list_remotes()

Also expose a new flatpak_remote_get_remote_type() API so that users can
query what type of remote something is — whether it’s a USB or LAN
remote, or something statically configured.

Make this all conditional on compiling with --enable-p2p.

Signed-off-by: Philip Withnall <withnall@endlessm.com>
tingping/wmclass
Philip Withnall 2017-05-16 13:11:52 +01:00 committed by Alexander Larsson
parent 30a5cf8136
commit 68ab12fce1
4 changed files with 189 additions and 3 deletions

View File

@ -22,6 +22,11 @@
#include <string.h>
#ifdef FLATPAK_ENABLE_P2P
#include <ostree.h>
#include <ostree-repo-finder-avahi.h>
#endif /* FLATPAK_ENABLE_P2P */
#include "flatpak-utils.h"
#include "flatpak-installation.h"
#include "flatpak-installed-ref-private.h"
@ -878,6 +883,93 @@ flatpak_installation_list_installed_refs_for_update (FlatpakInstallation *self,
return g_steal_pointer (&updates);
}
#ifdef FLATPAK_ENABLE_P2P
static void
async_result_cb (GObject *obj,
GAsyncResult *result,
gpointer user_data)
{
GAsyncResult **result_out = user_data;
*result_out = g_object_ref (result);
}
#endif /* FLATPAK_ENABLE_P2P */
/* Find all USB and LAN repositories which share the same collection ID as
* @remote_name, and add a #FlatpakRemote to @remotes for each of them. The caller
* must initialise @remotes. Returns %TRUE without modifying @remotes if the
* given remote doesnt have a collection ID configured.
*
* FIXME: If this were async, the parallelisation could be handled in the caller. */
static gboolean
list_remotes_for_configured_remote (FlatpakInstallation *self,
const gchar *remote_name,
FlatpakDir *dir,
GPtrArray *remotes /* (element-type FlatpakRemote) */,
GCancellable *cancellable,
GError **error)
{
#ifdef FLATPAK_ENABLE_P2P
g_autofree gchar *collection_id = NULL;
OstreeCollectionRef ref;
const OstreeCollectionRef *refs[2] = { NULL, };
g_autofree gchar *appstream_ref = NULL;
g_autoptr(GMainContext) context = NULL;
g_auto(OstreeRepoFinderResultv) results = NULL;
g_autoptr(GAsyncResult) result = NULL;
g_autoptr(OstreeRepoFinder) finder_mount = NULL, finder_avahi = NULL;
OstreeRepoFinder *finders[3] = { NULL, };
gsize i;
/* Find the collection ID for @remote_name, or bail if there is none. */
if (!ostree_repo_get_remote_option (flatpak_dir_get_repo (dir),
remote_name, "collection-id",
NULL, &collection_id, error))
return FALSE;
if (collection_id == NULL || *collection_id == '\0')
return TRUE;
context = g_main_context_new ();
g_main_context_push_thread_default (context);
appstream_ref = g_strdup_printf ("appstream/%s", flatpak_get_arch ());
ref.collection_id = collection_id;
ref.ref_name = appstream_ref;
refs[0] = &ref;
finder_mount = OSTREE_REPO_FINDER (ostree_repo_finder_mount_new (NULL));
finder_avahi = OSTREE_REPO_FINDER (ostree_repo_finder_avahi_new (context));
finders[0] = finder_mount;
finders[1] = finder_avahi;
ostree_repo_finder_avahi_start (OSTREE_REPO_FINDER_AVAHI (finder_avahi), NULL); /* ignore failure */
ostree_repo_find_remotes_async (flatpak_dir_get_repo (dir),
(const OstreeCollectionRef * const *) refs,
NULL, /* no options */
finders,
NULL, /* no progress */
cancellable,
async_result_cb,
&result);
while (result == NULL)
g_main_context_iteration (context, TRUE);
results = ostree_repo_find_remotes_finish (flatpak_dir_get_repo (dir), result, error);
ostree_repo_finder_avahi_stop (OSTREE_REPO_FINDER_AVAHI (finder_avahi));
g_main_context_pop_thread_default (context);
for (i = 0; results != NULL && results[i] != NULL; i++)
{
g_ptr_array_add (remotes,
flatpak_remote_new_from_ostree (results[i]->remote,
results[i]->finder,
dir));
}
#endif /* FLATPAK_ENABLE_P2P */
return TRUE;
}
/**
* flatpak_installation_list_remotes:
@ -900,7 +992,7 @@ flatpak_installation_list_remotes (FlatpakInstallation *self,
g_autoptr(FlatpakDir) dir_clone = NULL;
g_auto(GStrv) remote_names = NULL;
g_autoptr(GPtrArray) remotes = g_ptr_array_new_with_free_func (g_object_unref);
int i;
gsize i;
remote_names = flatpak_dir_list_remotes (dir, cancellable, error);
if (remote_names == NULL)
@ -913,8 +1005,15 @@ flatpak_installation_list_remotes (FlatpakInstallation *self,
return NULL;
for (i = 0; remote_names[i] != NULL; i++)
g_ptr_array_add (remotes,
flatpak_remote_new_with_dir (remote_names[i], dir_clone));
{
g_ptr_array_add (remotes,
flatpak_remote_new_with_dir (remote_names[i], dir_clone));
/* Add the dynamic mirrors of this remote. */
if (!list_remotes_for_configured_remote (self, remote_names[i], dir_clone,
remotes, cancellable, error))
return NULL;
}
return g_steal_pointer (&remotes);
}

View File

@ -32,6 +32,12 @@
FlatpakRemote *flatpak_remote_new_with_dir (const char *name,
FlatpakDir *dir);
#ifdef FLATPAK_ENABLE_P2P
FlatpakRemote *flatpak_remote_new_from_ostree (OstreeRemote *remote,
OstreeRepoFinder *repo_finder,
FlatpakDir *dir);
#endif /* FLATPAK_ENABLE_P2P */
gboolean flatpak_remote_commit (FlatpakRemote *self,
FlatpakDir *dir,
GCancellable *cancellable,

View File

@ -26,6 +26,18 @@
#include "flatpak-enum-types.h"
#include <string.h>
#include <ostree.h>
#ifdef FLATPAK_ENABLE_P2P
#include <ostree-repo-finder-avahi.h>
#endif /* FLATPAK_ENABLE_P2P */
#ifndef FLATPAK_ENABLE_P2P
/* Avoid too many #ifdefs by redefining this enum when compiling without P2P support. */
typedef enum {
FLATPAK_REMOTE_TYPE_STATIC = 0,
} FlatpakRemoteType;
#endif /* FLATPAK_ENABLE_P2P */
/**
* SECTION:flatpak-remote
@ -61,6 +73,7 @@ struct _FlatpakRemotePrivate
gboolean local_nodeps;
gboolean local_disabled;
int local_prio;
FlatpakRemoteType type;
guint local_url_set : 1;
guint local_title_set : 1;
@ -80,6 +93,7 @@ enum {
PROP_0,
PROP_NAME,
PROP_TYPE,
};
static void
@ -117,6 +131,10 @@ flatpak_remote_set_property (GObject *object,
priv->name = g_value_dup_string (value);
break;
case PROP_TYPE:
priv->type = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -138,6 +156,10 @@ flatpak_remote_get_property (GObject *object,
g_value_set_string (value, priv->name);
break;
case PROP_TYPE:
g_value_set_enum (value, priv->type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -160,6 +182,19 @@ flatpak_remote_class_init (FlatpakRemoteClass *klass)
"The name of the remote",
NULL,
G_PARAM_READWRITE));
#ifdef FLATPAK_ENABLE_P2P
#ifndef __GI_SCANNER__
g_object_class_install_property (object_class,
PROP_TYPE,
g_param_spec_enum ("type",
"Type",
"The type of the remote",
FLATPAK_TYPE_REMOTE_TYPE,
FLATPAK_REMOTE_TYPE_STATIC,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
#endif /* !__GI_SCANNER__ */
#endif /* FLATPAK_ENABLE_P2P */
}
static void
@ -637,6 +672,37 @@ flatpak_remote_new_with_dir (const char *name,
return self;
}
#ifdef FLATPAK_ENABLE_P2P
static FlatpakRemoteType
repo_finder_to_remote_type (OstreeRepoFinder *repo_finder)
{
if (OSTREE_IS_REPO_FINDER_AVAHI (repo_finder))
return FLATPAK_REMOTE_TYPE_LAN;
else if (OSTREE_IS_REPO_FINDER_MOUNT (repo_finder))
return FLATPAK_REMOTE_TYPE_USB;
else
return FLATPAK_REMOTE_TYPE_STATIC;
}
FlatpakRemote *
flatpak_remote_new_from_ostree (OstreeRemote *remote,
OstreeRepoFinder *repo_finder,
FlatpakDir *dir)
{
FlatpakRemotePrivate *priv;
FlatpakRemote *self = g_object_new (FLATPAK_TYPE_REMOTE,
"name", ostree_remote_get_name (remote),
"type", repo_finder_to_remote_type (repo_finder),
NULL);
priv = flatpak_remote_get_instance_private (self);
if (dir)
priv->dir = g_object_ref (dir);
return self;
}
#endif /* FLATPAK_ENABLE_P2P */
/**
* flatpak_remote_new:
* @name: a name
@ -670,6 +736,9 @@ flatpak_remote_commit (FlatpakRemote *self,
if (url == NULL || *url == 0)
return flatpak_fail (error, "No url specified");
if (priv->type != FLATPAK_REMOTE_TYPE_STATIC)
return flatpak_fail (error, "Dynamic remote cannot be committed");
config = ostree_repo_copy_config (flatpak_dir_get_repo (dir));
if (priv->local_url_set)
g_key_file_set_string (config, group, "url", priv->local_url);

View File

@ -25,6 +25,15 @@
#ifndef __FLATPAK_REMOTE_H__
#define __FLATPAK_REMOTE_H__
#ifdef FLATPAK_ENABLE_P2P
typedef enum
{
FLATPAK_REMOTE_TYPE_STATIC, /*< skip >*/
FLATPAK_REMOTE_TYPE_USB, /*< skip >*/
FLATPAK_REMOTE_TYPE_LAN, /*< skip >*/
} FlatpakRemoteType;
#endif /* FLATPAK_ENABLE_P2P */
typedef struct _FlatpakRemote FlatpakRemote;
#include <gio/gio.h>
@ -84,6 +93,9 @@ FLATPAK_EXTERN int flatpak_remote_get_prio (FlatpakRemote *self);
FLATPAK_EXTERN void flatpak_remote_set_prio (FlatpakRemote *self,
int prio);
#ifdef FLATPAK_ENABLE_P2P
FLATPAK_EXTERN FlatpakRemoteType flatpak_remote_get_remote_type (FlatpakRemote *self);
#endif /* FLATPAK_ENABLE_P2P */
#endif /* __FLATPAK_REMOTE_H__ */