Skip to content

Commit b088993

Browse files
fix(bump): flag sibling version mismatches under --check-consistency
When `version_files` regex matches multiple version-shaped values in the same file (the typical pyproject.toml pattern with both `[tool.poetry].version` / `[project].version` and `[tool.commitizen].version`), the previous behaviour silently rewrote only the line containing the current version and left the sibling out-of-sync. Under `--check-consistency`, also fail when a matching line holds a different version-shaped value. The error names the offending line so users can either align the sources, narrow the `version_files` regex or drop `--check-consistency`. The default (`check_consistency = False`) is unchanged: only lines containing `current_version` are rewritten, others are passed through. Closes #595 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4d99415 commit b088993

2 files changed

Lines changed: 90 additions & 8 deletions

File tree

commitizen/bump.py

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,27 @@ def update_version_in_files(
8282

8383
for path, pattern in _resolve_files_and_regexes(version_files, current_version):
8484
current_version_found = False
85+
inconsistent_lines: list[tuple[int, str]] = []
8586
bumped_lines = []
8687

8788
with open(path, encoding=encoding) as version_file:
88-
for line in version_file:
89-
bumped_line = (
90-
line.replace(current_version, new_version)
91-
if pattern.search(line)
92-
else line
93-
)
94-
95-
current_version_found = current_version_found or bumped_line != line
89+
for lineno, line in enumerate(version_file, 1):
90+
if pattern.search(line):
91+
if current_version in line:
92+
bumped_line = line.replace(current_version, new_version)
93+
current_version_found = True
94+
else:
95+
# The version-files regex matched this line, but the
96+
# current version isn't on it. If the line looks like
97+
# it sets a version-shaped value, this is almost
98+
# certainly an inconsistent source we'd otherwise miss
99+
# silently (#595).
100+
bumped_line = line
101+
if _LIKELY_VERSION_VALUE_RE.search(line):
102+
inconsistent_lines.append((lineno, line.rstrip()))
103+
else:
104+
bumped_line = line
105+
96106
bumped_lines.append(bumped_line)
97107

98108
if check_consistency and not current_version_found:
@@ -102,6 +112,17 @@ def update_version_in_files(
102112
"version_files are possibly inconsistent."
103113
)
104114

115+
if check_consistency and inconsistent_lines:
116+
details = "\n".join(f" line {n}: {text}" for n, text in inconsistent_lines)
117+
raise CurrentVersionNotFoundError(
118+
f"Found line(s) in {path} matching the version regex but "
119+
f"holding a version other than {current_version}:\n"
120+
f"{details}\n"
121+
"This usually means another tool (e.g. poetry, pep621) is "
122+
"tracking a different version. Either align them, narrow the "
123+
"`version_files` regex, or drop `--check-consistency`."
124+
)
125+
105126
bumped_version_file_content = "".join(bumped_lines)
106127

107128
# Write the file out again
@@ -112,6 +133,12 @@ def update_version_in_files(
112133
return updated_files
113134

114135

136+
# Lines that look like ``key = "1.2.3"`` / ``key: 1.2.3-rc.0`` etc. -- enough
137+
# to catch the typical pyproject.toml ``[tool.poetry].version = "..."`` and
138+
# ``[project].version = "..."`` cases handled by ``--check-consistency``.
139+
_LIKELY_VERSION_VALUE_RE = re.compile(r"\d+\.\d+\.\d+(?:[\w.\-+]*)")
140+
141+
115142
def _resolve_files_and_regexes(
116143
patterns: Iterable[str], version: str
117144
) -> Generator[tuple[str, re.Pattern], None, None]:

tests/test_bump_update_version_in_files.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,61 @@ def test_update_version_in_files_with_check_consistency_true_failure(
302302
assert expected_msg in str(excinfo.value)
303303

304304

305+
def test_update_version_in_files_check_consistency_detects_sibling_version(tmp_path):
306+
"""Regression test for #595: when a single file's version regex matches
307+
multiple version-shaped values (typical pyproject.toml with
308+
``[tool.poetry].version`` and ``[tool.commitizen].version``),
309+
``--check-consistency`` should flag the lines whose version doesn't match
310+
the current one instead of silently leaving the sibling out of date.
311+
"""
312+
pyproject = tmp_path / "pyproject.toml"
313+
pyproject.write_text(
314+
'[tool.poetry]\nversion = "2.5.7"\n\n[tool.commitizen]\nversion = "2.5.2"\n',
315+
encoding="utf-8",
316+
)
317+
318+
with pytest.raises(CurrentVersionNotFoundError) as excinfo:
319+
bump.update_version_in_files(
320+
current_version="2.5.2",
321+
new_version="2.6.0",
322+
version_files=[f"{pyproject}:version"],
323+
check_consistency=True,
324+
encoding="utf-8",
325+
)
326+
327+
msg = str(excinfo.value)
328+
assert "2.5.7" in msg
329+
assert "2.5.2" in msg
330+
# The original file must NOT have been rewritten when consistency fails.
331+
# (We re-read it to confirm the bump didn't proceed.)
332+
assert '"2.5.2"' in pyproject.read_text(encoding="utf-8")
333+
334+
335+
def test_update_version_in_files_check_consistency_off_keeps_legacy_behaviour(
336+
tmp_path,
337+
):
338+
"""Without ``check_consistency``, the old behaviour is preserved: only
339+
the lines that contain the current version are updated, and sibling
340+
versions are left alone (no exception)."""
341+
pyproject = tmp_path / "pyproject.toml"
342+
pyproject.write_text(
343+
'[tool.poetry]\nversion = "2.5.7"\n\n[tool.commitizen]\nversion = "2.5.2"\n',
344+
encoding="utf-8",
345+
)
346+
347+
bump.update_version_in_files(
348+
current_version="2.5.2",
349+
new_version="2.6.0",
350+
version_files=[f"{pyproject}:version"],
351+
check_consistency=False,
352+
encoding="utf-8",
353+
)
354+
355+
rewritten = pyproject.read_text(encoding="utf-8")
356+
assert '[tool.poetry]\nversion = "2.5.7"' in rewritten
357+
assert '[tool.commitizen]\nversion = "2.6.0"' in rewritten
358+
359+
305360
@pytest.mark.parametrize(
306361
("encoding", "filename"),
307362
[

0 commit comments

Comments
 (0)