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.cute-signatures
parent
ee5ce7284a
commit
693b4bcdb0
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue