diff --git a/common/flatpak-remote.c b/common/flatpak-remote.c
index 72b0bfe1..16e00eb2 100644
--- a/common/flatpak-remote.c
+++ b/common/flatpak-remote.c
@@ -1089,6 +1089,90 @@ flatpak_remote_new (const char *name)
return flatpak_remote_new_with_dir (name, NULL);
}
+
+#define read_str_option(_key, _field) \
+ { \
+ char *val = g_key_file_get_string (config, group, _key, NULL); \
+ if (val != NULL) { \
+ priv->local_ ## _field = val; \
+ priv->local_ ## _field ## _set = TRUE; \
+ } \
+ }
+
+#define read_bool_option(_key, _field) \
+ if (g_key_file_has_key (config, group, _key, NULL)) { \
+ priv->local_ ## _field = g_key_file_get_boolean (config, group, _key, NULL); \
+ priv->local_ ## _field ## _set = TRUE; \
+ }
+
+#define read_int_option(_key, _field) \
+ if (g_key_file_has_key (config, group, _key, NULL)) { \
+ priv->local_ ## _field = g_key_file_get_integer (config, group, _key, NULL); \
+ priv->local_ ## _field ## _set = TRUE; \
+ }
+
+
+/**
+ * flatpak_remote_new_from_file:
+ * @name: a name
+ * @data: The content of a flatpakrepo file
+ * @error: return location for a #GError
+ *
+ * Returns a new pre-filled remote object which can be used to configure a new remote.
+ * The fields in the remote are filled in according to the values in the
+ * passed in flatpakrepo file.
+ *
+ * Note: This is a local configuration object, you must commit changes
+ * using flatpak_installation_modify_remote() or flatpak_installation_add_remote() for the changes to take
+ * effect.
+ *
+ * Returns: (transfer full): a new #FlatpakRemote, or %NULL on error
+ *
+ * Since: 1.3.4
+ **/
+FlatpakRemote *
+flatpak_remote_new_from_file (const char *name, GBytes *data, GError **error)
+{
+ FlatpakRemote *remote = flatpak_remote_new (name);
+ FlatpakRemotePrivate *priv = flatpak_remote_get_instance_private (remote);
+ g_autofree char *group = g_strdup_printf ("remote \"%s\"", name);
+ g_autoptr(GKeyFile) keyfile = g_key_file_new ();
+ g_autoptr(GKeyFile) config = NULL;
+ g_autoptr(GBytes) gpg_data = NULL;
+
+ if (!g_key_file_load_from_data (keyfile, g_bytes_get_data (data, NULL), g_bytes_get_size (data), 0, error))
+ return NULL;
+
+ config = flatpak_parse_repofile (name, FALSE, keyfile, &gpg_data, NULL, error);
+ if (config == NULL)
+ return NULL;
+
+ priv->local_gpg_key = g_steal_pointer (&gpg_data);
+
+ read_str_option("url", url);
+ read_str_option("collection-id", collection_id);
+ read_str_option("xa.title", title);
+ read_str_option("xa.filter", filter);
+ /* Canonicalize empty to null-but-is-set */
+ if (priv->local_filter && priv->local_filter[0] == 0)
+ g_free (g_steal_pointer (&priv->local_filter));
+ read_str_option("xa.comment", comment);
+ read_str_option("xa.description", description);
+ read_str_option("xa.homepage", homepage);
+ read_str_option("xa.icon", icon);
+ read_str_option("xa.default-branch", default_branch);
+ read_str_option("xa.main-ref", main_ref);
+
+ read_bool_option("xa.gpg-verify", gpg_verify);
+ read_bool_option("xa.noenumerate", noenumerate);
+ read_bool_option("xa.disable", disabled);
+ read_bool_option("xa.nodeps", nodeps);
+
+ read_int_option("xa.prio", prio);
+
+ return remote;
+}
+
/* copied from GLib */
static gboolean
g_key_file_is_group_name (const gchar *name)
@@ -1192,7 +1276,7 @@ flatpak_remote_commit (FlatpakRemote *self,
g_key_file_set_string (config, group, "xa.title", priv->local_title);
if (priv->local_filter_set)
- g_key_file_set_string (config, group, "xa.filter", priv->local_filter);
+ g_key_file_set_string (config, group, "xa.filter", priv->local_filter ? priv->local_filter : "");
if (priv->local_comment_set)
g_key_file_set_string (config, group, "xa.comment", priv->local_comment);
diff --git a/common/flatpak-remote.h b/common/flatpak-remote.h
index 80fe2292..fa223d33 100644
--- a/common/flatpak-remote.h
+++ b/common/flatpak-remote.h
@@ -65,6 +65,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (FlatpakRemote, g_object_unref)
#endif
FLATPAK_EXTERN FlatpakRemote * flatpak_remote_new (const char *name);
+FLATPAK_EXTERN FlatpakRemote * flatpak_remote_new_from_file (const char *name,
+ GBytes *data,
+ GError **error);
FLATPAK_EXTERN const char * flatpak_remote_get_name (FlatpakRemote *self);
FLATPAK_EXTERN GFile * flatpak_remote_get_appstream_dir (FlatpakRemote *self,
diff --git a/doc/reference/flatpak-sections.txt b/doc/reference/flatpak-sections.txt
index db585b75..08f7b22e 100644
--- a/doc/reference/flatpak-sections.txt
+++ b/doc/reference/flatpak-sections.txt
@@ -151,6 +151,7 @@ flatpak_ref_get_type
FlatpakRemote
FlatpakRemote
flatpak_remote_new
+flatpak_remote_new_from_file
flatpak_remote_get_name
flatpak_remote_get_appstream_dir
flatpak_remote_get_appstream_timestamp
diff --git a/tests/testlibrary.c b/tests/testlibrary.c
index 64c33401..f2773dc8 100644
--- a/tests/testlibrary.c
+++ b/tests/testlibrary.c
@@ -683,6 +683,105 @@ test_remote_new (void)
g_clear_error (&error);
}
+static void
+test_remote_new_from_file (void)
+{
+ g_autoptr(FlatpakInstallation) inst = NULL;
+ g_autoptr(FlatpakRemote) remote = NULL;
+ g_autoptr(GError) error = NULL;
+ gboolean res;
+ const char *_data =
+ "[Flatpak Repo]\n"
+ "Url=http://127.0.0.1/repo\n"
+ "Title=The Title\n"
+ "Comment=The Comment\n"
+ "Description=The Description\n"
+ "Homepage=https://the.homepage/\n"
+ "Icon=https://the.icon/\n"
+ "DefaultBranch=default-branch\n"
+ "NoDeps=true\n";
+ g_autoptr(GBytes) data = g_bytes_new_static (_data, strlen (_data));
+
+ inst = flatpak_installation_new_user (NULL, &error);
+ g_assert_no_error (error);
+
+ remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
+ g_assert_null (remote);
+ g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_REMOTE_NOT_FOUND);
+ g_clear_error (&error);
+
+ remote = flatpak_remote_new_from_file ("file-remote", data, &error);
+ g_assert_nonnull (remote);
+ g_assert_no_error (error);
+
+ res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_clear_object (&remote);
+
+ remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/repo");
+ g_assert_cmpstr (flatpak_remote_get_title (remote), ==, "The Title");
+ g_assert_cmpstr (flatpak_remote_get_comment (remote), ==, "The Comment");
+ g_assert_cmpstr (flatpak_remote_get_description (remote), ==, "The Description");
+ g_assert_cmpstr (flatpak_remote_get_homepage (remote), ==, "https://the.homepage/");
+ g_assert_cmpstr (flatpak_remote_get_icon (remote), ==, "https://the.icon/");
+ g_assert_cmpstr (flatpak_remote_get_default_branch (remote), ==, "default-branch");
+ g_assert_cmpint (flatpak_remote_get_nodeps (remote), ==, TRUE);
+
+ g_clear_object (&remote);
+
+ remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (flatpak_remote_get_filter (remote), ==, NULL);
+
+ flatpak_remote_set_url (remote, "http://127.0.0.1/other");
+ flatpak_remote_set_filter (remote, "/some/path/to/filter");
+
+ res = flatpak_installation_modify_remote (inst, remote, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_clear_object (&remote);
+
+ remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/other");
+ g_assert_cmpstr (flatpak_remote_get_filter (remote), ==, "/some/path/to/filter");
+
+ g_clear_object (&remote);
+
+ remote = flatpak_remote_new_from_file ("file-remote", data, &error);
+ g_assert_nonnull (remote);
+ g_assert_no_error (error);
+
+ /* regular add fails */
+ res = flatpak_installation_add_remote (inst, remote, FALSE, NULL, &error);
+ g_assert_error (error, FLATPAK_ERROR, FLATPAK_ERROR_ALREADY_INSTALLED);
+ g_clear_error (&error);
+ g_assert_false (res);
+
+ /* add if needed succeeds and resets filter */
+ res = flatpak_installation_add_remote (inst, remote, TRUE, NULL, &error);
+ g_assert_no_error (error);
+ g_assert_true (res);
+
+ g_clear_object (&remote);
+
+ remote = flatpak_installation_get_remote_by_name (inst, "file-remote", NULL, &error);
+ g_assert_no_error (error);
+
+ g_assert_cmpstr (flatpak_remote_get_url (remote), ==, "http://127.0.0.1/other");
+ g_assert_cmpstr (flatpak_remote_get_filter (remote), ==, NULL);
+
+ g_clear_object (&remote);
+}
+
static void
test_list_refs (void)
{
@@ -3544,6 +3643,7 @@ main (int argc, char *argv[])
g_test_add_func ("/library/remote-by-name", test_remote_by_name);
g_test_add_func ("/library/remote", test_remote);
g_test_add_func ("/library/remote-new", test_remote_new);
+ g_test_add_func ("/library/remote-new-from-file", test_remote_new_from_file);
g_test_add_func ("/library/list-remote-refs", test_list_remote_refs);
g_test_add_func ("/library/list-remote-related-refs", test_list_remote_related_refs);
g_test_add_func ("/library/list-refs", test_list_refs);