aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Pitcock <nenolod@dereferenced.org>2017-05-27 21:49:53 +0000
committerWilliam Pitcock <nenolod@dereferenced.org>2017-05-27 21:49:53 +0000
commit693b4bcdb0f22904a521a7c8ac4f13e697dc4d71 (patch)
treea4cdf39e5c4ad6169bf3a3a261d1c833298238f5
parentee5ce7284aef8679fabcf728dd5bd5a17c965798 (diff)
downloadaports-693b4bcdb0f22904a521a7c8ac4f13e697dc4d71.tar.bz2
aports-693b4bcdb0f22904a521a7c8ac4f13e697dc4d71.tar.xz
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.
-rw-r--r--src/add.c2
-rw-r--r--src/apk_package.h3
-rw-r--r--src/apk_version.h4
-rw-r--r--src/package.c14
-rw-r--r--src/version.c12
5 files changed, 26 insertions, 9 deletions
diff --git a/src/add.c b/src/add.c
index 2df4dc8431..742df07b78 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 ab7ab021e7..c561fc15be 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 42753434fb..47a6b7325c 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 c1d7b775d9..0bb37473c5 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 eaac762cb9..9bd96cb338 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));