From 693b4bcdb0f22904a521a7c8ac4f13e697dc4d71 Mon Sep 17 00:00:00 2001 From: William Pitcock Date: Sat, 27 May 2017 21:49:53 +0000 Subject: version: add support for fuzzy version matching This is useful for requirements such as: python3=~3.6, which would match python3-3.6.[0-9]. This implementation should in theory be backwards compatible with the implementation in Adelie. --- src/add.c | 2 +- src/apk_package.h | 3 ++- src/apk_version.h | 4 +++- src/package.c | 14 ++++++++++---- src/version.c | 12 ++++++++++-- 5 files changed, 26 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/add.c b/src/add.c index 2df4dc8..742df07 100644 --- a/src/add.c +++ b/src/add.c @@ -137,7 +137,7 @@ static int add_main(void *ctx, struct apk_database *db, struct apk_string_array apk_blob_pull_dep(&b, db, &dep); if (APK_BLOB_IS_NULL(b) || b.len > 0) { - apk_error("'%s' is not a valid dependency, format is name(@tag)([<>=]version)", + apk_error("'%s' is not a valid dependency, format is name(@tag)([<>~=]version)", *parg); return -1; } diff --git a/src/apk_package.h b/src/apk_package.h index ab7ab02..c561fc1 100644 --- a/src/apk_package.h +++ b/src/apk_package.h @@ -73,7 +73,8 @@ struct apk_dependency { unsigned broken : 1; unsigned repository_tag : 6; unsigned conflict : 1; - unsigned result_mask : 3; + unsigned result_mask : 4; + unsigned fuzzy : 1; }; APK_ARRAY(apk_dependency_array, struct apk_dependency); diff --git a/src/apk_version.h b/src/apk_version.h index 4275343..47a6b73 100644 --- a/src/apk_version.h +++ b/src/apk_version.h @@ -18,14 +18,16 @@ #define APK_VERSION_EQUAL 1 #define APK_VERSION_LESS 2 #define APK_VERSION_GREATER 4 +#define APK_VERSION_FUZZY 8 #define APK_DEPMASK_ANY (APK_VERSION_EQUAL|APK_VERSION_LESS|\ - APK_VERSION_GREATER) + APK_VERSION_GREATER|APK_VERSION_FUZZY) #define APK_DEPMASK_CHECKSUM (APK_VERSION_LESS|APK_VERSION_GREATER) const char *apk_version_op_string(int result_mask); int apk_version_result_mask(const char *str); int apk_version_validate(apk_blob_t ver); +int apk_version_compare_blob_fuzzy(apk_blob_t a, apk_blob_t b, int fuzzy); int apk_version_compare_blob(apk_blob_t a, apk_blob_t b); int apk_version_compare(const char *str1, const char *str2); diff --git a/src/package.c b/src/package.c index c1d7b77..0bb3747 100644 --- a/src/package.c +++ b/src/package.c @@ -31,6 +31,7 @@ static const apk_spn_match_def apk_spn_dependency_comparer = { [7] = (1<<4) /*<*/ | (1<<5) /*=*/ | (1<<6) /*<*/, + [15] = (1<<6) /*~*/ }; static const apk_spn_match_def apk_spn_dependency_separator = { @@ -190,9 +191,9 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend { struct apk_name *name; apk_blob_t bdep, bname, bop, bver = APK_BLOB_NULL, btag; - int mask = APK_DEPMASK_ANY, conflict = 0, tag = 0; + int mask = APK_DEPMASK_ANY, conflict = 0, tag = 0, fuzzy = 0; - /* [!]name[<,<=,=,>=,>,><]ver */ + /* [!]name[<,<=,<~,=,~,>~,>=,>,><]ver */ if (APK_BLOB_IS_NULL(*b)) goto fail; @@ -231,6 +232,10 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend case '>': mask |= APK_VERSION_GREATER; break; + case '~': + mask |= APK_VERSION_FUZZY|APK_VERSION_EQUAL; + fuzzy = TRUE; + break; case '=': mask |= APK_VERSION_EQUAL; break; @@ -259,6 +264,7 @@ void apk_blob_pull_dep(apk_blob_t *b, struct apk_database *db, struct apk_depend .repository_tag = tag, .result_mask = mask, .conflict = conflict, + .fuzzy = fuzzy, }; return; fail: @@ -320,7 +326,7 @@ int apk_dep_is_provided(struct apk_dependency *dep, struct apk_provider *p) default: if (p->version == &apk_null_blob) return dep->conflict; - if (apk_version_compare_blob(*p->version, *dep->version) + if (apk_version_compare_blob_fuzzy(*p->version, *dep->version, dep->fuzzy) & dep->result_mask) return !dep->conflict; return dep->conflict; @@ -341,7 +347,7 @@ int apk_dep_is_materialized(struct apk_dependency *dep, struct apk_package *pkg) case APK_DEPMASK_ANY: return !dep->conflict; default: - if (apk_version_compare_blob(*pkg->version, *dep->version) + if (apk_version_compare_blob_fuzzy(*pkg->version, *dep->version, dep->fuzzy) & dep->result_mask) return !dep->conflict; return dep->conflict; diff --git a/src/version.c b/src/version.c index eaac762..9bd96cb 100644 --- a/src/version.c +++ b/src/version.c @@ -145,6 +145,9 @@ const char *apk_version_op_string(int mask) return "<"; case APK_VERSION_LESS|APK_VERSION_EQUAL: return "<="; + case APK_VERSION_EQUAL|APK_VERSION_FUZZY: + case APK_VERSION_FUZZY: + return "~"; case APK_VERSION_EQUAL: return "="; case APK_VERSION_GREATER|APK_VERSION_EQUAL: @@ -186,7 +189,7 @@ int apk_version_validate(apk_blob_t ver) return t == TOKEN_END; } -int apk_version_compare_blob(apk_blob_t a, apk_blob_t b) +int apk_version_compare_blob_fuzzy(apk_blob_t a, apk_blob_t b, int fuzzy) { int at = TOKEN_DIGIT, bt = TOKEN_DIGIT, tt; int av = 0, bv = 0; @@ -215,7 +218,7 @@ int apk_version_compare_blob(apk_blob_t a, apk_blob_t b) return APK_VERSION_GREATER; /* both have TOKEN_END or TOKEN_INVALID next? */ - if (at == bt) + if (at == bt || fuzzy) return APK_VERSION_EQUAL; /* if only difference is pkgrev, they are equal. */ @@ -240,6 +243,11 @@ int apk_version_compare_blob(apk_blob_t a, apk_blob_t b) return APK_VERSION_EQUAL; } +int apk_version_compare_blob(apk_blob_t a, apk_blob_t b) +{ + return apk_version_compare_blob_fuzzy(a, b, FALSE); +} + int apk_version_compare(const char *str1, const char *str2) { return apk_version_compare_blob(APK_BLOB_STR(str1), APK_BLOB_STR(str2)); -- cgit v1.2.3