comver 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- comver/__init__.py +33 -0
- comver/__main__.py +13 -0
- comver/_cli.py +38 -0
- comver/_parser.py +132 -0
- comver/_regex/__init__.py +17 -0
- comver/_regex/_process.py +41 -0
- comver/_regex/match.py +83 -0
- comver/_regex/semantic.py +97 -0
- comver/_subcommand.py +174 -0
- comver/_version.py +772 -0
- comver/error.py +82 -0
- comver/plugin.py +241 -0
- comver/py.typed +0 -0
- comver/py.typed.license +4 -0
- comver/type_definitions.py +27 -0
- comver-0.2.0.dist-info/METADATA +329 -0
- comver-0.2.0.dist-info/RECORD +19 -0
- comver-0.2.0.dist-info/WHEEL +4 -0
- comver-0.2.0.dist-info/entry_points.txt +5 -0
comver/__init__.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""comver internal API reference.
|
|
7
|
+
|
|
8
|
+
This section of documentation should be mainly considered by people who:
|
|
9
|
+
|
|
10
|
+
- are curious how the project works under the hood
|
|
11
|
+
- want to provide integration of `comver` with third part tooling.
|
|
12
|
+
|
|
13
|
+
Important:
|
|
14
|
+
Check out guidelines and tutorials for information about CLI/plugin
|
|
15
|
+
as this is a more common starting point.
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from comver import error, plugin, type_definitions
|
|
22
|
+
from comver._version import Version, _version
|
|
23
|
+
|
|
24
|
+
__version__ = _version
|
|
25
|
+
"""Current comver version."""
|
|
26
|
+
|
|
27
|
+
__all__: list[str] = [
|
|
28
|
+
"Version",
|
|
29
|
+
"__version__",
|
|
30
|
+
"error",
|
|
31
|
+
"plugin",
|
|
32
|
+
"type_definitions",
|
|
33
|
+
]
|
comver/__main__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""The `python -m comver` entrypoint."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations # pragma: no cover
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__": # pragma: no cover
|
|
11
|
+
from comver._cli import main
|
|
12
|
+
|
|
13
|
+
main()
|
comver/_cli.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""CLI entrypoint of comver."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
|
|
12
|
+
from comver import _parser, _subcommand
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main(args: list[str] | None = None) -> None:
|
|
16
|
+
"""Command-line entry point of the `comver`.
|
|
17
|
+
|
|
18
|
+
Parses arguments and dispatches execution to the appropriate subcommand
|
|
19
|
+
based on user input. If no arguments are provided explicitly, the arguments
|
|
20
|
+
from `sys.argv[1:]` are used instead.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
args:
|
|
24
|
+
CLI arguments passed, if any (used mainly during testing).
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
parsed_args = _parser.root().parse_args(args)
|
|
28
|
+
subcommand = getattr(_subcommand, parsed_args.subcommand, None)
|
|
29
|
+
|
|
30
|
+
# Cannot be `None`, but left to make pyright feel at peace
|
|
31
|
+
if subcommand is None: # pragma: no cover
|
|
32
|
+
print( # noqa: T201
|
|
33
|
+
"Unknown command chosen",
|
|
34
|
+
file=sys.stderr,
|
|
35
|
+
)
|
|
36
|
+
sys.exit(1)
|
|
37
|
+
|
|
38
|
+
subcommand(parsed_args)
|
comver/_parser.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""Parser of the `comver` CLI."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import textwrap
|
|
12
|
+
|
|
13
|
+
from comver._version import _version
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def root() -> argparse.ArgumentParser:
|
|
17
|
+
"""Create and return the top-level CLI parser.
|
|
18
|
+
|
|
19
|
+
This parser defines all available subcommands and any global flags.
|
|
20
|
+
Each subcommand is parsed with its corresponding arguments and stored
|
|
21
|
+
in the `subcommand` attribute for later dispatching.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
The argument parser configured with all CLI subcommands.
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
parser = argparse.ArgumentParser(
|
|
28
|
+
description="Tool CLI with support for subcommands.",
|
|
29
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
_ = parser.add_argument(
|
|
33
|
+
"--version",
|
|
34
|
+
action="version",
|
|
35
|
+
version=_version,
|
|
36
|
+
help="Show the tool version and exit.",
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
subparsers = parser.add_subparsers(
|
|
40
|
+
dest="subcommand",
|
|
41
|
+
required=True,
|
|
42
|
+
)
|
|
43
|
+
_calculate(subparsers)
|
|
44
|
+
_verify(subparsers)
|
|
45
|
+
|
|
46
|
+
return parser
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _calculate(subparsers) -> None: # noqa: ANN001 # pyright: ignore [reportUnknownParameterType, reportMissingParameterType]
|
|
50
|
+
"""Create `calculate` subcommand subparser.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
subparsers:
|
|
54
|
+
Object where this subparser is registered.
|
|
55
|
+
|
|
56
|
+
"""
|
|
57
|
+
parser = subparsers.add_parser(
|
|
58
|
+
"calculate",
|
|
59
|
+
description=textwrap.dedent("""\
|
|
60
|
+
Calculate semantic version based on commits.
|
|
61
|
+
|
|
62
|
+
NOTE:
|
|
63
|
+
|
|
64
|
+
- This command runs on the git-tree found in current
|
|
65
|
+
working directory.
|
|
66
|
+
- Each value (e.g. version and sha) is space separated
|
|
67
|
+
"""),
|
|
68
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"--format",
|
|
73
|
+
choices=["line", "json"],
|
|
74
|
+
default="line",
|
|
75
|
+
help="Format of the output (default: line, each output space separated)",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
parser.add_argument(
|
|
79
|
+
"--sha",
|
|
80
|
+
action="store_true",
|
|
81
|
+
required=False,
|
|
82
|
+
help=(
|
|
83
|
+
"Return sha of the commit related to the version (usable for verification)"
|
|
84
|
+
),
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
parser.add_argument(
|
|
88
|
+
"--checksum",
|
|
89
|
+
action="store_true",
|
|
90
|
+
required=False,
|
|
91
|
+
help="Return checksum of the configuration (usable for verification)",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _verify(subparsers) -> None: # noqa: ANN001 # pyright: ignore [reportUnknownParameterType, reportMissingParameterType]
|
|
96
|
+
"""Create `verify` subcommand subparser.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
subparsers:
|
|
100
|
+
Object where this subparser is registered.
|
|
101
|
+
|
|
102
|
+
"""
|
|
103
|
+
parser = subparsers.add_parser(
|
|
104
|
+
"verify",
|
|
105
|
+
description=textwrap.dedent("""
|
|
106
|
+
Verify version consistency.
|
|
107
|
+
|
|
108
|
+
NOTE:
|
|
109
|
+
|
|
110
|
+
- This command runs on the git-tree found in current
|
|
111
|
+
working directory.
|
|
112
|
+
- You can feed the output of the `calculate` command here
|
|
113
|
+
"""),
|
|
114
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
parser.add_argument(
|
|
118
|
+
"version",
|
|
119
|
+
help="Version to check (e.g. `1.37.21`).",
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
parser.add_argument(
|
|
123
|
+
"sha",
|
|
124
|
+
help="Sha of the commit to compare against.",
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
parser.add_argument(
|
|
128
|
+
"checksum",
|
|
129
|
+
help="Checksum of the configuration to check against.",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
return parser
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""Regex related internal functionalities."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from comver._regex import match, semantic
|
|
11
|
+
from comver._regex._process import process
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"match",
|
|
15
|
+
"process",
|
|
16
|
+
"semantic",
|
|
17
|
+
]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""Compilation/performance related regex functionalities."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import re
|
|
11
|
+
import typing
|
|
12
|
+
|
|
13
|
+
if typing.TYPE_CHECKING:
|
|
14
|
+
from comver.type_definitions import OptionalStringsOrPatterns
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def process(
|
|
18
|
+
regexes: OptionalStringsOrPatterns, default: str | None = None
|
|
19
|
+
) -> re.Pattern[str] | None:
|
|
20
|
+
"""Cached compilation of multiple regexes.
|
|
21
|
+
|
|
22
|
+
> [!IMPORTANT]
|
|
23
|
+
> `compile` should use internal cache, see
|
|
24
|
+
> here: https://github.com/python/cpython/blob/v3.12.0/Lib/re/__init__.py#L271-L329
|
|
25
|
+
|
|
26
|
+
`None` is used, as the regex matching might be slow
|
|
27
|
+
and is avoided whenever possible throughout
|
|
28
|
+
the whole `comver`.
|
|
29
|
+
|
|
30
|
+
Arguments:
|
|
31
|
+
regexes:
|
|
32
|
+
Regexes which should be compiled together
|
|
33
|
+
(if provided).
|
|
34
|
+
default:
|
|
35
|
+
Default regex, if provided.
|
|
36
|
+
"""
|
|
37
|
+
if not regexes:
|
|
38
|
+
if default is None:
|
|
39
|
+
return None
|
|
40
|
+
return re.compile(default)
|
|
41
|
+
return re.compile(r"(" + r"|".join(rf"({r})" for r in regexes) + r")")
|
comver/_regex/match.py
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 nosludge <https://github.com/nosludge>
|
|
2
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
3
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
|
|
7
|
+
"""Regex matching functions."""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import typing
|
|
12
|
+
|
|
13
|
+
if typing.TYPE_CHECKING:
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
import git
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def item(
|
|
20
|
+
what: str, include: re.Pattern[str] | None, exclude: re.Pattern[str] | None
|
|
21
|
+
) -> bool:
|
|
22
|
+
"""Check if the `what` is included based on the `include` and `exclude`.
|
|
23
|
+
|
|
24
|
+
Note:
|
|
25
|
+
Empty `include` are treated as include-everything.
|
|
26
|
+
|
|
27
|
+
Note:
|
|
28
|
+
Empty `exclude` are treated as include-everything.
|
|
29
|
+
|
|
30
|
+
Warning:
|
|
31
|
+
Exclude regexes take precedence over include regexes.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
what:
|
|
35
|
+
The string to check.
|
|
36
|
+
include:
|
|
37
|
+
The regex to include the string.
|
|
38
|
+
exclude:
|
|
39
|
+
The regex to exclude.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
True if the `what` is included, False otherwise.
|
|
43
|
+
|
|
44
|
+
"""
|
|
45
|
+
return (include is None or include.search(what) is not None) and (
|
|
46
|
+
exclude is None or exclude.search(what) is None
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def path(
|
|
51
|
+
commit: git.Commit,
|
|
52
|
+
include: re.Pattern[str] | None,
|
|
53
|
+
exclude: re.Pattern[str] | None,
|
|
54
|
+
) -> bool:
|
|
55
|
+
"""Check if the commit touched the file based regexes.
|
|
56
|
+
|
|
57
|
+
Note:
|
|
58
|
+
Empty `include` are treated as include-everything.
|
|
59
|
+
|
|
60
|
+
Note:
|
|
61
|
+
Empty `exclude` are treated as include-everything.
|
|
62
|
+
|
|
63
|
+
Warning:
|
|
64
|
+
Exclude regexes take precedence over include regexes.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
commit:
|
|
68
|
+
The commit to check.
|
|
69
|
+
include:
|
|
70
|
+
The regex to include the file.
|
|
71
|
+
exclude:
|
|
72
|
+
The regex to exclude the file.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
True if the commit touched the file, False otherwise.
|
|
76
|
+
"""
|
|
77
|
+
if include is None and exclude is None:
|
|
78
|
+
return True
|
|
79
|
+
|
|
80
|
+
return not commit.diff() or any(
|
|
81
|
+
item(diff.a_path, include, exclude) if diff.a_path else True
|
|
82
|
+
for diff in commit.diff()
|
|
83
|
+
)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 nosludge <https://github.com/nosludge>
|
|
2
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
3
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
6
|
+
|
|
7
|
+
"""Semantic versioning related regexes."""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import re
|
|
12
|
+
import typing
|
|
13
|
+
|
|
14
|
+
from comver._regex._process import process
|
|
15
|
+
|
|
16
|
+
if typing.TYPE_CHECKING:
|
|
17
|
+
from comver.type_definitions import OptionalStringsOrPatterns
|
|
18
|
+
|
|
19
|
+
Key = typing.TypeVar("Key")
|
|
20
|
+
|
|
21
|
+
Semantic = tuple[Key, re.Pattern[str] | None]
|
|
22
|
+
Major = Semantic[typing.Literal["major"]]
|
|
23
|
+
Minor = Semantic[typing.Literal["minor"]]
|
|
24
|
+
Patch = Semantic[typing.Literal["patch"]]
|
|
25
|
+
|
|
26
|
+
StringOrPattern = str | re.Pattern[str]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def components(
|
|
30
|
+
major_regexes: OptionalStringsOrPatterns,
|
|
31
|
+
minor_regexes: OptionalStringsOrPatterns,
|
|
32
|
+
patch_regexes: OptionalStringsOrPatterns,
|
|
33
|
+
) -> tuple[Major, Minor, Patch]:
|
|
34
|
+
"""Grouped semantic versioning regexes.
|
|
35
|
+
|
|
36
|
+
This allows iteration over all necessary components
|
|
37
|
+
with one function.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
major_regexes:
|
|
41
|
+
The regexes finding the `major` version.
|
|
42
|
+
minor_regexes:
|
|
43
|
+
The regexes finding the `minor` version.
|
|
44
|
+
patch_regexes:
|
|
45
|
+
The regexes finding the `patch` version.
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Dictionary mapping element of semantic versioning to the regex.
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
return (
|
|
52
|
+
("major", major(major_regexes)),
|
|
53
|
+
("minor", minor(minor_regexes)),
|
|
54
|
+
("patch", patch(patch_regexes)),
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def major(regexes: OptionalStringsOrPatterns) -> re.Pattern[str] | None:
|
|
59
|
+
"""Return compiled `major` regex.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
regexes:
|
|
63
|
+
Specified `major` version element regexes.
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Compiled regular expression (either default or provided).
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
return process(regexes, r".*BREAKING CHANGE.*|^(feat|fix)(\(.*?\))?!: .*")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def minor(regexes: OptionalStringsOrPatterns) -> re.Pattern[str] | None:
|
|
73
|
+
"""Return compiled `mior` regex.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
regexes:
|
|
77
|
+
Specified `minor` version element regexes.
|
|
78
|
+
|
|
79
|
+
Returns:
|
|
80
|
+
Compiled regular expression (either default or provided).
|
|
81
|
+
|
|
82
|
+
"""
|
|
83
|
+
return process(regexes, "^feat(\\(.*?\\))?: .*")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def patch(regexes: OptionalStringsOrPatterns) -> re.Pattern[str] | None:
|
|
87
|
+
"""Return compiled `patch` regex.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
regexes:
|
|
91
|
+
Specified `patch` version element regexes.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Compiled regular expression (either default or provided).
|
|
95
|
+
|
|
96
|
+
"""
|
|
97
|
+
return process(regexes, "^fix(\\(.*?\\))?: .*")
|
comver/_subcommand.py
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""Subcommands of the CLI `comver`."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import collections
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
import sys
|
|
14
|
+
import typing
|
|
15
|
+
|
|
16
|
+
import loadfig
|
|
17
|
+
|
|
18
|
+
from comver._version import Version, VersionCommit
|
|
19
|
+
|
|
20
|
+
if typing.TYPE_CHECKING:
|
|
21
|
+
import argparse
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def calculate(args: argparse.Namespace) -> typing.NoReturn:
|
|
25
|
+
"""Calculate semantic versioning based on commit messages.
|
|
26
|
+
|
|
27
|
+
Outputs version and (optionally) sha of a commit
|
|
28
|
+
related to this version (the last one in commit chain).
|
|
29
|
+
|
|
30
|
+
This output allows to later compare git trees and inferred
|
|
31
|
+
versions if necessary.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
args:
|
|
35
|
+
Arguments from the CLI.
|
|
36
|
+
|
|
37
|
+
"""
|
|
38
|
+
print(_calculate(args)) # noqa: T201
|
|
39
|
+
sys.exit(0)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def verify(args: argparse.Namespace) -> typing.NoReturn:
|
|
43
|
+
"""Verify commit sha and inferred version match.
|
|
44
|
+
|
|
45
|
+
Given `version` (as string, e.g. `1.2.3`) and
|
|
46
|
+
commit sha verify whether this version was created
|
|
47
|
+
from this commit chain.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
args:
|
|
51
|
+
Arguments from the CLI.
|
|
52
|
+
|
|
53
|
+
"""
|
|
54
|
+
sys.exit(_verify(args))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _calculate(args: argparse.Namespace) -> str: # noqa: C901
|
|
58
|
+
"""Implementation of calculate cli command.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
args:
|
|
62
|
+
Arguments from the CLI.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Either formatted dictionary (if `args.json`) string
|
|
66
|
+
or space separated "version sha". `sha` component
|
|
67
|
+
is optional based on `args.sha` flag.
|
|
68
|
+
|
|
69
|
+
"""
|
|
70
|
+
version = VersionCommit()
|
|
71
|
+
for version in Version.from_git_configured(): # noqa: B007
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
sha = version.commit.hexsha if version.commit is not None else None
|
|
75
|
+
checksum = _checksum_config()
|
|
76
|
+
|
|
77
|
+
version = str(version.version)
|
|
78
|
+
|
|
79
|
+
if args.format == "line":
|
|
80
|
+
if args.sha:
|
|
81
|
+
version = f"{version} {sha}"
|
|
82
|
+
if args.checksum:
|
|
83
|
+
version = f"{version} {checksum}"
|
|
84
|
+
return version
|
|
85
|
+
|
|
86
|
+
output = {"version": str(version)}
|
|
87
|
+
if args.sha and isinstance(sha, str):
|
|
88
|
+
output["sha"] = sha
|
|
89
|
+
if args.checksum:
|
|
90
|
+
output["checksum"] = checksum
|
|
91
|
+
|
|
92
|
+
return json.dumps(output, indent=4)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _verify(args: argparse.Namespace) -> bool:
|
|
96
|
+
"""Verify commit sha and inferred version match.
|
|
97
|
+
|
|
98
|
+
Warning:
|
|
99
|
+
This subcommand also outputs messages for the end user
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
args:
|
|
103
|
+
Arguments from the CLI.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
Code status of the command (`True` for error, `False`
|
|
107
|
+
on successful verification).
|
|
108
|
+
|
|
109
|
+
"""
|
|
110
|
+
checksum = _checksum_config()
|
|
111
|
+
|
|
112
|
+
if args.checksum != checksum:
|
|
113
|
+
print( # noqa: T201
|
|
114
|
+
"Provided checksum and the checksum of configuration do not match.",
|
|
115
|
+
file=sys.stderr,
|
|
116
|
+
)
|
|
117
|
+
return True
|
|
118
|
+
|
|
119
|
+
for output in Version.from_git_configured():
|
|
120
|
+
version, commit = output.version, output.commit
|
|
121
|
+
|
|
122
|
+
sha = commit.hexsha if commit is not None else None
|
|
123
|
+
|
|
124
|
+
if args.version == version:
|
|
125
|
+
if sha is not None and sha == args.sha:
|
|
126
|
+
return False
|
|
127
|
+
|
|
128
|
+
print( # noqa: T201
|
|
129
|
+
f"Specified version: `{args.version}` has sha: `{sha}`, while expected sha is: `{args.sha}`",
|
|
130
|
+
file=sys.stderr,
|
|
131
|
+
) # pragma: no cover
|
|
132
|
+
return True # pragma: no cover
|
|
133
|
+
|
|
134
|
+
if args.sha == sha:
|
|
135
|
+
print( # noqa: T201
|
|
136
|
+
f"Specified sha: `{args.sha}` corresponds to version: `{version}`, while expected version is: `{args.version}`", # noqa: E501
|
|
137
|
+
file=sys.stderr,
|
|
138
|
+
)
|
|
139
|
+
return True
|
|
140
|
+
|
|
141
|
+
print( # noqa: T201
|
|
142
|
+
f"Neither specified sha: `{args.sha}` nor its corresponding version: `{args.version}` was found in the git tree", # noqa: E501
|
|
143
|
+
file=sys.stderr,
|
|
144
|
+
)
|
|
145
|
+
return True
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _checksum_config() -> str:
|
|
149
|
+
"""Get checksum of config.
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
Checksum of subconfig.
|
|
153
|
+
|
|
154
|
+
"""
|
|
155
|
+
config = collections.defaultdict(lambda: None, loadfig.config("comver"))
|
|
156
|
+
keys = [
|
|
157
|
+
"message_includes",
|
|
158
|
+
"message_excludes",
|
|
159
|
+
"path_includes",
|
|
160
|
+
"path_excludes",
|
|
161
|
+
"author_name_includes",
|
|
162
|
+
"author_name_excludes",
|
|
163
|
+
"author_email_includes",
|
|
164
|
+
"author_email_excludes",
|
|
165
|
+
"major_regexes",
|
|
166
|
+
"minor_regexes",
|
|
167
|
+
"patch_regexes",
|
|
168
|
+
"unrecognized_message",
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
# Get only relevant sections of the dict
|
|
172
|
+
subconfig = {k: config[k] for k in keys}
|
|
173
|
+
stringified = json.dumps(subconfig, sort_keys=True)
|
|
174
|
+
return hashlib.sha256(stringified.encode()).hexdigest()
|