Skip to content

Commit

Permalink
Fixed issue with tag name.
Browse files Browse the repository at this point in the history
Fixes #74

current_version and tag_name now do not need to match exactly
  • Loading branch information
coordt committed Nov 18, 2023
1 parent 909a53f commit e218264
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 19 deletions.
3 changes: 1 addition & 2 deletions bumpversion/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,7 @@ def get_configuration(config_file: Union[str, Path, None] = None, **overrides) -
config = Config(**config_dict) # type: ignore[arg-type]

# Get the information about the SCM
tag_pattern = config.tag_name.replace("{new_version}", "*")
scm_info = get_scm_info(tag_pattern)
scm_info = get_scm_info(config.tag_name, config.parse)
config.scm_info = scm_info

# Update and verify the current_version
Expand Down
33 changes: 22 additions & 11 deletions bumpversion/scm.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def assert_nondirty(cls) -> None:
raise NotImplementedError()

@classmethod
def latest_tag_info(cls, tag_pattern: str) -> SCMInfo:
def latest_tag_info(cls, tag_name: str, parse_pattern: str) -> SCMInfo:
"""Return information about the latest tag."""
raise NotImplementedError()

Expand All @@ -109,6 +109,14 @@ def get_all_tags(cls) -> List[str]:
except (FileNotFoundError, PermissionError, NotADirectoryError, subprocess.CalledProcessError):
return []

@classmethod
def get_version_from_tag(cls, tag: str, tag_name: str, parse_pattern: str) -> Optional[str]:
"""Return the version from a tag."""
version_pattern = parse_pattern.replace("\\\\", "\\")
rep = tag_name.replace("{new_version}", f"(?P<current_version>{version_pattern})")
tag_regex = re.compile(rep)
return match["current_version"] if (match := tag_regex.match(tag)) else None

@classmethod
def commit_to_scm(
cls,
Expand Down Expand Up @@ -173,7 +181,6 @@ def tag_in_scm(cls, config: "Config", context: MutableMapping, dry_run: bool = F
tag_name = config.tag_name.format(**context)
tag_message = config.tag_message.format(**context)
existing_tags = cls.get_all_tags()

do_tag = not dry_run

if tag_name in existing_tags:
Expand Down Expand Up @@ -219,15 +226,15 @@ def assert_nondirty(cls) -> None:
raise DirtyWorkingDirectoryError(f"Git working directory is not clean:\n\n{joined_lines}")

@classmethod
def latest_tag_info(cls, tag_pattern: str) -> SCMInfo:
def latest_tag_info(cls, tag_name: str, parse_pattern: str) -> SCMInfo:
"""Return information about the latest tag."""
try:
# git-describe doesn't update the git-index, so we do that
subprocess.run(["git", "update-index", "--refresh", "-q"], capture_output=True) # noqa: S603, S607
except subprocess.CalledProcessError as e:
logger.debug("Error when running git update-index: %s", e.stderr)
return SCMInfo(tool=cls)

tag_pattern = tag_name.replace("{new_version}", "*")
try:
# get info about the latest tag in git
git_cmd = [
Expand Down Expand Up @@ -260,7 +267,8 @@ def latest_tag_info(cls, tag_pattern: str) -> SCMInfo:

info.commit_sha = describe_out.pop().lstrip("g")
info.distance_to_latest_tag = int(describe_out.pop())
info.current_version = "-".join(describe_out).lstrip("v")
version = cls.get_version_from_tag(describe_out[-1], tag_name, parse_pattern)
info.current_version = version or "-".join(describe_out).lstrip("v")

return info

Expand Down Expand Up @@ -298,10 +306,10 @@ class Mercurial(SourceCodeManager):
_ALL_TAGS_COMMAND: ClassVar[List[str]] = ["hg", "log", '--rev="tag()"', '--template="{tags}\n"']

@classmethod
def latest_tag_info(cls, tag_pattern: str) -> SCMInfo:
def latest_tag_info(cls, tag_name: str, parse_pattern: str) -> SCMInfo:
"""Return information about the latest tag."""
current_version = None
re_pattern = tag_pattern.replace("*", ".*")
re_pattern = tag_name.replace("{new_version}", ".*")
result = subprocess.run(
["hg", "log", "-r", f"tag('re:{re_pattern}')", "--template", "{latesttag}\n"], # noqa: S603, S607
text=True,
Expand All @@ -310,7 +318,10 @@ def latest_tag_info(cls, tag_pattern: str) -> SCMInfo:
)
result.check_returncode()
if result.stdout:
current_version = result.stdout.splitlines(keepends=False)[-1].lstrip("v")
tag_string = result.stdout.splitlines(keepends=False)[-1]
current_version = cls.get_version_from_tag(tag_string, tag_name, parse_pattern)
else:
logger.debug("No tags found")
is_dirty = len(subprocess.check_output(["hg", "status", "-mard"])) != 0 # noqa: S603, S607
return SCMInfo(tool=cls, current_version=current_version, dirty=is_dirty)

Expand Down Expand Up @@ -356,11 +367,11 @@ def tag(cls, name: str, sign: bool = False, message: Optional[str] = None) -> No
subprocess.check_output(command) # noqa: S603


def get_scm_info(tag_pattern: str) -> SCMInfo:
def get_scm_info(tag_name: str, parse_pattern: str) -> SCMInfo:
"""Return a dict with the latest source code management info."""
if Git.is_usable():
return Git.latest_tag_info(tag_pattern)
return Git.latest_tag_info(tag_name, parse_pattern)
elif Mercurial.is_usable():
return Mercurial.latest_tag_info(tag_pattern)
return Mercurial.latest_tag_info(tag_name, parse_pattern)
else:
return SCMInfo()
14 changes: 8 additions & 6 deletions tests/test_scm.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,25 @@ def test_git_latest_tag_info(git_repo: Path) -> None:
"""Should return information about the latest tag."""
readme = git_repo.joinpath("readme.md")
readme.touch()

tag_prefix = "app/"
parse_pattern = r"(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)"
tag_name = f"{tag_prefix}{{new_version}}"
with inside_dir(git_repo):
assert scm.Git.latest_tag_info("v*") == scm.SCMInfo(tool=scm.Git)
assert scm.Git.latest_tag_info(tag_name, parse_pattern=parse_pattern) == scm.SCMInfo(tool=scm.Git)

# Add a file and tag
subprocess.run(["git", "add", "readme.md"])
subprocess.run(["git", "commit", "-m", "first"])
subprocess.run(["git", "tag", "v0.1.0"])
tag_info = scm.Git.latest_tag_info("v*")
subprocess.run(["git", "tag", f"{tag_prefix}0.1.0"])
tag_info = scm.Git.latest_tag_info(tag_name, parse_pattern=parse_pattern)
assert tag_info.commit_sha is not None
assert tag_info.current_version == "0.1.0"
assert tag_info.distance_to_latest_tag == 0

# Make it dirty
git_repo.joinpath("something.md").touch()
subprocess.run(["git", "add", "something.md"])
tag_info = scm.Git.latest_tag_info("v*")
tag_info = scm.Git.latest_tag_info(tag_name, parse_pattern=parse_pattern)
assert tag_info.commit_sha is not None
assert tag_info.current_version == "0.1.0"
assert tag_info.distance_to_latest_tag == 0
Expand Down Expand Up @@ -137,7 +139,7 @@ def test_commit_and_tag_from_below_scm_root(repo: str, scm_command: str, scm_cla
scm_class.tag_in_scm(config=conf, context=context)

# Assert
tag_info = scm_class.latest_tag_info("v*")
tag_info = scm_class.latest_tag_info(conf.tag_name, parse_pattern=conf.parse)
if scm_command == "git":
assert tag_info.commit_sha is not None
assert tag_info.distance_to_latest_tag == 0
Expand Down

0 comments on commit e218264

Please sign in to comment.