Skip to content

Commit 890b692

Browse files
committed
Refactor error handling and improve logging in utils
Extracted error formatting to a dedicated function and applied it across the codebase. Improved command path handling in `add_path` and enhanced test coverage with necessary imports and logging configurations.
1 parent 5fb5ef2 commit 890b692

File tree

4 files changed

+42
-22
lines changed

4 files changed

+42
-22
lines changed

bumpversion/scm.py

+12-13
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, MutableMapping, Optional, Type, Union
1010

1111
from bumpversion.ui import get_indented_logger
12-
from bumpversion.utils import extract_regex_flags, run_command
12+
from bumpversion.utils import extract_regex_flags, format_and_raise_error, run_command
1313

1414
if TYPE_CHECKING: # pragma: no-coverage
1515
from bumpversion.config import Config
1616

17-
from bumpversion.exceptions import BumpVersionError, DirtyWorkingDirectoryError, SignedTagsError
17+
from bumpversion.exceptions import DirtyWorkingDirectoryError, SignedTagsError
1818

1919
logger = get_indented_logger(__name__)
2020

@@ -53,7 +53,7 @@ def path_in_repo(self, path: Union[Path, str]) -> bool:
5353
if self.repository_root is None:
5454
return True
5555

56-
return Path(path).is_relative_to(self.repository_root)
56+
return str(path).startswith(str(self.repository_root))
5757

5858

5959
class SourceCodeManager:
@@ -93,14 +93,7 @@ def commit(cls, message: str, current_version: str, new_version: str, extra_args
9393
@classmethod
9494
def format_and_raise_error(cls, exc: Union[TypeError, subprocess.CalledProcessError]) -> None:
9595
"""Format the error message from an exception and re-raise it as a BumpVersionError."""
96-
if isinstance(exc, subprocess.CalledProcessError):
97-
output = "\n".join([x for x in [exc.stdout.decode("utf8"), exc.stderr.decode("utf8")] if x])
98-
cmd = " ".join(exc.cmd)
99-
err_msg = f"Failed to run `{cmd}`: return code {exc.returncode}, output: {output}"
100-
else: # pragma: no-coverage
101-
err_msg = f"Failed to run {cls._COMMIT_COMMAND}: {exc}"
102-
logger.exception(err_msg)
103-
raise BumpVersionError(err_msg) from exc
96+
format_and_raise_error(exc)
10497

10598
@classmethod
10699
def is_usable(cls) -> bool:
@@ -355,8 +348,14 @@ def _revision_info(cls) -> dict:
355348
def add_path(cls, path: Union[str, Path]) -> None:
356349
"""Add a path to the VCS."""
357350
info = SCMInfo(**cls._revision_info())
358-
if info.path_in_repo(path):
359-
run_command(["git", "add", "--update", str(path)])
351+
if not info.path_in_repo(path):
352+
return
353+
cwd = Path.cwd()
354+
temp_path = os.path.relpath(path, cwd)
355+
try:
356+
run_command(["git", "add", "--update", str(temp_path)])
357+
except subprocess.CalledProcessError as e:
358+
format_and_raise_error(e)
360359

361360
@classmethod
362361
def tag(cls, name: str, sign: bool = False, message: Optional[str] = None) -> None:

bumpversion/utils.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import string
44
import subprocess
55
from subprocess import CompletedProcess
6-
from typing import Any, List, Optional, Tuple
6+
from typing import Any, List, Optional, Tuple, Union
7+
8+
from bumpversion.exceptions import BumpVersionError
9+
from bumpversion.ui import get_indented_logger
10+
11+
logger = get_indented_logger(__name__)
712

813

914
def extract_regex_flags(regex_pattern: str) -> Tuple[str, str]:
@@ -103,6 +108,18 @@ def set_nested_value(d: dict, value: Any, path: str) -> None:
103108
current_element = current_element[key]
104109

105110

111+
def format_and_raise_error(exc: Union[TypeError, subprocess.CalledProcessError]) -> None:
112+
"""Format the error message from an exception and re-raise it as a BumpVersionError."""
113+
if isinstance(exc, subprocess.CalledProcessError):
114+
output = "\n".join([x for x in [exc.stdout, exc.stderr] if x])
115+
cmd = " ".join(exc.cmd)
116+
err_msg = f"Failed to run `{cmd}`: return code {exc.returncode}, output: {output}"
117+
else: # pragma: no-coverage
118+
err_msg = f"Failed to run a command: {exc}"
119+
logger.exception(err_msg)
120+
raise BumpVersionError(err_msg) from exc
121+
122+
106123
def run_command(command: list, env: Optional[dict] = None) -> CompletedProcess:
107124
"""Run a shell command and return its output."""
108125
result = subprocess.run(command, text=True, check=True, capture_output=True, env=env) # NOQA: S603

tests/test_bump.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,17 @@ def mock_context():
2222
class TestGetNextVersion:
2323
"""Tests for the get_next_version function."""
2424

25-
def test_passing_a_new_version_should_override_a_version_part(self):
25+
def test_passing_a_new_version_should_override_a_version_part(self, tmp_path: Path):
2626
"""Passing a new version should return that version."""
2727
# Arrange
28-
config, version_config, current_version = get_config_data({"current_version": "0.1.0"})
29-
version_part = "patch"
30-
new_version = "1.2.3"
31-
expected_next_version = version_config.parse("1.2.3")
28+
with inside_dir(tmp_path):
29+
config, version_config, current_version = get_config_data({"current_version": "0.1.0"})
30+
version_part = "patch"
31+
new_version = "1.2.3"
32+
expected_next_version = version_config.parse("1.2.3")
3233

33-
# Act
34-
actual_next_version = bump.get_next_version(current_version, config, version_part, new_version)
34+
# Act
35+
actual_next_version = bump.get_next_version(current_version, config, version_part, new_version)
3536

3637
# Assert
3738
assert actual_next_version == expected_next_version

tests/test_scm.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""Tests of the VCS module."""
22

3+
import logging
34
import subprocess
45
from pathlib import Path
56

@@ -9,6 +10,7 @@
910
from bumpversion import scm
1011
from bumpversion.exceptions import DirtyWorkingDirectoryError, BumpVersionError
1112
from bumpversion.ui import setup_logging
13+
from bumpversion.utils import run_command
1214
from tests.conftest import get_config_data, inside_dir
1315

1416

@@ -49,7 +51,7 @@ def test_format_and_raise_error_returns_scm_error(self, git_repo: Path) -> None:
4951
"""The output formatting from called process error string includes the underlying scm error."""
5052
with inside_dir(git_repo):
5153
try:
52-
subprocess.run(["git", "add", "newfile.txt"], capture_output=True, check=True) # noqa: S603
54+
run_command(["git", "add", "newfile.txt"])
5355
except subprocess.CalledProcessError as e:
5456
with pytest.raises(BumpVersionError) as bump_error:
5557
scm.Git.format_and_raise_error(e)
@@ -274,6 +276,7 @@ def test_commit_tag_dry_run_interactions(
274276
):
275277
"""Combinations of commit, tag, dry-run and should produce the expected results."""
276278
# Arrange
279+
caplog.set_level(logging.INFO)
277280
repo_path: Path = request.getfixturevalue(repo)
278281
version_path = repo_path / "VERSION"
279282
version_path.write_text("30.0.3", encoding="utf-8")

0 commit comments

Comments
 (0)