lib/repo-finder: Add config-file based OstreeRepoFinder implementation
This is a basic implementation of OstreeRepoFinder which resolves ref names to remote URIs by looking their collection IDs up in the local configuration of remotes who have their collection-id key set. Unit tests are included. Signed-off-by: Philip Withnall <withnall@endlessm.com> Closes: #924 Approved by: cgwalters
This commit is contained in:
parent
292230301d
commit
d15f83c922
|
|
@ -43,6 +43,7 @@ libostree_public_headers += \
|
||||||
src/libostree/ostree-ref.h \
|
src/libostree/ostree-ref.h \
|
||||||
src/libostree/ostree-remote.h \
|
src/libostree/ostree-remote.h \
|
||||||
src/libostree/ostree-repo-finder.h \
|
src/libostree/ostree-repo-finder.h \
|
||||||
|
src/libostree/ostree-repo-finder-config.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,10 +155,12 @@ libostree_1_la_SOURCES += \
|
||||||
src/libostree/ostree-ref.h \
|
src/libostree/ostree-ref.h \
|
||||||
src/libostree/ostree-remote.h \
|
src/libostree/ostree-remote.h \
|
||||||
src/libostree/ostree-repo-finder.h \
|
src/libostree/ostree-repo-finder.h \
|
||||||
|
src/libostree/ostree-repo-finder-config.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
else # if ENABLE_EXPERIMENTAL_API
|
else # if ENABLE_EXPERIMENTAL_API
|
||||||
libostree_1_la_SOURCES += \
|
libostree_1_la_SOURCES += \
|
||||||
src/libostree/ostree-repo-finder.c \
|
src/libostree/ostree-repo-finder.c \
|
||||||
|
src/libostree/ostree-repo-finder-config.c \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
@ -235,7 +237,7 @@ OSTree_1_0_gir_INCLUDES = Gio-2.0
|
||||||
OSTree_1_0_gir_CFLAGS = $(libostree_1_la_CFLAGS)
|
OSTree_1_0_gir_CFLAGS = $(libostree_1_la_CFLAGS)
|
||||||
OSTree_1_0_gir_LIBS = libostree-1.la
|
OSTree_1_0_gir_LIBS = libostree-1.la
|
||||||
OSTree_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=Ostree --symbol-prefix=ostree
|
OSTree_1_0_gir_SCANNERFLAGS = --warn-all --identifier-prefix=Ostree --symbol-prefix=ostree
|
||||||
OSTree_1_0_gir_FILES = $(libostreeinclude_HEADERS) $(filter-out %-private.h %/ostree-soup-uri.h %/ostree-repo-finder.h,$(libostree_1_la_SOURCES))
|
OSTree_1_0_gir_FILES = $(libostreeinclude_HEADERS) $(filter-out %-private.h %/ostree-soup-uri.h %/ostree-repo-finder.h %/ostree-repo-finder-config.h,$(libostree_1_la_SOURCES))
|
||||||
INTROSPECTION_GIRS += OSTree-1.0.gir
|
INTROSPECTION_GIRS += OSTree-1.0.gir
|
||||||
gir_DATA += OSTree-1.0.gir
|
gir_DATA += OSTree-1.0.gir
|
||||||
typelib_DATA += OSTree-1.0.typelib
|
typelib_DATA += OSTree-1.0.typelib
|
||||||
|
|
|
||||||
|
|
@ -193,6 +193,12 @@ _installed_or_uninstalled_test_programs = tests/test-varint tests/test-ot-unix-u
|
||||||
tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \
|
tests/test-gpg-verify-result tests/test-checksum tests/test-lzma tests/test-rollsum \
|
||||||
tests/test-basic-c tests/test-sysroot-c tests/test-pull-c
|
tests/test-basic-c tests/test-sysroot-c tests/test-pull-c
|
||||||
|
|
||||||
|
if ENABLE_EXPERIMENTAL_API
|
||||||
|
test_programs += \
|
||||||
|
tests/test-repo-finder-config \
|
||||||
|
$(NULL)
|
||||||
|
endif
|
||||||
|
|
||||||
# An interactive tool
|
# An interactive tool
|
||||||
noinst_PROGRAMS += tests/test-rollsum-cli
|
noinst_PROGRAMS += tests/test-rollsum-cli
|
||||||
|
|
||||||
|
|
@ -219,6 +225,10 @@ tests_test_rollsum_SOURCES = src/libostree/ostree-rollsum.c tests/test-rollsum.c
|
||||||
tests_test_rollsum_CFLAGS = $(TESTS_CFLAGS) $(OT_DEP_ZLIB_CFLAGS)
|
tests_test_rollsum_CFLAGS = $(TESTS_CFLAGS) $(OT_DEP_ZLIB_CFLAGS)
|
||||||
tests_test_rollsum_LDADD = $(bupsplitpath) $(TESTS_LDADD) $(OT_DEP_ZLIB_LIBS)
|
tests_test_rollsum_LDADD = $(bupsplitpath) $(TESTS_LDADD) $(OT_DEP_ZLIB_LIBS)
|
||||||
|
|
||||||
|
tests_test_repo_finder_config_SOURCES = tests/test-repo-finder-config.c
|
||||||
|
tests_test_repo_finder_config_CFLAGS = $(TESTS_CFLAGS)
|
||||||
|
tests_test_repo_finder_config_LDADD = $(TESTS_LDADD)
|
||||||
|
|
||||||
tests_test_mutable_tree_CFLAGS = $(TESTS_CFLAGS)
|
tests_test_mutable_tree_CFLAGS = $(TESTS_CFLAGS)
|
||||||
tests_test_mutable_tree_LDADD = $(TESTS_LDADD)
|
tests_test_mutable_tree_LDADD = $(TESTS_LDADD)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,14 @@ ostree_repo_finder_get_type
|
||||||
ostree_repo_finder_result_get_type
|
ostree_repo_finder_result_get_type
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
<SECTION>
|
||||||
|
<FILE>ostree-repo-finder-config</FILE>
|
||||||
|
OstreeRepoFinderConfig
|
||||||
|
ostree_repo_finder_config_new
|
||||||
|
<SUBSECTION Standard>
|
||||||
|
ostree_repo_finder_config_get_type
|
||||||
|
</SECTION>
|
||||||
|
|
||||||
<SECTION>
|
<SECTION>
|
||||||
<FILE>ostree-misc-experimental</FILE>
|
<FILE>ostree-misc-experimental</FILE>
|
||||||
ostree_repo_get_collection_id
|
ostree_repo_get_collection_id
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,8 @@ global:
|
||||||
ostree_collection_ref_new;
|
ostree_collection_ref_new;
|
||||||
ostree_repo_find_remotes_async;
|
ostree_repo_find_remotes_async;
|
||||||
ostree_repo_find_remotes_finish;
|
ostree_repo_find_remotes_finish;
|
||||||
|
ostree_repo_finder_config_get_type;
|
||||||
|
ostree_repo_finder_config_new;
|
||||||
ostree_repo_finder_get_type;
|
ostree_repo_finder_get_type;
|
||||||
ostree_repo_finder_resolve_async;
|
ostree_repo_finder_resolve_async;
|
||||||
ostree_repo_finder_resolve_all_async;
|
ostree_repo_finder_resolve_all_async;
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeCollectionRef, ostree_collection_ref_free)
|
||||||
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeCollectionRefv, ostree_collection_ref_freev, NULL)
|
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeCollectionRefv, ostree_collection_ref_freev, NULL)
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRemote, ostree_remote_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRemote, ostree_remote_unref)
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinder, g_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinder, g_object_unref)
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderConfig, g_object_unref)
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, ostree_repo_finder_result_free)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, ostree_repo_finder_result_free)
|
||||||
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, ostree_repo_finder_result_freev, NULL)
|
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, ostree_repo_finder_result_freev, NULL)
|
||||||
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
|
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,9 @@ G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeCollectionRefv, ostree_collection_ref_fre
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinder, g_object_unref)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinder, g_object_unref)
|
||||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, ostree_repo_finder_result_free)
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderResult, ostree_repo_finder_result_free)
|
||||||
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, ostree_repo_finder_result_freev, NULL)
|
G_DEFINE_AUTO_CLEANUP_FREE_FUNC (OstreeRepoFinderResultv, ostree_repo_finder_result_freev, NULL)
|
||||||
|
|
||||||
|
#include "ostree-repo-finder-config.h"
|
||||||
|
G_DEFINE_AUTOPTR_CLEANUP_FUNC (OstreeRepoFinderConfig, g_object_unref)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,235 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright © 2017 Endless Mobile, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Philip Withnall <withnall@endlessm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <libglnx.h>
|
||||||
|
|
||||||
|
#include "ostree-remote-private.h"
|
||||||
|
#include "ostree-repo.h"
|
||||||
|
#include "ostree-repo-private.h"
|
||||||
|
#include "ostree-repo-finder.h"
|
||||||
|
#include "ostree-repo-finder-config.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:ostree-repo-finder-config
|
||||||
|
* @title: OstreeRepoFinderConfig
|
||||||
|
* @short_description: Finds remote repositories from ref names using the local
|
||||||
|
* repository configuration files
|
||||||
|
* @stability: Unstable
|
||||||
|
* @include: libostree/ostree-repo-finder-config.h
|
||||||
|
*
|
||||||
|
* #OstreeRepoFinderConfig is an implementation of #OstreeRepoFinder which looks
|
||||||
|
* refs up in locally configured remotes and returns remote URIs.
|
||||||
|
* Duplicate remote URIs are combined into a single #OstreeRepoFinderResult
|
||||||
|
* which lists multiple refs.
|
||||||
|
*
|
||||||
|
* For all the locally configured remotes which have an `collection-id` specified
|
||||||
|
* (see [ostree.repo-config(5)](man:ostree.repo-config(5))), it finds the
|
||||||
|
* intersection of their refs and the set of refs to resolve. If the
|
||||||
|
* intersection is non-empty, that remote is returned as a result. Remotes which
|
||||||
|
* do not have their `collection-id` key configured are ignored.
|
||||||
|
*
|
||||||
|
* Since: 2017.8
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void ostree_repo_finder_config_iface_init (OstreeRepoFinderInterface *iface);
|
||||||
|
|
||||||
|
struct _OstreeRepoFinderConfig
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (OstreeRepoFinderConfig, ostree_repo_finder_config, G_TYPE_OBJECT,
|
||||||
|
G_IMPLEMENT_INTERFACE (OSTREE_TYPE_REPO_FINDER, ostree_repo_finder_config_iface_init))
|
||||||
|
|
||||||
|
static gint
|
||||||
|
results_compare_cb (gconstpointer a,
|
||||||
|
gconstpointer b)
|
||||||
|
{
|
||||||
|
const OstreeRepoFinderResult *result_a = *((const OstreeRepoFinderResult **) a);
|
||||||
|
const OstreeRepoFinderResult *result_b = *((const OstreeRepoFinderResult **) b);
|
||||||
|
|
||||||
|
return ostree_repo_finder_result_compare (result_a, result_b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_repo_finder_config_resolve_async (OstreeRepoFinder *finder,
|
||||||
|
const OstreeCollectionRef * const *refs,
|
||||||
|
OstreeRepo *parent_repo,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr(GTask) task = NULL;
|
||||||
|
g_autoptr(GPtrArray) results = NULL;
|
||||||
|
const gint priority = 100; /* arbitrarily chosen; lower than the others */
|
||||||
|
gsize i, j;
|
||||||
|
g_autoptr(GHashTable) repo_name_to_refs = NULL; /* (element-type utf8 GHashTable) */
|
||||||
|
GHashTable *supported_ref_to_checksum; /* (element-type OstreeCollectionRef utf8) */
|
||||||
|
GHashTableIter iter;
|
||||||
|
const gchar *remote_name;
|
||||||
|
g_auto(GStrv) remotes = NULL;
|
||||||
|
gsize n_remotes = 0;
|
||||||
|
|
||||||
|
task = g_task_new (finder, cancellable, callback, user_data);
|
||||||
|
g_task_set_source_tag (task, ostree_repo_finder_config_resolve_async);
|
||||||
|
results = g_ptr_array_new_with_free_func ((GDestroyNotify) ostree_repo_finder_result_free);
|
||||||
|
repo_name_to_refs = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
|
||||||
|
(GDestroyNotify) g_hash_table_unref);
|
||||||
|
|
||||||
|
/* List all remotes in this #OstreeRepo and see which of their ref lists
|
||||||
|
* intersect with @refs. */
|
||||||
|
remotes = ostree_repo_remote_list (parent_repo, (guint *) &n_remotes);
|
||||||
|
|
||||||
|
g_debug ("%s: Checking %" G_GSIZE_FORMAT " remotes", G_STRFUNC, n_remotes);
|
||||||
|
|
||||||
|
for (i = 0; i < n_remotes; i++)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
g_autoptr(GHashTable) remote_refs = NULL; /* (element-type utf8 utf8) */
|
||||||
|
const gchar *checksum;
|
||||||
|
g_autofree gchar *remote_collection_id = NULL;
|
||||||
|
|
||||||
|
remote_name = remotes[i];
|
||||||
|
|
||||||
|
if (!ostree_repo_get_remote_option (parent_repo, remote_name, "collection-id",
|
||||||
|
NULL, &remote_collection_id, &local_error) ||
|
||||||
|
!ostree_validate_collection_id (remote_collection_id, &local_error))
|
||||||
|
{
|
||||||
|
g_debug ("Ignoring remote ‘%s’ due to no valid collection ID being configured for it: %s",
|
||||||
|
remote_name, local_error->message);
|
||||||
|
g_clear_error (&local_error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ostree_repo_remote_list_refs (parent_repo, remote_name, &remote_refs,
|
||||||
|
cancellable, &local_error))
|
||||||
|
{
|
||||||
|
g_debug ("Ignoring remote ‘%s’ due to error loading its refs: %s",
|
||||||
|
remote_name, local_error->message);
|
||||||
|
g_clear_error (&local_error);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; refs[j] != NULL; j++)
|
||||||
|
{
|
||||||
|
if (g_strcmp0 (refs[j]->collection_id, remote_collection_id) == 0 &&
|
||||||
|
g_hash_table_lookup_extended (remote_refs, refs[j]->ref_name, NULL, (gpointer *) &checksum))
|
||||||
|
{
|
||||||
|
/* The requested ref is listed in the refs for this remote. Add
|
||||||
|
* the remote to the results, and the ref to its
|
||||||
|
* @supported_ref_to_checksum. */
|
||||||
|
g_debug ("Resolved ref (%s, %s) to remote ‘%s’.",
|
||||||
|
refs[j]->collection_id, refs[j]->ref_name, remote_name);
|
||||||
|
|
||||||
|
supported_ref_to_checksum = g_hash_table_lookup (repo_name_to_refs, remote_name);
|
||||||
|
|
||||||
|
if (supported_ref_to_checksum == NULL)
|
||||||
|
{
|
||||||
|
supported_ref_to_checksum = g_hash_table_new_full (ostree_collection_ref_hash,
|
||||||
|
ostree_collection_ref_equal,
|
||||||
|
NULL, g_free);
|
||||||
|
g_hash_table_insert (repo_name_to_refs, (gpointer) remote_name, supported_ref_to_checksum /* transfer */);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_insert (supported_ref_to_checksum,
|
||||||
|
(gpointer) refs[j], g_strdup (checksum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Aggregate the results. */
|
||||||
|
g_hash_table_iter_init (&iter, repo_name_to_refs);
|
||||||
|
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *) &remote_name, (gpointer *) &supported_ref_to_checksum))
|
||||||
|
{
|
||||||
|
g_autoptr(GError) local_error = NULL;
|
||||||
|
OstreeRemote *remote;
|
||||||
|
|
||||||
|
/* We don’t know what last-modified timestamp the remote has without
|
||||||
|
* making expensive HTTP queries, so leave that information blank. We
|
||||||
|
* assume that the configuration which says the refs and commits in
|
||||||
|
* @supported_ref_to_checksum are in the repository is correct; the code
|
||||||
|
* in ostree_repo_find_remotes_async() will check that. */
|
||||||
|
remote = _ostree_repo_get_remote_inherited (parent_repo, remote_name, &local_error);
|
||||||
|
if (remote == NULL)
|
||||||
|
{
|
||||||
|
g_debug ("Configuration for remote ‘%s’ could not be found. Ignoring.",
|
||||||
|
remote_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add (results, ostree_repo_finder_result_new (remote, finder, priority, supported_ref_to_checksum, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_sort (results, results_compare_cb);
|
||||||
|
|
||||||
|
g_task_return_pointer (task, g_steal_pointer (&results), (GDestroyNotify) g_ptr_array_unref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GPtrArray *
|
||||||
|
ostree_repo_finder_config_resolve_finish (OstreeRepoFinder *finder,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (g_task_is_valid (result, finder), NULL);
|
||||||
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_repo_finder_config_init (OstreeRepoFinderConfig *self)
|
||||||
|
{
|
||||||
|
/* Nothing to see here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_repo_finder_config_class_init (OstreeRepoFinderConfigClass *klass)
|
||||||
|
{
|
||||||
|
/* Nothing to see here. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ostree_repo_finder_config_iface_init (OstreeRepoFinderInterface *iface)
|
||||||
|
{
|
||||||
|
iface->resolve_async = ostree_repo_finder_config_resolve_async;
|
||||||
|
iface->resolve_finish = ostree_repo_finder_config_resolve_finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ostree_repo_finder_config_new:
|
||||||
|
*
|
||||||
|
* Create a new #OstreeRepoFinderConfig.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): a new #OstreeRepoFinderConfig
|
||||||
|
* Since: 2017.8
|
||||||
|
*/
|
||||||
|
OstreeRepoFinderConfig *
|
||||||
|
ostree_repo_finder_config_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (OSTREE_TYPE_REPO_FINDER_CONFIG, NULL);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright © 2017 Endless Mobile, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Philip Withnall <withnall@endlessm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
#include "ostree-repo-finder.h"
|
||||||
|
#include "ostree-types.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define OSTREE_TYPE_REPO_FINDER_CONFIG (ostree_repo_finder_config_get_type ())
|
||||||
|
|
||||||
|
/* Manually expanded version of the following, omitting autoptr support (for GLib < 2.44):
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
G_DECLARE_FINAL_TYPE (OstreeRepoFinderConfig, ostree_repo_finder_config, OSTREE, REPO_FINDER_CONFIG, GObject) */
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
GType ostree_repo_finder_config_get_type (void);
|
||||||
|
|
||||||
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||||
|
typedef struct _OstreeRepoFinderConfig OstreeRepoFinderConfig;
|
||||||
|
typedef struct { GObjectClass parent_class; } OstreeRepoFinderConfigClass;
|
||||||
|
|
||||||
|
static inline OstreeRepoFinderConfig *OSTREE_REPO_FINDER_CONFIG (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_CAST (ptr, ostree_repo_finder_config_get_type (), OstreeRepoFinderConfig); }
|
||||||
|
static inline gboolean OSTREE_IS_REPO_FINDER_CONFIG (gpointer ptr) { return G_TYPE_CHECK_INSTANCE_TYPE (ptr, ostree_repo_finder_config_get_type ()); }
|
||||||
|
G_GNUC_END_IGNORE_DEPRECATIONS
|
||||||
|
|
||||||
|
_OSTREE_PUBLIC
|
||||||
|
OstreeRepoFinderConfig *ostree_repo_finder_config_new (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
|
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
|
||||||
#include "ostree-repo-finder.h"
|
#include "ostree-repo-finder.h"
|
||||||
|
#include "ostree-repo-finder-config.h"
|
||||||
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
|
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
|
||||||
|
|
||||||
#include <gio/gunixinputstream.h>
|
#include <gio/gunixinputstream.h>
|
||||||
|
|
@ -4085,6 +4086,7 @@ ostree_repo_find_remotes_async (OstreeRepo *self,
|
||||||
g_autoptr(FindRemotesData) data = NULL;
|
g_autoptr(FindRemotesData) data = NULL;
|
||||||
GMainContext *context;
|
GMainContext *context;
|
||||||
OstreeRepoFinder *default_finders[4] = { NULL, };
|
OstreeRepoFinder *default_finders[4] = { NULL, };
|
||||||
|
g_autoptr(OstreeRepoFinder) finder_config = NULL;
|
||||||
|
|
||||||
g_return_if_fail (OSTREE_IS_REPO (self));
|
g_return_if_fail (OSTREE_IS_REPO (self));
|
||||||
g_return_if_fail (is_valid_collection_ref_array (refs));
|
g_return_if_fail (is_valid_collection_ref_array (refs));
|
||||||
|
|
@ -4103,6 +4105,10 @@ ostree_repo_find_remotes_async (OstreeRepo *self,
|
||||||
/* Are we using #OstreeRepoFinders provided by the user, or the defaults? */
|
/* Are we using #OstreeRepoFinders provided by the user, or the defaults? */
|
||||||
if (finders == NULL)
|
if (finders == NULL)
|
||||||
{
|
{
|
||||||
|
finder_config = OSTREE_REPO_FINDER (ostree_repo_finder_config_new ());
|
||||||
|
|
||||||
|
default_finders[0] = finder_config;
|
||||||
|
|
||||||
finders = default_finders;
|
finders = default_finders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@
|
||||||
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
|
#ifdef OSTREE_ENABLE_EXPERIMENTAL_API
|
||||||
#include <ostree-ref.h>
|
#include <ostree-ref.h>
|
||||||
#include <ostree-repo-finder.h>
|
#include <ostree-repo-finder.h>
|
||||||
|
#include <ostree-repo-finder-config.h>
|
||||||
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
|
#endif /* OSTREE_ENABLE_EXPERIMENTAL_API */
|
||||||
|
|
||||||
#include <ostree-autocleanups.h>
|
#include <ostree-autocleanups.h>
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,5 @@ test-mutable-tree
|
||||||
test-ot-opt-utils
|
test-ot-opt-utils
|
||||||
test-ot-tool-util
|
test-ot-tool-util
|
||||||
test-ot-unix-utils
|
test-ot-unix-utils
|
||||||
|
test-repo-finder-config
|
||||||
test-rollsum-cli
|
test-rollsum-cli
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,327 @@
|
||||||
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
|
||||||
|
*
|
||||||
|
* Copyright © 2017 Endless Mobile, Inc.
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* - Philip Withnall <withnall@endlessm.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib-object.h>
|
||||||
|
#include <libglnx.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "libostreetest.h"
|
||||||
|
#include "ostree-autocleanups.h"
|
||||||
|
#include "ostree-repo-finder.h"
|
||||||
|
#include "ostree-repo-finder-config.h"
|
||||||
|
|
||||||
|
/* Test fixture. Creates a temporary directory. */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
OstreeRepo *parent_repo; /* owned */
|
||||||
|
int working_dfd; /* owned */
|
||||||
|
GFile *working_dir; /* owned */
|
||||||
|
} Fixture;
|
||||||
|
|
||||||
|
static void
|
||||||
|
setup (Fixture *fixture,
|
||||||
|
gconstpointer test_data)
|
||||||
|
{
|
||||||
|
g_autofree gchar *tmp_name = NULL;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
tmp_name = g_strdup ("test-repo-finder-config-XXXXXX");
|
||||||
|
glnx_mkdtempat_open_in_system (tmp_name, 0700, &fixture->working_dfd, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_test_message ("Using temporary directory: %s", tmp_name);
|
||||||
|
|
||||||
|
glnx_shutil_mkdir_p_at (fixture->working_dfd, "repo", 0700, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_autoptr(GFile) tmp_dir = g_file_new_for_path (g_get_tmp_dir ());
|
||||||
|
fixture->working_dir = g_file_get_child (tmp_dir, tmp_name);
|
||||||
|
|
||||||
|
fixture->parent_repo = ot_test_setup_repo (NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
teardown (Fixture *fixture,
|
||||||
|
gconstpointer test_data)
|
||||||
|
{
|
||||||
|
glnx_fd_close int parent_repo_dfd = -1;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
|
||||||
|
/* Recursively remove the temporary directory. */
|
||||||
|
glnx_shutil_rm_rf_at (fixture->working_dfd, ".", NULL, NULL);
|
||||||
|
|
||||||
|
close (fixture->working_dfd);
|
||||||
|
fixture->working_dfd = -1;
|
||||||
|
|
||||||
|
/* The repo also needs its source files to be removed. This is the inverse
|
||||||
|
* of setup_test_repository() in libtest.sh. */
|
||||||
|
g_autofree gchar *parent_repo_path = g_file_get_path (ostree_repo_get_path (fixture->parent_repo));
|
||||||
|
glnx_opendirat (-1, parent_repo_path, TRUE, &parent_repo_dfd, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
glnx_shutil_rm_rf_at (parent_repo_dfd, "../files", NULL, NULL);
|
||||||
|
glnx_shutil_rm_rf_at (parent_repo_dfd, "../repo", NULL, NULL);
|
||||||
|
|
||||||
|
g_clear_object (&fixture->working_dir);
|
||||||
|
g_clear_object (&fixture->parent_repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test the object constructor works at a basic level. */
|
||||||
|
static void
|
||||||
|
test_repo_finder_config_init (void)
|
||||||
|
{
|
||||||
|
g_autoptr(OstreeRepoFinderConfig) finder = NULL;
|
||||||
|
|
||||||
|
/* Default everything. */
|
||||||
|
finder = ostree_repo_finder_config_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
result_cb (GObject *source_object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GAsyncResult **result_out = user_data;
|
||||||
|
*result_out = g_object_ref (result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test that no remotes are found if there are no config files in the refs
|
||||||
|
* directory. */
|
||||||
|
static void
|
||||||
|
test_repo_finder_config_no_configs (Fixture *fixture,
|
||||||
|
gconstpointer test_data)
|
||||||
|
{
|
||||||
|
g_autoptr(OstreeRepoFinderConfig) finder = NULL;
|
||||||
|
g_autoptr(GMainContext) context = NULL;
|
||||||
|
g_autoptr(GAsyncResult) result = NULL;
|
||||||
|
g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
const OstreeCollectionRef ref1 = { "org.example.Os", "exampleos/x86_64/standard" };
|
||||||
|
const OstreeCollectionRef ref2 = { "org.example.Os", "exampleos/x86_64/buildmaster/standard" };
|
||||||
|
const OstreeCollectionRef * const refs[] = { &ref1, &ref2, NULL };
|
||||||
|
|
||||||
|
context = g_main_context_new ();
|
||||||
|
g_main_context_push_thread_default (context);
|
||||||
|
|
||||||
|
finder = ostree_repo_finder_config_new ();
|
||||||
|
|
||||||
|
ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs,
|
||||||
|
fixture->parent_repo, NULL, result_cb, &result);
|
||||||
|
|
||||||
|
while (result == NULL)
|
||||||
|
g_main_context_iteration (context, TRUE);
|
||||||
|
|
||||||
|
results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder),
|
||||||
|
result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_nonnull (results);
|
||||||
|
g_assert_cmpuint (results->len, ==, 0);
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add configuration for a remote named @remote_name, at @remote_uri, with a
|
||||||
|
* remote collection ID of @collection_id, to the given @repo. */
|
||||||
|
static void
|
||||||
|
assert_create_remote_config (OstreeRepo *repo,
|
||||||
|
const gchar *remote_name,
|
||||||
|
const gchar *remote_uri,
|
||||||
|
const gchar *collection_id)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
g_autoptr(GVariant) options = NULL;
|
||||||
|
|
||||||
|
if (collection_id != NULL)
|
||||||
|
options = g_variant_new_parsed ("@a{sv} { 'collection-id': <%s> }",
|
||||||
|
collection_id);
|
||||||
|
|
||||||
|
ostree_repo_remote_add (repo, remote_name, remote_uri, options, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *assert_create_remote (Fixture *fixture,
|
||||||
|
const gchar *collection_id,
|
||||||
|
...) G_GNUC_NULL_TERMINATED;
|
||||||
|
|
||||||
|
/* Create a new repository in a temporary directory with its collection ID set
|
||||||
|
* to @collection_id, and containing the refs given in @... (which must be
|
||||||
|
* %NULL-terminated). Return the `file://` URI of the new repository. */
|
||||||
|
static gchar *
|
||||||
|
assert_create_remote (Fixture *fixture,
|
||||||
|
const gchar *collection_id,
|
||||||
|
...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
const gchar *repo_name = (collection_id != NULL) ? collection_id : "no-collection";
|
||||||
|
|
||||||
|
glnx_shutil_mkdir_p_at (fixture->working_dfd, repo_name, 0700, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_autoptr(GFile) repo_path = g_file_get_child (fixture->working_dir, repo_name);
|
||||||
|
g_autoptr(OstreeRepo) repo = ostree_repo_new (repo_path);
|
||||||
|
ostree_repo_set_collection_id (repo, collection_id, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
ostree_repo_create (repo, OSTREE_REPO_MODE_ARCHIVE_Z2, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
/* Set up the refs from @.... */
|
||||||
|
va_start (args, collection_id);
|
||||||
|
|
||||||
|
for (const gchar *ref_name = va_arg (args, const gchar *);
|
||||||
|
ref_name != NULL;
|
||||||
|
ref_name = va_arg (args, const gchar *))
|
||||||
|
{
|
||||||
|
OstreeCollectionRef collection_ref = { (gchar *) collection_id, (gchar *) ref_name };
|
||||||
|
g_autofree gchar *checksum = NULL;
|
||||||
|
g_autoptr(OstreeMutableTree) mtree = NULL;
|
||||||
|
g_autoptr(OstreeRepoFile) repo_file = NULL;
|
||||||
|
|
||||||
|
mtree = ostree_mutable_tree_new ();
|
||||||
|
ostree_repo_write_dfd_to_mtree (repo, AT_FDCWD, ".", mtree, NULL, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
ostree_repo_write_mtree (repo, mtree, (GFile **) &repo_file, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
ostree_repo_write_commit (repo, NULL /* no parent */, ref_name, ref_name,
|
||||||
|
NULL /* no metadata */, repo_file, &checksum,
|
||||||
|
NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
if (collection_id != NULL)
|
||||||
|
ostree_repo_set_collection_ref_immediate (repo, &collection_ref, checksum, NULL, &error);
|
||||||
|
else
|
||||||
|
ostree_repo_set_ref_immediate (repo, NULL, ref_name, checksum, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end (args);
|
||||||
|
|
||||||
|
/* Update the summary. */
|
||||||
|
ostree_repo_regenerate_summary (repo, NULL /* no metadata */, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
return g_file_get_uri (repo_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test resolving the refs against a collection of config files, which contain
|
||||||
|
* valid, invalid or duplicate repo information. */
|
||||||
|
static void
|
||||||
|
test_repo_finder_config_mixed_configs (Fixture *fixture,
|
||||||
|
gconstpointer test_data)
|
||||||
|
{
|
||||||
|
g_autoptr(OstreeRepoFinderConfig) finder = NULL;
|
||||||
|
g_autoptr(GMainContext) context = NULL;
|
||||||
|
g_autoptr(GAsyncResult) result = NULL;
|
||||||
|
g_autoptr(GPtrArray) results = NULL; /* (element-type OstreeRepoFinderResult) */
|
||||||
|
g_autoptr(GError) error = NULL;
|
||||||
|
gsize i;
|
||||||
|
const OstreeCollectionRef ref0 = { "org.example.Collection0", "exampleos/x86_64/ref0" };
|
||||||
|
const OstreeCollectionRef ref1 = { "org.example.Collection0", "exampleos/x86_64/ref1" };
|
||||||
|
const OstreeCollectionRef ref2 = { "org.example.Collection1", "exampleos/x86_64/ref1" };
|
||||||
|
const OstreeCollectionRef ref3 = { "org.example.Collection1", "exampleos/x86_64/ref2" };
|
||||||
|
const OstreeCollectionRef ref4 = { "org.example.Collection2", "exampleos/x86_64/ref3" };
|
||||||
|
const OstreeCollectionRef * const refs[] = { &ref0, &ref1, &ref2, &ref3, &ref4, NULL };
|
||||||
|
|
||||||
|
context = g_main_context_new ();
|
||||||
|
g_main_context_push_thread_default (context);
|
||||||
|
|
||||||
|
/* Put together various ref configuration files. */
|
||||||
|
g_autofree gchar *collection0_uri = assert_create_remote (fixture, "org.example.Collection0",
|
||||||
|
"exampleos/x86_64/ref0",
|
||||||
|
"exampleos/x86_64/ref1",
|
||||||
|
NULL);
|
||||||
|
g_autofree gchar *collection1_uri = assert_create_remote (fixture, "org.example.Collection1",
|
||||||
|
"exampleos/x86_64/ref2",
|
||||||
|
NULL);
|
||||||
|
g_autofree gchar *no_collection_uri = assert_create_remote (fixture, NULL,
|
||||||
|
"exampleos/x86_64/ref3",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
assert_create_remote_config (fixture->parent_repo, "remote0", collection0_uri, "org.example.Collection0");
|
||||||
|
assert_create_remote_config (fixture->parent_repo, "remote1", collection1_uri, "org.example.Collection1");
|
||||||
|
assert_create_remote_config (fixture->parent_repo, "remote0-copy", collection0_uri, "org.example.Collection0");
|
||||||
|
assert_create_remote_config (fixture->parent_repo, "remote1-bad-copy", collection1_uri, "org.example.NotCollection1");
|
||||||
|
assert_create_remote_config (fixture->parent_repo, "remote2", no_collection_uri, NULL);
|
||||||
|
|
||||||
|
finder = ostree_repo_finder_config_new ();
|
||||||
|
|
||||||
|
/* Resolve the refs. */
|
||||||
|
ostree_repo_finder_resolve_async (OSTREE_REPO_FINDER (finder), refs,
|
||||||
|
fixture->parent_repo, NULL, result_cb, &result);
|
||||||
|
|
||||||
|
while (result == NULL)
|
||||||
|
g_main_context_iteration (context, TRUE);
|
||||||
|
|
||||||
|
results = ostree_repo_finder_resolve_finish (OSTREE_REPO_FINDER (finder),
|
||||||
|
result, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
g_assert_nonnull (results);
|
||||||
|
g_assert_cmpuint (results->len, ==, 3);
|
||||||
|
|
||||||
|
/* Check that the results are correct: the invalid refs should have been
|
||||||
|
* ignored, and the valid results canonicalised and deduplicated. */
|
||||||
|
for (i = 0; i < results->len; i++)
|
||||||
|
{
|
||||||
|
const OstreeRepoFinderResult *result = g_ptr_array_index (results, i);
|
||||||
|
|
||||||
|
if (g_strcmp0 (ostree_remote_get_name (result->remote), "remote0") == 0 ||
|
||||||
|
g_strcmp0 (ostree_remote_get_name (result->remote), "remote0-copy") == 0)
|
||||||
|
{
|
||||||
|
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 2);
|
||||||
|
g_assert_true (g_hash_table_contains (result->ref_to_checksum, &ref0));
|
||||||
|
g_assert_true (g_hash_table_contains (result->ref_to_checksum, &ref1));
|
||||||
|
}
|
||||||
|
else if (g_strcmp0 (ostree_remote_get_name (result->remote), "remote1") == 0)
|
||||||
|
{
|
||||||
|
g_assert_cmpuint (g_hash_table_size (result->ref_to_checksum), ==, 1);
|
||||||
|
g_assert_true (g_hash_table_contains (result->ref_to_checksum, &ref3));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_assert_not_reached ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_main_context_pop_thread_default (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
setlocale (LC_ALL, "");
|
||||||
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
|
g_test_add_func ("/repo-finder-config/init", test_repo_finder_config_init);
|
||||||
|
g_test_add ("/repo-finder-config/no-configs", Fixture, NULL, setup,
|
||||||
|
test_repo_finder_config_no_configs, teardown);
|
||||||
|
g_test_add ("/repo-finder-config/mixed-configs", Fixture, NULL, setup,
|
||||||
|
test_repo_finder_config_mixed_configs, teardown);
|
||||||
|
|
||||||
|
return g_test_run();
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue