Skip to content

Commit

Permalink
Add support for .hg_archival.txt files
Browse files Browse the repository at this point in the history
  • Loading branch information
mtkennerly committed Nov 6, 2022
1 parent 614abeb commit 17d50dc
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Unreleased

* Added a `strict` option to prevent falling back to `0.0.0` when there are no tags.
* Added support for `.hg_archival.txt` files (created by `hg archive`).

## v1.13.2 (2022-10-14)

Expand Down
64 changes: 64 additions & 0 deletions dunamai/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,23 @@ def _detect_vcs(expected_vcs: Optional[Vcs] = None) -> Vcs:
raise RuntimeError("Unable to detect version control system.")


def _find_higher_file(name: str, limit: Optional[str] = None, start: Path = None) -> Optional[Path]:
"""
:param name: Bare name of a file we'd like to find.
:param limit: Give up if we find a file/folder with this name.
:param start: Begin recursing from this folder (default: `.`).
"""

if start is None:
start = Path.cwd()
for level in [start, *start.parents]:
if (level / name).is_file():
return level / name
if limit is not None and (level / limit).exists():
return None
return None


class _GitRefInfo:
def __init__(
self, ref: str, commit: str, creatordate: str, committerdate: str, taggerdate: str
Expand Down Expand Up @@ -933,6 +950,53 @@ def from_mercurial(
:param full_commit: Get the full commit hash instead of the short form.
:param strict: When there are no tags, fail instead of falling back to 0.0.0.
"""
archival = _find_higher_file(".hg_archival.txt", ".hg")
if archival is not None:
content = archival.read_text("utf8")
data = {}
for line in content.splitlines():
parts = line.split(":", 1)
if len(parts) != 2:
continue
data[parts[0].strip()] = parts[1].strip()

tag = data.get("latesttag")
# The distance is 1 on a new repo or on a tagged commit.
distance = int(data.get("latesttagdistance", 1)) - 1
commit = data.get("node")
branch = data.get("branch")

if tag is None or tag == "null":
return cls._fallback(strict, distance=distance, commit=commit, branch=branch)

all_tags_file = _find_higher_file(".hgtags", ".hg")
if all_tags_file is None:
all_tags = [tag]
else:
all_tags = []
all_tags_content = all_tags_file.read_text("utf8")
for line in reversed(all_tags_content.splitlines()):
parts = line.split(" ", 1)
if len(parts) != 2:
continue
all_tags.append(parts[1])

tag, base, stage, unmatched, tagged_metadata, epoch = _match_version_pattern(
pattern, all_tags, latest_tag
)
version = cls(
base,
stage=stage,
distance=distance,
commit=commit,
tagged_metadata=tagged_metadata,
epoch=epoch,
branch=branch,
)
version._matched_tag = tag
version._newer_unmatched_tags = unmatched
return version

_detect_vcs(Vcs.Mercurial)

code, msg = _run_cmd("hg summary")
Expand Down
6 changes: 6 additions & 0 deletions tests/integration/archival-hg-tagged/.hg_archival.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
repo: 25e474af1332ed4fff9351c70ef8f36352c013f2
node: cf36273384e558411364a3a973aaa0cc08e48aea
branch: default
latesttag: foo bar
latesttagdistance: 1
changessincelatesttag: 1
3 changes: 3 additions & 0 deletions tests/integration/archival-hg-tagged/.hgtags
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
d80ce21ea5d88b577ee32661ffd3a5b3834f14e0 v0.1.0
5255faf9dfb276bbe189562e9a1194f43506c21c v0.1.1
1662f75d4df8f05506c2bc9d9801f80d879bf3f0 foo bar
6 changes: 6 additions & 0 deletions tests/integration/archival-hg-untagged/.hg_archival.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
repo: 25e474af1332ed4fff9351c70ef8f36352c013f2
node: 25e474af1332ed4fff9351c70ef8f36352c013f2
branch: default
latesttag: null
latesttagdistance: 1
changessincelatesttag: 1
30 changes: 30 additions & 0 deletions tests/integration/test_dunamai.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ def avoid_identical_ref_timestamps() -> None:
time.sleep(1.2)


REPO = Path(__file__).parent.parent.parent


@contextmanager
def chdir(where: Path) -> Iterator[None]:
start = Path.cwd()
Expand Down Expand Up @@ -426,6 +429,33 @@ def test__version__from_mercurial(tmp_path) -> None:
assert from_vcs(latest_tag=True) == Version("0.1.0", dirty=False, branch=b)


def test__version__from_mercurial__archival_untagged() -> None:
with chdir(REPO / "tests" / "integration" / "archival-hg-untagged"):
detected = Version.from_mercurial()
assert detected == Version(
"0.0.0",
branch="default",
commit="25e474af1332ed4fff9351c70ef8f36352c013f2",
)
assert detected._matched_tag is None
assert detected._newer_unmatched_tags is None

with pytest.raises(RuntimeError):
Version.from_mercurial(strict=True)


def test__version__from_mercurial__archival_tagged() -> None:
with chdir(REPO / "tests" / "integration" / "archival-hg-tagged"):
detected = Version.from_mercurial()
assert detected == Version(
"0.1.1",
branch="default",
commit="cf36273384e558411364a3a973aaa0cc08e48aea",
)
assert detected._matched_tag == "v0.1.1"
assert detected._newer_unmatched_tags == ["foo bar"]


@pytest.mark.skipif(shutil.which("darcs") is None, reason="Requires Darcs")
def test__version__from_darcs(tmp_path) -> None:
vcs = tmp_path / "dunamai-darcs"
Expand Down

0 comments on commit 17d50dc

Please sign in to comment.