Skip to content

Commit 0684925

Browse files
committed
Moved reusable version functions into utils
Signed-off-by: Ole Herman Schumacher Elgesem <ole@northern.tech>
1 parent 5c2680b commit 0684925

File tree

7 files changed

+120
-110
lines changed

7 files changed

+120
-110
lines changed

cfbs/analyze.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,19 @@
44
import copy
55

66
from cfbs.internal_file_management import fetch_archive
7-
from cfbs.masterfiles.analyze import (
8-
highest_version,
9-
sort_versions,
10-
version_as_comparable_list,
11-
)
127
from cfbs.utils import (
138
CFBSNetworkError,
149
cfbs_dir,
1510
deduplicate_list,
1611
fetch_url,
1712
file_sha256,
1813
get_json,
14+
highest_version,
1915
immediate_subdirectories,
2016
mkdir,
2117
read_json,
18+
sort_versions,
19+
version_as_comparable_list,
2220
CFBSExitError,
2321
)
2422

cfbs/commands.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ def search_command(terms: List[str]):
5959

6060
from cfbs.cfbs_json import CFBSJson
6161
from cfbs.cfbs_types import CFBSCommandExitCode, CFBSCommandGitResult
62-
from cfbs.masterfiles.analyze import most_relevant_version
6362
from cfbs.masterfiles.download import download_single_version
6463
from cfbs.updates import ModuleUpdates, update_module
6564
from cfbs.utils import (
@@ -72,6 +71,7 @@ def search_command(terms: List[str]):
7271
file_diff_text,
7372
is_cfbs_repo,
7473
mkdir,
74+
most_relevant_version,
7575
read_json,
7676
CFBSExitError,
7777
save_file,

cfbs/masterfiles/analyze.py

Lines changed: 1 addition & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
from collections import OrderedDict
22
import os
3-
from typing import Iterable, List
43

5-
from cfbs.utils import dict_sorted_by_key, file_sha256
4+
from cfbs.utils import dict_sorted_by_key, file_sha256, version_as_comparable_list
65

76
Version = str
87

@@ -92,99 +91,3 @@ def finalize_vcf(versions_dict, checksums_dict, files_dict):
9291
)
9392

9493
return versions_dict, checksums_dict, files_dict
95-
96-
97-
def version_as_comparable_list(version: str):
98-
"""Also supports versions containing exactly one of `b` or `-`.
99-
100-
Example of the version ordering: `3.24.0b1 < 3.24.0 < 3.24.0-1`.
101-
102-
Examples:
103-
* `version_as_comparable_list("3.24.0b1")` is `[[3, 24, 0], [-1, 1]]`
104-
* `version_as_comparable_list("3.24.0-2")` is `[[3, 24, 0], [1, 2]]`
105-
* `version_as_comparable_list("3.24.x")` is `[[3, 24, 99999], [0, 0]]`"""
106-
if version == "master":
107-
version = "x"
108-
109-
if "b" not in version:
110-
if "-" not in version:
111-
version += "|0.0"
112-
version = version.replace("x", "99999").replace("-", "|1.").replace("b", "|-1.")
113-
versionpair = version.split("|")
114-
versions_str = [versionpair[0].split("."), versionpair[1].split(".")]
115-
116-
versions_int = [
117-
[int(s) for s in versions_str[0]],
118-
[int(s) for s in versions_str[1]],
119-
]
120-
121-
return versions_int
122-
123-
124-
def version_as_comparable_list_negated(version):
125-
vcl = version_as_comparable_list(version)
126-
127-
vcl[0] = [-x for x in vcl[0]]
128-
vcl[1] = [-x for x in vcl[1]]
129-
130-
return vcl
131-
132-
133-
def version_is_at_least(version, min_version):
134-
return min_version is None or (
135-
version_as_comparable_list(version) >= version_as_comparable_list(min_version)
136-
)
137-
138-
139-
def sort_versions(versions: list, reverse: bool = True):
140-
"""Sorts a list of versions, in descending order by default."""
141-
versions.sort(
142-
key=version_as_comparable_list,
143-
reverse=reverse,
144-
)
145-
146-
147-
def highest_version(versions: Iterable[Version]):
148-
return max(versions, key=version_as_comparable_list, default=None)
149-
150-
151-
def lowest_version(versions: Iterable[Version]):
152-
return min(versions, key=version_as_comparable_list, default=None)
153-
154-
155-
def is_lower_version(version_a: Version, version_b: Version):
156-
"""Returns `True` if and only if `version_a` is lower than `version_b`."""
157-
158-
return version_as_comparable_list(version_a) < version_as_comparable_list(version_b)
159-
160-
161-
def most_relevant_version(
162-
other_versions: List[Version], reference_version: Version
163-
) -> Version:
164-
"""
165-
The most relevant version is the highest version among older other versions,
166-
or if there are no older other versions, the lowest version among other versions.
167-
168-
`other_versions` is assumed to be non-empty and not contain `reference_version`."""
169-
assert len(other_versions) > 0
170-
assert reference_version not in other_versions
171-
172-
highest_other_version = highest_version(other_versions)
173-
lowest_other_version = lowest_version(other_versions)
174-
# Unfortunately, Pyright can not infer that these can't be `None` when `other_versions` is non-empty.
175-
assert highest_other_version is not None
176-
assert lowest_other_version is not None
177-
178-
if is_lower_version(highest_other_version, reference_version):
179-
# all other versions are older
180-
return highest_other_version
181-
if is_lower_version(reference_version, lowest_other_version):
182-
# all other versions are newer
183-
return lowest_other_version
184-
# there are both older and newer versions
185-
lower_other_versions = [
186-
o_v for o_v in other_versions if is_lower_version(o_v, reference_version)
187-
]
188-
highest_lower = highest_version(lower_other_versions)
189-
assert highest_lower is not None
190-
return highest_lower

cfbs/masterfiles/check_download_matches_git.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
import os
22
from collections import OrderedDict
33

4-
from cfbs.masterfiles.analyze import version_as_comparable_list
5-
from cfbs.utils import dict_diff, read_json, CFBSExitError, write_json
4+
from cfbs.utils import (
5+
dict_diff,
6+
read_json,
7+
CFBSExitError,
8+
write_json,
9+
version_as_comparable_list,
10+
)
611

712

813
def check_download_matches_git(versions):

cfbs/masterfiles/download.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
import os
22
import shutil
33

4-
from cfbs.masterfiles.analyze import version_is_at_least
5-
from cfbs.utils import CFBSNetworkError, fetch_url, get_json, mkdir, CFBSExitError
4+
from cfbs.utils import (
5+
CFBSNetworkError,
6+
fetch_url,
7+
get_json,
8+
mkdir,
9+
CFBSExitError,
10+
version_is_at_least,
11+
)
612

713
ENTERPRISE_RELEASES_URL = "https://cfengine.com/release-data/enterprise/releases.json"
814

cfbs/masterfiles/generate_release_information.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
from cfbs.masterfiles.analyze import version_is_at_least
21
from cfbs.masterfiles.download import download_all_versions
32
from cfbs.masterfiles.generate_vcf_download import generate_vcf_download
43
from cfbs.masterfiles.generate_vcf_git_checkout import generate_vcf_git_checkout
54
from cfbs.masterfiles.check_download_matches_git import check_download_matches_git
6-
from cfbs.utils import immediate_subdirectories
5+
from cfbs.utils import immediate_subdirectories, version_is_at_least
76

87
DOWNLOAD_PATH = "downloaded_masterfiles"
98

cfbs/utils.py

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,3 +601,102 @@ def loads_bundlenames(policy: str):
601601

602602
regex = r"(?<=^bundle agent )[a-zA-Z0-9_\200-\377]+"
603603
return re.findall(regex, policy, re.MULTILINE)
604+
605+
606+
Version = str
607+
608+
609+
def version_as_comparable_list(version: str):
610+
"""Also supports versions containing exactly one of `b` or `-`.
611+
612+
Example of the version ordering: `3.24.0b1 < 3.24.0 < 3.24.0-1`.
613+
614+
Examples:
615+
* `version_as_comparable_list("3.24.0b1")` is `[[3, 24, 0], [-1, 1]]`
616+
* `version_as_comparable_list("3.24.0-2")` is `[[3, 24, 0], [1, 2]]`
617+
* `version_as_comparable_list("3.24.x")` is `[[3, 24, 99999], [0, 0]]`"""
618+
if version == "master":
619+
version = "x"
620+
621+
if "b" not in version:
622+
if "-" not in version:
623+
version += "|0.0"
624+
version = version.replace("x", "99999").replace("-", "|1.").replace("b", "|-1.")
625+
versionpair = version.split("|")
626+
versions_str = [versionpair[0].split("."), versionpair[1].split(".")]
627+
628+
versions_int = [
629+
[int(s) for s in versions_str[0]],
630+
[int(s) for s in versions_str[1]],
631+
]
632+
633+
return versions_int
634+
635+
636+
def version_as_comparable_list_negated(version):
637+
vcl = version_as_comparable_list(version)
638+
639+
vcl[0] = [-x for x in vcl[0]]
640+
vcl[1] = [-x for x in vcl[1]]
641+
642+
return vcl
643+
644+
645+
def version_is_at_least(version, min_version):
646+
return min_version is None or (
647+
version_as_comparable_list(version) >= version_as_comparable_list(min_version)
648+
)
649+
650+
651+
def sort_versions(versions: list, reverse: bool = True):
652+
"""Sorts a list of versions, in descending order by default."""
653+
versions.sort(
654+
key=version_as_comparable_list,
655+
reverse=reverse,
656+
)
657+
658+
659+
def highest_version(versions: Iterable[Version]):
660+
return max(versions, key=version_as_comparable_list, default=None)
661+
662+
663+
def lowest_version(versions: Iterable[Version]):
664+
return min(versions, key=version_as_comparable_list, default=None)
665+
666+
667+
def is_lower_version(version_a: Version, version_b: Version):
668+
"""Returns `True` if and only if `version_a` is lower than `version_b`."""
669+
670+
return version_as_comparable_list(version_a) < version_as_comparable_list(version_b)
671+
672+
673+
def most_relevant_version(
674+
other_versions: List[Version], reference_version: Version
675+
) -> Version:
676+
"""
677+
The most relevant version is the highest version among older other versions,
678+
or if there are no older other versions, the lowest version among other versions.
679+
680+
`other_versions` is assumed to be non-empty and not contain `reference_version`."""
681+
assert len(other_versions) > 0
682+
assert reference_version not in other_versions
683+
684+
highest_other_version = highest_version(other_versions)
685+
lowest_other_version = lowest_version(other_versions)
686+
# Unfortunately, Pyright can not infer that these can't be `None` when `other_versions` is non-empty.
687+
assert highest_other_version is not None
688+
assert lowest_other_version is not None
689+
690+
if is_lower_version(highest_other_version, reference_version):
691+
# all other versions are older
692+
return highest_other_version
693+
if is_lower_version(reference_version, lowest_other_version):
694+
# all other versions are newer
695+
return lowest_other_version
696+
# there are both older and newer versions
697+
lower_other_versions = [
698+
o_v for o_v in other_versions if is_lower_version(o_v, reference_version)
699+
]
700+
highest_lower = highest_version(lower_other_versions)
701+
assert highest_lower is not None
702+
return highest_lower

0 commit comments

Comments
 (0)