Skip to content

Commit

Permalink
Add Bazaar support
Browse files Browse the repository at this point in the history
  • Loading branch information
mtkennerly committed Apr 17, 2019
1 parent 0554102 commit f3c3cef
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

## Unreleased

* Added Bazaar support.
* Added the `dunamai check` command and the corresponding `check_version`
function.
* Added the option to check just the latest tag or to keep checking tags
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ simply by creating a tag.
* Mercurial
* Darcs
* Subversion
* Bazaar
* Version styles:
* [PEP 440](https://www.python.org/dev/peps/pep-0440)
* [Semantic Versioning](https://semver.org)
Expand Down
41 changes: 40 additions & 1 deletion dunamai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,43 @@ def from_subversion(

return cls(base, pre=pre, post=post, dev=dev, commit=commit, dirty=dirty)

@classmethod
def from_bazaar(cls, pattern: str = _VERSION_PATTERN, latest_tag: bool = False) -> "Version":
r"""
Determine a version based on Bazaar tags.
:param pattern: Regular expression matched against the version source.
This should contain one capture group named `base` corresponding to
the release segment of the source, and optionally another two groups
named `pre_type` and `pre_number` corresponding to the type (a, b, rc)
and number of prerelease. For example, with a tag like v0.1.0, the
pattern would be `v(?P<base>\d+\.\d+\.\d+)`.
:param latest_tag: If true, only inspect the latest tag for a pattern
match. If false, keep looking at tags until there is a match.
"""
code, msg = _run_cmd("bzr status")
dirty = msg != ""

code, msg = _run_cmd("bzr log --limit 1 --line")
commit = msg.split(":", 1)[0] if msg else None

code, msg = _run_cmd("bzr tags")
if not msg or not commit:
return cls("0.0.0", post=0, dev=0, commit=commit, dirty=dirty)
tags_to_revs = {line.split()[0]: int(line.split()[1]) for line in msg.splitlines()}
tags = [x[1] for x in sorted([(v, k) for k, v in tags_to_revs.items()], reverse=True)]
tag, base, pre = _match_version_pattern(pattern, tags, latest_tag)

distance = int(commit) - tags_to_revs[tag]

post = None
dev = None
if distance > 0:
post = distance
dev = 0

return cls(base, pre=pre, post=post, dev=dev, commit=commit, dirty=dirty)

@classmethod
def from_any_vcs(cls, pattern: str = None, latest_tag: bool = False) -> "Version":
"""
Expand All @@ -488,7 +525,7 @@ def from_any_vcs(cls, pattern: str = None, latest_tag: bool = False) -> "Version
:param latest_tag: If true, only inspect the latest tag for a pattern
match. If false, keep looking at tags until there is a match.
"""
vcs = _find_higher_dir(".git", ".hg", "_darcs", ".svn")
vcs = _find_higher_dir(".git", ".hg", "_darcs", ".svn", ".bzr")

if pattern is None:
pattern = _VERSION_PATTERN
Expand All @@ -501,6 +538,8 @@ def from_any_vcs(cls, pattern: str = None, latest_tag: bool = False) -> "Version
return cls.from_darcs(pattern=pattern, latest_tag=latest_tag)
elif vcs == ".svn":
return cls.from_subversion(pattern=pattern, latest_tag=latest_tag)
elif vcs == ".bzr":
return cls.from_bazaar(pattern=pattern, latest_tag=latest_tag)
else:
raise RuntimeError("Unable to detect version control system.")

Expand Down
7 changes: 7 additions & 0 deletions dunamai/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Vcs(Enum):
Mercurial = "mercurial"
Darcs = "darcs"
Subversion = "subversion"
Bazaar = "bazaar"


common_sub_args = [
Expand Down Expand Up @@ -107,6 +108,10 @@ class Vcs(Enum):
},
],
},
Vcs.Bazaar.value: {
"description": "Generate version from Bazaar",
"args": common_sub_args,
},
},
},
"check": {
Expand Down Expand Up @@ -188,6 +193,8 @@ def from_vcs(
version = Version.from_darcs(pattern=pattern, latest_tag=latest_tag)
elif vcs == Vcs.Subversion:
version = Version.from_subversion(pattern=pattern, latest_tag=latest_tag, tag_dir=tag_dir)
elif vcs == Vcs.Bazaar:
version = Version.from_bazaar(pattern=pattern, latest_tag=latest_tag)

print(version.serialize(metadata, dirty, format, style))

Expand Down
38 changes: 38 additions & 0 deletions tests/test_dunamai.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,44 @@ def test__version__from_subversion(tmp_path):
from_vcs(latest_tag=True)


@pytest.mark.skipif(shutil.which("bzr") is None, reason="Requires Bazaar")
def test__version__from_bazaar(tmp_path):
vcs = tmp_path / "dunamai-bzr"
vcs.mkdir()
run = make_run_callback(vcs)
from_vcs = make_from_callback(Version.from_bazaar, mock_commit=None)

with chdir(vcs):
run("bzr init")
assert from_vcs() == Version("0.0.0", post=0, dev=0, commit=None, dirty=False)

(vcs / "foo.txt").write_text("hi")
assert from_vcs() == Version("0.0.0", post=0, dev=0, commit=None, dirty=True)

run("bzr add .")
run('bzr commit -m "Initial commit"')
assert from_vcs() == Version("0.0.0", post=0, dev=0, commit="1", dirty=False)

run("bzr tag v0.1.0")
assert from_vcs() == Version("0.1.0", commit="1", dirty=False)
assert from_vcs(latest_tag=True) == Version("0.1.0", commit="1", dirty=False)
assert run("dunamai from bazaar") == "0.1.0"
assert run("dunamai from any") == "0.1.0"

(vcs / "foo.txt").write_text("bye")
assert from_vcs() == Version("0.1.0", commit="1", dirty=True)

run("bzr add .")
run('bzr commit -m "Second"')
assert from_vcs() == Version("0.1.0", post=1, dev=0, commit="2", dirty=False)
assert from_any_vcs_unmocked() == Version("0.1.0", post=1, dev=0, commit="2", dirty=False)

run("bzr tag unmatched")
assert from_vcs() == Version("0.1.0", post=1, dev=0, commit="2", dirty=False)
with pytest.raises(ValueError):
from_vcs(latest_tag=True)


def test__version__from_any_vcs(tmp_path):
with chdir(tmp_path):
with pytest.raises(RuntimeError):
Expand Down
1 change: 1 addition & 0 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def test__parse_args__from():
assert parse_args(["from", "darcs"]).vcs == "darcs"
assert parse_args(["from", "subversion"]).vcs == "subversion"
assert parse_args(["from", "subversion"]).tag_dir == "tags"
assert parse_args(["from", "bazaar"]).vcs == "bazaar"
assert parse_args(["from", "any", "--pattern", r"\d+"]).pattern == r"\d+"
assert parse_args(["from", "any", "--metadata"]).metadata is True
assert parse_args(["from", "any", "--no-metadata"]).metadata is False
Expand Down

0 comments on commit f3c3cef

Please sign in to comment.