diff --git a/.gitignore b/.gitignore index 415d750d9..7e5eaebeb 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ misc/po/*.mo server/doc/man/*.1 #*# lib/*test*.py +.idea +venv diff --git a/lib/entropy/dep.py b/lib/entropy/dep.py index 7ed88e711..fbbe1108e 100644 --- a/lib/entropy/dep.py +++ b/lib/entropy/dep.py @@ -43,6 +43,9 @@ endversion_keys = ["pre", "p", "alpha", "beta", "rc"] valid_category = re.compile("^\w[\w-]*") invalid_atom_chars_regexp = re.compile("[()|@]") +digits_group = re.compile('([0-9]+)') + + def _ververify(myver): if myver.endswith("*"): m = ver_regexp.match(myver[:-1]) @@ -632,6 +635,20 @@ def is_valid_package_tag(tag): return False return True +def _nat_sort_key(key): + """ + Key generator for natural sorting algorithms. + + @param key: Entropy package tag + return: array obtained from the input string with strings parsed as + strings and numbers parsed as number with the empty string as + first and last element. + """ + if key is None: + key = '' + return [int(c) if c.isdigit() else c.lower() + for c in re.split(digits_group, key.strip())] + def entropy_compare_package_tags(tag_a, tag_b): """ Compare two Entropy package tags using builtin cmp(). @@ -644,7 +661,7 @@ def entropy_compare_package_tags(tag_a, tag_b): zero if tag_a == tag_b. rtype: int """ - return const_cmp(tag_a, tag_b) + return const_cmp(_nat_sort_key(tag_a), _nat_sort_key(tag_b)) def sort_entropy_package_tags(tags): """ @@ -655,7 +672,7 @@ def sort_entropy_package_tags(tags): @return: sorted list of Entropy package tags @rtype: list """ - return sorted(tags) + return sorted(tags, key=_nat_sort_key) def entropy_compare_versions(ver_data, ver_data2): """ @@ -673,7 +690,7 @@ def entropy_compare_versions(ver_data, ver_data2): # if both are tagged, check tag first rc = 0 if a_tag and b_tag: - rc = const_cmp(a_tag, b_tag) + rc = entropy_compare_package_tags(a_tag, b_tag) if rc == 0: rc = compare_versions(a_ver, b_ver) @@ -1173,8 +1190,8 @@ def expand_dependencies(dependencies, entropy_repository_list, @param dependencies: list of raw package dependencies, as returned by EntropyRepositoryBase.retrieveDependencies{,List}() @type dependencies: iterable - @param entropy_repository_list: ordered list of EntropyRepositoryBase instances - used to execute the actual resolution + @param entropy_repository_list: ordered list of EntropyRepositoryBase + instances used to execute the actual resolution @type entropy_repository_list: list @keyword selected_matches: list of preferred package matches used to evaluate or-dependencies. diff --git a/lib/tests/dep.py b/lib/tests/dep.py index 7d6cd5f50..bae8e12e1 100644 --- a/lib/tests/dep.py +++ b/lib/tests/dep.py @@ -115,22 +115,54 @@ class DepTest(unittest.TestCase): ver_a = ("1.0.0", "1.0.0", 0,) ver_b = ("1.0.1", "1.0.0", 0.10000000000000001,) ver_c = ("1.0.0", "1.0.1", -0.10000000000000001,) + ver_d = ("4.9.44", "4.11.12", -2,) self.assertEqual(et.compare_versions(ver_a[0], ver_a[1]), ver_a[2]) self.assertEqual(et.compare_versions(ver_b[0], ver_b[1]), ver_b[2]) self.assertEqual(et.compare_versions(ver_c[0], ver_c[1]), ver_c[2]) + self.assertEqual(et.compare_versions(ver_d[0], ver_d[1]), ver_d[2]) def test_get_newer_version(self): - vers = ["1.0", "3.4", "0.5", "999", "9999", "10.0"] - out_vers = ['9999', '999', '10.0', '3.4', '1.0', '0.5'] + vers = ["1.0", "3.4", "0.5", "999", "9999", "10.0", "10.11.12", "10.1.32", "10.9.44"] + out_vers = ['9999', '999', '10.11.12', '10.9.44', '10.1.32', '10.0', '3.4', '1.0', '0.5'] self.assertEqual(et.get_newer_version(vers), out_vers) + def test_compare_tag_versions(self): + tag_ver_a = ("4.11.0-sabayon", "4.11.0-sabayon", 0,) + tag_ver_b = ("4.4.0-sabayon", "4.9.0-sabayon", -1,) + tag_ver_c = ("4.11.0-sabayon", "4.1.0-sabayon", 1,) + tag_ver_d = ("4.9.44", "3.11.12", 1,) + tag_ver_e = ("2.11.59", "4.12.0", -1,) + tag_ver_f = ("2222", "2223", -1,) + + self.assertEqual(et.entropy_compare_package_tags(tag_ver_a[0], tag_ver_a[1]), tag_ver_a[2]) + self.assertEqual(et.entropy_compare_package_tags(tag_ver_b[0], tag_ver_b[1]), tag_ver_b[2]) + self.assertEqual(et.entropy_compare_package_tags(tag_ver_c[0], tag_ver_c[1]), tag_ver_c[2]) + self.assertEqual(et.entropy_compare_package_tags(tag_ver_d[0], tag_ver_d[1]), tag_ver_d[2]) + self.assertEqual(et.entropy_compare_package_tags(tag_ver_e[0], tag_ver_e[1]), tag_ver_e[2]) + self.assertEqual(et.entropy_compare_package_tags(tag_ver_f[0], tag_ver_f[1]), tag_ver_f[2]) + def test_get_entropy_newer_version(self): vers = [("1.0", "2222", 1,), ("3.4", "2222", 0,), ("1.0", "2223", 1,), ("1.0", "2223", 3,)] out_vers = [('1.0', '2223', 3), ('1.0', '2223', 1), ('3.4', '2222', 0), ('1.0', '2222', 1)] + vers2 = [("340.102", "3.18.0-sabayon", 1,), + ("340.102", "4.11.0-sabayon", 5,), + ("340.102", "4.1.0-sabayon", 3,), + ("381.09", "4.11.0-sabayon", 0,), + ("381.09", "4.11.0-sabayon", 8,), + ("381.09", "3.18.0-sabayon", 0,), + ("381.09", "4.1.0-sabayon", 0,),] + out_vers2 = [("381.09", "4.11.0-sabayon", 8,), + ("381.09", "4.11.0-sabayon", 0,), + ("340.102", "4.11.0-sabayon", 5,), + ("381.09", "4.1.0-sabayon", 0,), + ("340.102", "4.1.0-sabayon", 3,), + ("381.09", "3.18.0-sabayon", 0,), + ("340.102", "3.18.0-sabayon", 1,),] self.assertEqual(et.get_entropy_newer_version(vers), out_vers) + self.assertEqual(et.get_entropy_newer_version(vers2), out_vers2) def test_create_package_filename(self): package_category = "app-foo"