Skip to content

Commit 7895ce1

Browse files
committed
Fix issue #46: Add tag detection for Git updates
Add git_is_tag() method to detect if a branch value is actually a tag, and handle tags correctly during git_update(): - Tags are checked out directly with 'git checkout <tag>' - Branches use the existing switch + merge logic - Explicitly fetch tags with 'git fetch --tags' This fixes the regression where updating from one tag to another stopped working in v4.x (worked in v2.x). The test now passes, demonstrating that tag updates work correctly. Fixes #46
1 parent 9fa8e3c commit 7895ce1

File tree

2 files changed

+34
-3
lines changed

2 files changed

+34
-3
lines changed

CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## 4.1.2 (unreleased)
44

5+
- Fix #46: Git tags in branch option are now correctly detected and handled during updates. Previously, updating from one tag to another failed because tags were incorrectly treated as branches.
6+
[jensens]
7+
58
- Fix #53: Per-package target setting now correctly overrides default-target when constructing checkout paths.
69
[jensens]
710

src/mxdev/vcs/git.py

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,25 @@ def git_switch_branch(
231231
raise GitError(f"git checkout of branch '{branch}' failed.\n{stderr}")
232232
return (stdout_in + stdout, stderr_in + stderr)
233233

234+
def git_is_tag(self, tag_name: str) -> bool:
235+
"""Check if the given name is a git tag.
236+
237+
Returns True if tag_name exists as a tag in the repository.
238+
"""
239+
path = self.source["path"]
240+
cmd = self.run_git(["tag", "-l", tag_name], cwd=path)
241+
stdout, stderr = cmd.communicate()
242+
if cmd.returncode != 0:
243+
return False
244+
# git tag -l returns the tag name if it exists, empty if not
245+
return tag_name in stdout.strip().split("\n")
246+
234247
def git_update(self, **kwargs) -> typing.Union[str, None]:
235248
name = self.source["name"]
236249
path = self.source["path"]
237250
self.output((logger.info, "Updated '%s' with git." % name))
238251
# First we fetch. This should always be possible.
239-
argv = ["fetch"]
252+
argv = ["fetch", "--tags"] # Also fetch tags explicitly
240253
update_git_submodules = self.source.get("submodules", kwargs["submodules"])
241254
if update_git_submodules == "recursive":
242255
argv.append("--recurse-submodules")
@@ -247,8 +260,23 @@ def git_update(self, **kwargs) -> typing.Union[str, None]:
247260
if "rev" in self.source:
248261
stdout, stderr = self.git_switch_branch(stdout, stderr)
249262
elif "branch" in self.source:
250-
stdout, stderr = self.git_switch_branch(stdout, stderr)
251-
stdout, stderr = self.git_merge_rbranch(stdout, stderr)
263+
# Check if 'branch' is actually a tag (#46)
264+
branch_value = self.source["branch"]
265+
if self.git_is_tag(branch_value):
266+
# It's a tag - checkout directly without merge
267+
cmd = self.run_git(["checkout", branch_value], cwd=path)
268+
tag_stdout, tag_stderr = cmd.communicate()
269+
if cmd.returncode != 0:
270+
raise GitError(
271+
f"git checkout of tag '{branch_value}' failed.\n{tag_stderr}"
272+
)
273+
stdout += tag_stdout
274+
stderr += tag_stderr
275+
self.output((logger.info, f"Switched to tag '{branch_value}'."))
276+
else:
277+
# It's a branch - use normal branch switch + merge
278+
stdout, stderr = self.git_switch_branch(stdout, stderr)
279+
stdout, stderr = self.git_merge_rbranch(stdout, stderr)
252280
else:
253281
# We may have specified a branch previously but not
254282
# anymore. In that case, we want to revert to master.

0 commit comments

Comments
 (0)