-
-
Notifications
You must be signed in to change notification settings - Fork 328
Expand file tree
/
Copy pathbump.py
More file actions
141 lines (109 loc) · 4.58 KB
/
bump.py
File metadata and controls
141 lines (109 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from __future__ import annotations
import os
import re
from collections import OrderedDict
from glob import iglob
from logging import getLogger
from string import Template
from typing import TYPE_CHECKING, cast
from commitizen.defaults import BUMP_MESSAGE, MAJOR, MINOR, PATCH
from commitizen.exceptions import CurrentVersionNotFoundError
from commitizen.git import GitCommit, smart_open
if TYPE_CHECKING:
from collections.abc import Generator, Iterable
from commitizen.version_schemes import Increment, Version
VERSION_TYPES = [None, PATCH, MINOR, MAJOR]
logger = getLogger("commitizen")
def find_increment(
commits: list[GitCommit], regex: str, increments_map: dict | OrderedDict
) -> Increment | None:
if isinstance(increments_map, dict):
increments_map = OrderedDict(increments_map)
# Most important cases are major and minor.
# Everything else will be considered patch.
select_pattern = re.compile(regex)
increment: str | None = None
for commit in commits:
for message in commit.message.split("\n"):
result = select_pattern.search(message)
if result:
found_keyword = result.group(1)
new_increment = None
for match_pattern in increments_map.keys():
if re.match(match_pattern, found_keyword):
new_increment = increments_map[match_pattern]
break
if new_increment is None:
logger.debug(
f"no increment needed for '{found_keyword}' in '{message}'"
)
if VERSION_TYPES.index(increment) < VERSION_TYPES.index(new_increment):
logger.debug(
f"increment detected is '{new_increment}' due to '{found_keyword}' in '{message}'"
)
increment = new_increment
if increment == MAJOR:
break
return cast("Increment", increment)
def update_version_in_files(
current_version: str,
new_version: str,
version_files: Iterable[str],
*,
check_consistency: bool,
encoding: str,
) -> list[str]:
"""Change old version to the new one in every file given.
Note that this version is not the tag formatted one.
So for example, your tag could look like `v1.0.0` while your version in
the package like `1.0.0`.
Returns the list of updated files.
"""
updated_files = []
for path, pattern in _resolve_files_and_regexes(version_files, current_version):
current_version_found = False
bumped_lines = []
with open(path, encoding=encoding) as version_file:
for line in version_file:
bumped_line = (
line.replace(current_version, new_version)
if pattern.search(line)
else line
)
current_version_found = current_version_found or bumped_line != line
bumped_lines.append(bumped_line)
if check_consistency and not current_version_found:
raise CurrentVersionNotFoundError(
f"Current version {current_version} is not found in {path}.\n"
"The version defined in commitizen configuration and the ones in "
"version_files are possibly inconsistent."
)
bumped_version_file_content = "".join(bumped_lines)
# Write the file out again
with smart_open(path, "w", encoding=encoding) as file:
file.write(bumped_version_file_content)
updated_files.append(path)
return updated_files
def _resolve_files_and_regexes(
patterns: Iterable[str], version: str
) -> Generator[tuple[str, re.Pattern], None, None]:
"""
Resolve all distinct files with their regexp from a list of glob patterns with optional regexp
"""
filepath_set: set[tuple[str, str]] = set()
for pattern in patterns:
drive, tail = os.path.splitdrive(pattern)
path, _, regex = tail.partition(":")
filepath = drive + path
regex = regex or re.escape(version)
filepath_set.update((path, regex) for path in iglob(filepath))
return ((path, re.compile(regex)) for path, regex in sorted(filepath_set))
def create_commit_message(
current_version: Version | str,
new_version: Version | str,
message_template: str | None = None,
) -> str:
if message_template is None:
message_template = BUMP_MESSAGE
t = Template(message_template)
return t.safe_substitute(current_version=current_version, new_version=new_version)