Skip to content

Commit

Permalink
Add Darcs support
Browse files Browse the repository at this point in the history
  • Loading branch information
mtkennerly committed Mar 30, 2019
1 parent e851bba commit 03e2e07
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

* Added built-in Semantic Versioning output style in addition to PEP 440.
* Added style validation for custom output formats.
* Added Darcs support.

## v0.4.0 (2019-03-29)

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ control system.
* Version control system support:
* Git
* Mercurial
* Darcs
* Version styles:
* [PEP 440](https://www.python.org/dev/peps/pep-0440)
* [Semantic Versioning](https://semver.org)
Expand Down
59 changes: 58 additions & 1 deletion dunamai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,62 @@ def from_mercurial(cls, pattern: str = _VERSION_PATTERN) -> "Version":

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

@classmethod
def from_darcs(cls, pattern: str = _VERSION_PATTERN) -> "Version":
r"""
Determine a version based on Darcs 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+)`.
"""
code, msg = _run_cmd("darcs status")
if code in [0, 1]:
dirty = msg != "No changes!"
else:
raise RuntimeError("Darcs returned code {}".format(code))

code, description = _run_cmd('darcs log --last 1')
if code == 0:
if not description:
commit = None
else:
commit = description.split()[1].strip()
else:
raise RuntimeError("Darcs returned code {}".format(code))

code, description = _run_cmd('darcs show tags')
if code == 0:
if not description:
return cls("0.0.0", post=0, dev=0, commit=commit, dirty=dirty)
tag = description.split()[0]
else:
raise RuntimeError("Darcs returned code {}".format(code))

code, description = _run_cmd('darcs log --from-tag {}'.format(tag))
if code == 0:
# The tag itself is in the list, so offset by 1.
distance = -1
for line in description.splitlines():
if line.startswith("patch "):
distance += 1
else:
raise RuntimeError("Darcs returned code {}".format(code))

base, pre = _match_version_pattern(pattern, tag)

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

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

@classmethod
def from_any_vcs(cls, pattern: str = None) -> "Version":
"""
Expand All @@ -325,13 +381,14 @@ def from_any_vcs(cls, pattern: str = None) -> "Version":
:param pattern: Regular expression matched against the version source.
The default value defers to the VCS-specific `from_` functions.
"""
vcs = _find_higher_dir(".git", ".hg")
vcs = _find_higher_dir(".git", ".hg", "_darcs")
if not vcs:
raise RuntimeError("Unable to detect version control system.")

callbacks = {
".git": cls.from_git,
".hg": cls.from_mercurial,
"_darcs": cls.from_darcs,
}

arguments = []
Expand Down
2 changes: 2 additions & 0 deletions dunamai/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Vcs(Enum):
Any = "any"
Git = "git"
Mercurial = "mercurial"
Darcs = "darcs"


class Style(Enum):
Expand Down Expand Up @@ -85,6 +86,7 @@ def from_vcs(
Vcs.Any: Version.from_any_vcs,
Vcs.Git: Version.from_git,
Vcs.Mercurial: Version.from_mercurial,
Vcs.Darcs: Version.from_darcs,
}

arguments = []
Expand Down
31 changes: 31 additions & 0 deletions tests/test_dunamai.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,37 @@ def test__version__from_mercurial(tmp_path):
assert from_any_vcs() == Version("0.1.0", post=1, dev=0, commit="abc")


@pytest.mark.skipif(shutil.which("darcs") is None, reason="Requires Darcs")
def test__version__from_darcs(tmp_path):
vcs = tmp_path / "dunamai-darcs"
vcs.mkdir()
run = make_run_callback(vcs)
from_vcs = make_from_callback(Version.from_darcs)

with chdir(vcs):
run("darcs 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('darcs add foo.txt')
run('darcs record -am "Initial commit"')
assert from_vcs() == Version("0.0.0", post=0, dev=0, commit="abc", dirty=False)

run("darcs tag v0.1.0")
assert from_vcs() == Version("0.1.0", commit="abc", dirty=False)
assert run("dunamai from darcs") == "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="abc", dirty=True)

run('darcs record -am "Second"')
assert from_vcs() == Version("0.1.0", post=1, dev=0, commit="abc")
assert from_any_vcs() == Version("0.1.0", post=1, dev=0, commit="abc")


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 @@ -10,6 +10,7 @@ def test__parse_args__from():
)
assert parse_args(["from", "git"]).vcs == "git"
assert parse_args(["from", "mercurial"]).vcs == "mercurial"
assert parse_args(["from", "darcs"]).vcs == "darcs"
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 03e2e07

Please sign in to comment.