Skip to content

Commit 0cbdc49

Browse files
committed
feat: add git utils for getting git commit hash
The current method for getting the git commit hash is to evaluate git commands as part of hjson wildcard substitution. Presumably as a means of making it more generic and supporting other version control systems. However the opentitan HJSON builds up a markdown string containing a URL link to github. Then DVSim parses that string with a regex. Which couples the somewhat generic mechanism to an exact implementation. This commit adds some generic git utility functions to work directly with git from within DVSim and bypass HJSON calculated values. If we are going to be calling Git, I'd rather do that directly from DVSim, rather than some uncontrolled system call eval in HJSON. If we need to add flexibility to support different systems then we can add that in the future using a plugin system in DVSim and declaratively switching between version control system (i.e. git) and hosting solution (i.e. github) in the HJSON if required. The current solution is highly coupled and doesn't allow for extension. This solution is still git/github specific, but adds scope for later extension if required. It also removes the dependence on one more eval in the OpenTitan HJSON. Signed-off-by: James McCorrie <[email protected]>
1 parent d1189db commit 0cbdc49

File tree

4 files changed

+91
-7
lines changed

4 files changed

+91
-7
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ dependencies = [
1919
# Keep sorted
2020
"click>=8.1.7",
2121
"enlighten>=1.12.4",
22+
"gitpython>=3.1.45",
2223
"hjson>=3.1.0",
2324
"jinja2>=3.1.6",
2425
"logzero>=1.7.0",

src/dvsim/utils/git.py

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,39 @@
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
44

5-
"""Git utinity functions."""
5+
"""Git utility functions."""
66

7-
from dvsim.utils.subprocess import run_cmd
7+
import logging as log
8+
from pathlib import Path
89

9-
__all__ = ("git_commit_hash",)
10+
from git import Repo
1011

12+
__all__ = ("repo_root",)
1113

12-
def git_commit_hash() -> str:
14+
15+
def repo_root(path: Path) -> Path | None:
16+
"""Given a sub dir in a git repo provide the root path.
17+
18+
Where the provided path is not part of a repo then None is returned.
19+
"""
20+
if (path / ".git").exists():
21+
return path
22+
23+
for p in path.parents:
24+
if (p / ".git").exists():
25+
return p
26+
27+
return None
28+
29+
30+
def git_commit_hash(path: Path | None = None) -> str:
1331
"""Hash of the current git commit."""
14-
return run_cmd("git rev-parse HEAD")
32+
root = repo_root(path=path if path else Path.cwd())
33+
34+
if root is None:
35+
log.error("no git repo found at %s", root)
36+
raise ValueError
37+
38+
r = Repo(root)
39+
40+
return r.head.commit.hexsha

tests/utils/test_git.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Copyright lowRISC contributors (OpenTitan project).
2+
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
"""Test git helpers."""
6+
7+
from typing import TYPE_CHECKING
8+
9+
from git import Repo
10+
from hamcrest import assert_that, equal_to
11+
12+
from dvsim.utils.git import git_commit_hash, repo_root
13+
14+
if TYPE_CHECKING:
15+
from pathlib import Path
16+
17+
__all__ = ()
18+
19+
20+
class TestGit:
21+
"""Test git helpers."""
22+
23+
@staticmethod
24+
def test_repo_root(tmp_path: "Path") -> None:
25+
"""Test git repo root can be found."""
26+
repo_root_path = tmp_path / "repo"
27+
repo_root_path.mkdir()
28+
29+
Repo.init(path=repo_root_path)
30+
31+
# from the actual repo root
32+
assert_that(repo_root(path=repo_root_path), equal_to(repo_root_path))
33+
34+
# from the repo sub dir
35+
sub_dir_path = repo_root_path / "a"
36+
sub_dir_path.mkdir()
37+
assert_that(repo_root(path=sub_dir_path), equal_to(repo_root_path))
38+
39+
# from outside the repo
40+
assert_that(repo_root(path=tmp_path), equal_to(None))
41+
42+
@staticmethod
43+
def test_git_commit_hash(tmp_path: "Path") -> None:
44+
"""Test that the expected git commit sha is returned."""
45+
r = Repo.init(path=tmp_path)
46+
47+
file = tmp_path / "a"
48+
file.write_text("file to commit")
49+
r.index.add([file])
50+
r.index.commit("initial commit")
51+
52+
assert_that(
53+
git_commit_hash(tmp_path),
54+
equal_to(r.head.commit.hexsha),
55+
)

uv.lock

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)