From 4a8c19a2bdc963a574bed5c0789ded36eda337da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 30 Nov 2021 10:28:24 +0000 Subject: osinfo: pull tree matching logic into public API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic for matching an unidentified tree against a reference tree is potentially useful to applications and should be part of a public API, rather than hidden. Signed-off-by: Daniel P. Berrangé --- osinfo/libosinfo.syms | 1 + osinfo/osinfo_db.c | 26 +------------------ osinfo/osinfo_tree.c | 44 ++++++++++++++++++++++++++++++++ osinfo/osinfo_tree.h | 1 + tests/test-tree.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 25 deletions(-) diff --git a/osinfo/libosinfo.syms b/osinfo/libosinfo.syms index 724ea15..a49678c 100644 --- a/osinfo/libosinfo.syms +++ b/osinfo/libosinfo.syms @@ -641,6 +641,7 @@ LIBOSINFO_1.10.0 { osinfo_media_matches; osinfo_os_get_complete_firmware_list; + osinfo_tree_matches; } LIBOSINFO_1.8.0; /* Symbols in next release... diff --git a/osinfo/osinfo_db.c b/osinfo/osinfo_db.c index 4002915..3781712 100644 --- a/osinfo/osinfo_db.c +++ b/osinfo/osinfo_db.c @@ -762,15 +762,6 @@ static gboolean compare_tree(OsinfoTree *tree, GList **fallback_oss) { GList *os_iter; - const gchar *treeinfo_family; - const gchar *treeinfo_variant; - const gchar *treeinfo_version; - const gchar *treeinfo_arch; - - treeinfo_family = osinfo_tree_get_treeinfo_family(tree); - treeinfo_variant = osinfo_tree_get_treeinfo_variant(tree); - treeinfo_version = osinfo_tree_get_treeinfo_version(tree); - treeinfo_arch = osinfo_tree_get_treeinfo_arch(tree); for (os_iter = oss; os_iter; os_iter = os_iter->next) { OsinfoOs *os = OSINFO_OS(os_iter->data); @@ -782,13 +773,6 @@ static gboolean compare_tree(OsinfoTree *tree, for (tree_iter = trees; tree_iter; tree_iter = tree_iter->next) { OsinfoTree *os_tree = OSINFO_TREE(tree_iter->data); const gchar *os_tree_arch = NULL; - const gchar *os_treeinfo_family; - const gchar *os_treeinfo_variant; - const gchar *os_treeinfo_version; - const gchar *os_treeinfo_arch; - - if (!osinfo_tree_has_treeinfo(os_tree)) - continue; os_tree_arch = osinfo_tree_get_architecture(os_tree); if (fallback_oss != NULL) { @@ -798,15 +782,7 @@ static gboolean compare_tree(OsinfoTree *tree, } } - os_treeinfo_family = osinfo_tree_get_treeinfo_family(os_tree); - os_treeinfo_variant = osinfo_tree_get_treeinfo_variant(os_tree); - os_treeinfo_version = osinfo_tree_get_treeinfo_version(os_tree); - os_treeinfo_arch = osinfo_tree_get_treeinfo_arch(os_tree); - - if (match_regex(os_treeinfo_family, treeinfo_family) && - match_regex(os_treeinfo_variant, treeinfo_variant) && - match_regex(os_treeinfo_version, treeinfo_version) && - match_regex(os_treeinfo_arch, treeinfo_arch)) { + if (osinfo_tree_matches(tree, os_tree)) { *ret_os = os; if (matched != NULL) { *matched = os_tree; diff --git a/osinfo/osinfo_tree.c b/osinfo/osinfo_tree.c index fcf71c0..cedeadc 100644 --- a/osinfo/osinfo_tree.c +++ b/osinfo/osinfo_tree.c @@ -1180,3 +1180,47 @@ OsinfoTree *osinfo_tree_create_from_treeinfo(const gchar *treeinfo, return load_keyinfo(location, treeinfo, strlen(treeinfo), error); } + +#define match_regex(pattern, str) \ + (((pattern) == NULL) || \ + (((str) != NULL) && \ + g_regex_match_simple((pattern), (str), 0, 0))) + +/** + * osinfo_tree_matches: + * @tree: an unidentified #OsinfoTree instance + * @reference: a reference #OsinfoTree instance + * + * Determines whether the metadata for the unidentified @tree is a match + * for the @reference tree. + * + * The metadata in the unidentified @tree must be literal strings, + * while the metadata in the @reference tree must be regular expressions. + * + * Returns: #TRUE if @tree is a match for @reference. #FALSE otherwise + * + * Since: 1.10.0 + */ +gboolean osinfo_tree_matches(OsinfoTree *tree, OsinfoTree *reference) +{ + const gchar *tree_treeinfo_family = osinfo_tree_get_treeinfo_family(tree); + const gchar *tree_treeinfo_variant = osinfo_tree_get_treeinfo_variant(tree); + const gchar *tree_treeinfo_version = osinfo_tree_get_treeinfo_version(tree); + const gchar *tree_treeinfo_arch = osinfo_tree_get_treeinfo_arch(tree); + + const gchar *reference_treeinfo_family = osinfo_tree_get_treeinfo_family(reference); + const gchar *reference_treeinfo_variant = osinfo_tree_get_treeinfo_variant(reference); + const gchar *reference_treeinfo_version = osinfo_tree_get_treeinfo_version(reference); + const gchar *reference_treeinfo_arch = osinfo_tree_get_treeinfo_arch(reference); + + if (!osinfo_tree_has_treeinfo(reference)) + return FALSE; + + if (match_regex(reference_treeinfo_family, tree_treeinfo_family) && + match_regex(reference_treeinfo_variant, tree_treeinfo_variant) && + match_regex(reference_treeinfo_version, tree_treeinfo_version) && + match_regex(reference_treeinfo_arch, tree_treeinfo_arch)) + return TRUE; + + return FALSE; +} diff --git a/osinfo/osinfo_tree.h b/osinfo/osinfo_tree.h index 3d96f5a..5671893 100644 --- a/osinfo/osinfo_tree.h +++ b/osinfo/osinfo_tree.h @@ -95,4 +95,5 @@ const gchar *osinfo_tree_get_initrd_path(OsinfoTree *tree); OsinfoOs *osinfo_tree_get_os(OsinfoTree *tree); void osinfo_tree_set_os(OsinfoTree *tree, OsinfoOs *os); OsinfoOsVariantList *osinfo_tree_get_os_variants(OsinfoTree *tree); +gboolean osinfo_tree_matches(OsinfoTree *tree, OsinfoTree *reference); /* XXX Xen kernel/initrd paths ? */ diff --git a/tests/test-tree.c b/tests/test-tree.c index deee819..88adccd 100644 --- a/tests/test-tree.c +++ b/tests/test-tree.c @@ -108,6 +108,75 @@ test_create_from_treeinfo(void) g_object_unref(loader); } +static OsinfoTree * +test_create_tree(const char *id, + const char *arch, + const char *family, + const char *variant, + const char *version, + const char *treearch) +{ + OsinfoTree *tree = osinfo_tree_new(id, arch); + + osinfo_entity_set_param_boolean(OSINFO_ENTITY(tree), + OSINFO_TREE_PROP_HAS_TREEINFO, + TRUE); + + if (family) + osinfo_entity_set_param(OSINFO_ENTITY(tree), + OSINFO_TREE_PROP_TREEINFO_FAMILY, + family); + if (variant) + osinfo_entity_set_param(OSINFO_ENTITY(tree), + OSINFO_TREE_PROP_TREEINFO_VARIANT, + variant); + if (version) + osinfo_entity_set_param(OSINFO_ENTITY(tree), + OSINFO_TREE_PROP_TREEINFO_VERSION, + version); + if (treearch) + osinfo_entity_set_param(OSINFO_ENTITY(tree), + OSINFO_TREE_PROP_TREEINFO_ARCH, + treearch); + + return tree; +} + +static void +test_matching(void) +{ + OsinfoTree *unknown = test_create_tree("https://libosinfo.org/test/", + "x86_64", + "Fedora", + "Server", + "35", + "x86_64"); + /* Match with several optional fields */ + OsinfoTree *reference1 = test_create_tree("https://fedoraproject.org/fedora/35/tree1", + "x86_64", + "Fedora", + NULL, + NULL, + NULL); + /* Mis-match on version */ + OsinfoTree *reference2 = test_create_tree("https://fedoraproject.org/fedora/34/tree2", + "x86_64", + "Fedora", + NULL, + "34", + "x86_64"); + /* Match with all fields with some regexes */ + OsinfoTree *reference3 = test_create_tree("https://fedoraproject.org/fedora/unknown/tree3", + "x86_64", + "Fedora", + "(Server|Workstation)", + "3[0-9]", + NULL); + g_assert(osinfo_tree_matches(unknown, reference1)); + g_assert(!osinfo_tree_matches(unknown, reference2)); + g_assert(osinfo_tree_matches(unknown, reference3)); +} + int main(int argc, char *argv[]) { @@ -116,6 +185,7 @@ main(int argc, char *argv[]) g_test_add_func("/tree/basic", test_basic); g_test_add_func("/tree/os-variants", test_os_variants); g_test_add_func("/tree/create-from-treeinfo", test_create_from_treeinfo); + g_test_add_func("/tree/matching", test_matching); /* Upfront so we don't confuse valgrind */ osinfo_tree_get_type(); -- cgit v1.2.1