Skip to content

Commit d201dff

Browse files
committed
Fixes lack of rendering in moveable tags
1 parent 65a9f4c commit d201dff

File tree

2 files changed

+108
-19
lines changed

2 files changed

+108
-19
lines changed

bumpversion/scm/git.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def commit_and_tag(self, files: List[Pathlike], context: MutableMapping, dry_run
103103
tag(tag_name, sign=self.config.sign_tags, message=tag_message)
104104

105105
for m_tag_name in self.config.moveable_tags:
106-
moveable_tag(m_tag_name)
106+
moveable_tag(m_tag_name.format(**context))
107107

108108
def assert_nondirty(self) -> None:
109109
"""

tests/test_scm/test_git.py

Lines changed: 107 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,56 @@
1414
from tests.conftest import inside_dir
1515

1616

17+
@pytest.fixture
18+
def git_instance(scm_config: SCMConfig) -> Git:
19+
"""Return a Git instance."""
20+
return Git(config=scm_config)
21+
22+
1723
class TestGit:
1824
"""Tests related to Git."""
1925

2026
class TestIsAvailable:
2127
"""Tests related to Git.is_available."""
2228

23-
def test_recognizes_a_git_repo(self, git_repo: Path, scm_config: SCMConfig) -> None:
29+
def test_recognizes_a_git_repo(self, git_repo: Path, git_instance: Git) -> None:
2430
"""Should return true if git is available, and it is a git repo."""
2531
with inside_dir(git_repo):
26-
git_tool = Git(scm_config)
27-
assert git_tool.is_available()
32+
assert git_instance.is_available()
2833

29-
def test_recognizes_not_a_git_repo(self, tmp_path: Path, scm_config: SCMConfig) -> None:
34+
def test_recognizes_not_a_git_repo(self, tmp_path: Path, git_instance: Git) -> None:
3035
"""Should return false if it is not a git repo."""
3136
with inside_dir(tmp_path):
32-
git_tool = Git(scm_config)
33-
assert not git_tool.is_available()
37+
assert not git_instance.is_available()
3438

3539
class TestLatestTagInfo:
3640
"""Test for the Git.latest_tag_info() function."""
3741

38-
def test_returns_default_if_not_available(self, tmp_path: Path, scm_config: SCMConfig) -> None:
42+
def test_returns_default_if_not_available(self, tmp_path: Path, git_instance: Git) -> None:
3943
"""If git is not available, it returns the default LatestTagInfo object, with all None values."""
4044
# Arrange
4145
expected = LatestTagInfo()
42-
tool = Git(scm_config)
4346

4447
# Act
4548
with inside_dir(tmp_path):
46-
info = tool.latest_tag_info()
49+
info = git_instance.latest_tag_info()
4750

4851
# Assert
4952
assert info == expected
5053

51-
def test_returns_correct_commit_and_tag_info(self, git_repo: Path, scm_config: SCMConfig) -> None:
54+
def test_returns_correct_commit_and_tag_info(self, git_repo: Path, git_instance: Git) -> None:
5255
"""Should return information that it is a git repo."""
5356
# Arrange
5457
tag_prefix = "app/"
5558
readme = git_repo.joinpath("readme.md")
5659
readme.touch()
57-
scm_config.tag_name = f"{tag_prefix}{{new_version}}"
60+
git_instance.config.tag_name = f"{tag_prefix}{{new_version}}"
5861

5962
# Act
6063
with inside_dir(git_repo):
6164
commit_readme("first")
6265
tag(f"{tag_prefix}0.1.0", sign=False, message="bumpversion")
63-
tag_info = Git(scm_config).latest_tag_info()
66+
tag_info = git_instance.latest_tag_info()
6467

6568
# Assert
6669
assert tag_info.commit_sha is not None
@@ -79,7 +82,7 @@ class TestGitAddPath:
7982
@patch("bumpversion.scm.git.Git.latest_tag_info")
8083
@patch("bumpversion.scm.git.is_subpath")
8184
def test_valid_subpath_is_added(
82-
self, mock_is_subpath, mock_latest_tag_info, mock_run_command, scm_config: SCMConfig, tmp_path: Path
85+
self, mock_is_subpath, mock_latest_tag_info, mock_run_command, git_instance: Git, tmp_path: Path
8386
):
8487
"""A path that is a subpath of the repository root should be added."""
8588
# Arrange
@@ -89,7 +92,6 @@ def test_valid_subpath_is_added(
8992
mock_latest_tag_info.return_value.repository_root = repository_root
9093
mock_is_subpath.return_value = True
9194
mock_run_command.return_value = None
92-
git_instance = Git(scm_config)
9395

9496
# Act
9597
with inside_dir(repository_root):
@@ -102,7 +104,7 @@ def test_valid_subpath_is_added(
102104
@patch("bumpversion.scm.git.Git.latest_tag_info")
103105
@patch("bumpversion.scm.git.is_subpath")
104106
def test_invalid_subpath_is_not_added(
105-
self, mock_is_subpath, mock_latest_tag_info, mock_run_command, scm_config, tmp_path: Path
107+
self, mock_is_subpath, mock_latest_tag_info, mock_run_command, git_instance: Git, tmp_path: Path
106108
):
107109
"""A path that is not a subpath of the repository root should not be added."""
108110
# Arrange
@@ -111,7 +113,6 @@ def test_invalid_subpath_is_not_added(
111113
path_to_add = repository_root / "file.txt"
112114
mock_latest_tag_info.return_value.repository_root = repository_root
113115
mock_is_subpath.return_value = False
114-
git_instance = Git(scm_config)
115116

116117
# Act
117118
git_instance.add_path(path_to_add)
@@ -123,7 +124,7 @@ def test_invalid_subpath_is_not_added(
123124
@patch("bumpversion.scm.git.Git.latest_tag_info")
124125
@patch("bumpversion.scm.git.is_subpath")
125126
def test_raises_error_on_command_failure(
126-
self, mock_is_subpath, mock_latest_tag_info, mock_run_command, scm_config: SCMConfig, tmp_path: Path
127+
self, mock_is_subpath, mock_latest_tag_info, mock_run_command, git_instance: Git, tmp_path: Path
127128
):
128129
"""If the git command fails, a BumpVersionError should be raised."""
129130
# Arrange
@@ -133,13 +134,101 @@ def test_raises_error_on_command_failure(
133134
mock_latest_tag_info.return_value.repository_root = repository_root
134135
mock_is_subpath.return_value = True
135136
mock_run_command.side_effect = subprocess.CalledProcessError(returncode=1, cmd="git add")
136-
git_instance = Git(scm_config)
137137

138138
# Act / Assert
139139
with inside_dir(repository_root):
140140
with pytest.raises(BumpVersionError):
141141
git_instance.add_path(path_to_add)
142142

143+
class TestGitCommitAndTag:
144+
"""Tests for the commit_and_tag() method."""
145+
146+
def test_dry_run_skips_method(self, git_instance: Git, mocker):
147+
"""If dry_run is True, the method is short-circuited."""
148+
# Arrange
149+
files = ["file1.txt", "file2.txt"]
150+
context = {"new_version": "1.0.0", "new_major": "1", "current_version": "0.1.0"}
151+
mock_add_path = mocker.patch.object(git_instance, "add_path")
152+
mock_commit = mocker.patch.object(git_instance, "commit")
153+
mock_tag = mocker.patch("bumpversion.scm.git.tag")
154+
mock_moveable_tag = mocker.patch("bumpversion.scm.git.moveable_tag")
155+
156+
# Act
157+
git_instance.commit_and_tag(files, context, dry_run=True)
158+
159+
# Assert
160+
mock_add_path.assert_not_called()
161+
mock_commit.assert_not_called()
162+
mock_tag.assert_not_called()
163+
mock_moveable_tag.assert_not_called()
164+
165+
def test_commits_and_tags_when_configured(self, git_instance: Git, mocker):
166+
"""Does both commit and tag functions when they are configured."""
167+
# Arrange
168+
files = ["file1.txt", "file2.txt"]
169+
context = {"new_version": "1.0.0", "new_major": "1", "current_version": "0.1.0"}
170+
git_instance.config.moveable_tags = ["v{new_major}"]
171+
git_instance.config.tag = True
172+
git_instance.config.commit = True
173+
mock_add_path = mocker.patch.object(git_instance, "add_path")
174+
mock_commit = mocker.patch.object(git_instance, "commit")
175+
mock_tag = mocker.patch("bumpversion.scm.git.tag")
176+
mock_moveable_tag = mocker.patch("bumpversion.scm.git.moveable_tag")
177+
178+
# Act
179+
git_instance.commit_and_tag(files, context, dry_run=False)
180+
181+
# Assert
182+
assert mock_add_path.call_count == len(files)
183+
mock_add_path.assert_any_call("file1.txt")
184+
mock_add_path.assert_any_call("file2.txt")
185+
mock_commit.assert_called_once_with(context)
186+
mock_tag.assert_called_once_with("v1.0.0", sign=False, message="Bump version: 0.1.0 → 1.0.0")
187+
mock_moveable_tag.assert_called_once_with("v1")
188+
189+
def test_tags_when_commit_is_false(self, git_instance: Git, mocker):
190+
"""The method only tags when commit is False."""
191+
# Arrange
192+
files = ["file1.txt"]
193+
context = {"new_version": "1.0.0", "new_major": "1", "current_version": "0.1.0"}
194+
git_instance.config.moveable_tags = ["v{new_major}"]
195+
git_instance.config.commit = False
196+
git_instance.config.tag = True
197+
mock_add_path = mocker.patch.object(git_instance, "add_path")
198+
mock_commit = mocker.patch.object(git_instance, "commit")
199+
mock_tag = mocker.patch("bumpversion.scm.git.tag")
200+
mock_moveable_tag = mocker.patch("bumpversion.scm.git.moveable_tag")
201+
202+
# Act
203+
git_instance.commit_and_tag(files, context, dry_run=False)
204+
205+
# Assert
206+
mock_add_path.assert_not_called()
207+
mock_commit.assert_not_called()
208+
mock_tag.assert_called_once_with("v1.0.0", sign=False, message="Bump version: 0.1.0 → 1.0.0")
209+
mock_moveable_tag.assert_called_once_with("v1")
210+
211+
def test_commits_when_tag_is_false(self, git_instance: Git, mocker):
212+
"""The method only commits when tag is False."""
213+
# Arrange
214+
files = ["file1.txt"]
215+
context = {"new_version": "1.0.0", "new_major": "1", "current_version": "0.1.0"}
216+
git_instance.config.moveable_tags = ["v{new_major}"]
217+
git_instance.config.tag = False
218+
git_instance.config.commit = True
219+
mock_add_path = mocker.patch.object(git_instance, "add_path")
220+
mock_commit = mocker.patch.object(git_instance, "commit")
221+
mock_tag = mocker.patch("bumpversion.scm.git.tag")
222+
mock_moveable_tag = mocker.patch("bumpversion.scm.git.moveable_tag")
223+
224+
# Act
225+
git_instance.commit_and_tag(files, context, dry_run=False)
226+
227+
mock_add_path.assert_called_with("file1.txt")
228+
mock_commit.assert_called_once_with(context)
229+
mock_tag.assert_not_called()
230+
mock_moveable_tag.assert_not_called()
231+
143232

144233
class TestRevisionInfo:
145234
"""Tests for the revision_info function."""

0 commit comments

Comments
 (0)