From 5ffe1a78b615184c1006838c95d8b602ae5574f1 Mon Sep 17 00:00:00 2001 From: James Gerity Date: Fri, 15 Dec 2023 23:47:15 -0500 Subject: [PATCH 1/8] version: retrieve commit hash for git worktrees --- sopel/builtins/version.py | 46 +++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index 536eaa83fd..4554b635fc 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -19,17 +19,55 @@ GIT_DIR = os.path.join(PROJECT_DIR, '.git') -def git_info(): - head = os.path.join(GIT_DIR, 'HEAD') +def _read_commit(gitdir: str, head: str) -> str | None: + """ + Given paths to ``.git/`` and ``HEAD``, determine the associated commit hash + """ + result = None + if os.path.isfile(head): with open(head) as h: head_loc = h.readline()[5:-1] # strip ref: and \n - head_file = os.path.join(GIT_DIR, head_loc) + head_file = os.path.join(gitdir, head_loc) if os.path.isfile(head_file): with open(head_file) as h: sha = h.readline() if sha: - return sha + result = sha + + return result + + +def _resolve_git_dirs(pth: str) -> tuple[str, str]: + """ + Resolve a ``.git`` path to its 'true' ``.git/`` and `HEAD` + + This helper is useful for dealing with the ``.git`` file stored in a + git worktree. + """ + # default to the old behavior: assume `pth` is a valid .git/ to begin with + gitdir = pth + head = os.path.join(pth, "HEAD") + + if os.path.isfile(pth): + # this may be a worktree, let's override the result properly if so + with open(pth, 'r') as f: + first, rest = next(f).strip().split(maxsplit=1) + if first == "gitdir:": + # line is "gitdir: /path/to/parentrepo/.git/worktrees/thispath" + gitdir = os.path.dirname(os.path.dirname(rest)) + head = os.path.join(rest, "HEAD") + # else: we can't make sense of this file, stick to the default + + return gitdir, head + + +def git_info() -> str | None: + """ + Determine the git commit hash of this Sopel, if applicable + """ + gitdir, head = _resolve_git_dirs(GIT_DIR) + return _read_commit(gitdir, head) @plugin.command('version') From 5212eff9623c8517eb905ff17a240e8d6567231d Mon Sep 17 00:00:00 2001 From: James Gerity Date: Sat, 19 Oct 2024 15:43:55 -0400 Subject: [PATCH 2/8] =?UTF-8?q?version:=20rename=20pth=20=E2=86=92=20path?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Florian Strzelecki --- sopel/builtins/version.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index 4554b635fc..720a7efde8 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -38,20 +38,18 @@ def _read_commit(gitdir: str, head: str) -> str | None: return result -def _resolve_git_dirs(pth: str) -> tuple[str, str]: - """ - Resolve a ``.git`` path to its 'true' ``.git/`` and `HEAD` +def _resolve_git_dirs(path: str) -> tuple[str, str]: This helper is useful for dealing with the ``.git`` file stored in a git worktree. """ - # default to the old behavior: assume `pth` is a valid .git/ to begin with - gitdir = pth - head = os.path.join(pth, "HEAD") + # default to the old behavior: assume `path` is a valid .git/ to begin with + gitdir = path + head = os.path.join(path, "HEAD") - if os.path.isfile(pth): + if os.path.isfile(path): # this may be a worktree, let's override the result properly if so - with open(pth, 'r') as f: + with open(path, 'r') as f: first, rest = next(f).strip().split(maxsplit=1) if first == "gitdir:": # line is "gitdir: /path/to/parentrepo/.git/worktrees/thispath" From 9992d1bc4a6e0e1f1133787474e5d23c6213ef89 Mon Sep 17 00:00:00 2001 From: James Gerity Date: Sat, 19 Oct 2024 15:47:12 -0400 Subject: [PATCH 3/8] verison: use correct docstring style Co-authored-by: Florian Strzelecki --- sopel/builtins/version.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index 720a7efde8..6834caae9f 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -39,6 +39,7 @@ def _read_commit(gitdir: str, head: str) -> str | None: def _resolve_git_dirs(path: str) -> tuple[str, str]: + """Resolve a ``.git`` path to its 'true' ``.git/`` and `HEAD` This helper is useful for dealing with the ``.git`` file stored in a git worktree. From 986ae9895143e833a4578223e10a10cb3584944d Mon Sep 17 00:00:00 2001 From: James Gerity Date: Sat, 19 Oct 2024 15:50:07 -0400 Subject: [PATCH 4/8] version: degrade quietly if git_info() causes OSError Co-authored-by: Florian Strzelecki --- sopel/builtins/version.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index 6834caae9f..1e206056d3 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -9,12 +9,16 @@ from __future__ import annotations import datetime +import logging import os import platform from sopel import __version__ as release, plugin +logger = logging.getLogger(__name__) + + PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) GIT_DIR = os.path.join(PROJECT_DIR, '.git') @@ -102,7 +106,12 @@ def version(bot, trigger): 'Sopel v%s' % release, 'Python: %s' % platform.python_version() ] - sha = git_info() + try: + sha = git_info() + except OSError: + logger.warning("Failed to retrieve git commit hash", exc_info=True) + sha = None + if sha: parts.append('Commit: %s' % sha) From 322857e47ac42b6eeb66fdd5dcf4a26829f81f04 Mon Sep 17 00:00:00 2001 From: James Gerity Date: Sat, 19 Oct 2024 17:44:15 -0400 Subject: [PATCH 5/8] version: describe params in docstring Co-authored-by: Florian Strzelecki --- sopel/builtins/version.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index 1e206056d3..5b5a74ee1d 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -24,8 +24,10 @@ def _read_commit(gitdir: str, head: str) -> str | None: - """ - Given paths to ``.git/`` and ``HEAD``, determine the associated commit hash + """Given paths to ``.git/`` and ``HEAD``, determine the associated commit hash + + :param gitdir: path to a ``.git/`` directory + :param head: path to ``HEAD`` file """ result = None @@ -47,6 +49,8 @@ def _resolve_git_dirs(path: str) -> tuple[str, str]: This helper is useful for dealing with the ``.git`` file stored in a git worktree. + + :param path: path to a .git directory or worktree reference file """ # default to the old behavior: assume `path` is a valid .git/ to begin with gitdir = path From aa885db998b686cadff69e72b8c7aed3af15bf57 Mon Sep 17 00:00:00 2001 From: James Gerity Date: Sat, 19 Oct 2024 21:34:53 -0400 Subject: [PATCH 6/8] version: tweak docstring --- sopel/builtins/version.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index 5b5a74ee1d..293d6161a1 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -70,8 +70,7 @@ def _resolve_git_dirs(path: str) -> tuple[str, str]: def git_info() -> str | None: - """ - Determine the git commit hash of this Sopel, if applicable + """Determine the git commit hash of this Sopel, if applicable """ gitdir, head = _resolve_git_dirs(GIT_DIR) return _read_commit(gitdir, head) From a37f8ed46d5b2b3c9799693cb1dfcdf4171a58ba Mon Sep 17 00:00:00 2001 From: James Gerity Date: Mon, 21 Oct 2024 11:52:43 -0400 Subject: [PATCH 7/8] version: rename git commit helper --- sopel/builtins/version.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index 293d6161a1..c4b88591d8 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -18,7 +18,6 @@ logger = logging.getLogger(__name__) - PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__))) GIT_DIR = os.path.join(PROJECT_DIR, '.git') @@ -69,7 +68,7 @@ def _resolve_git_dirs(path: str) -> tuple[str, str]: return gitdir, head -def git_info() -> str | None: +def sopel_git_commit() -> str | None: """Determine the git commit hash of this Sopel, if applicable """ gitdir, head = _resolve_git_dirs(GIT_DIR) @@ -110,7 +109,7 @@ def version(bot, trigger): 'Python: %s' % platform.python_version() ] try: - sha = git_info() + sha = sopel_git_commit() except OSError: logger.warning("Failed to retrieve git commit hash", exc_info=True) sha = None From bc8632246962b9f6c9d1258432aec18dbf7c55c3 Mon Sep 17 00:00:00 2001 From: James Gerity Date: Mon, 21 Oct 2024 11:53:47 -0400 Subject: [PATCH 8/8] Strip trailing newline --- sopel/builtins/version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sopel/builtins/version.py b/sopel/builtins/version.py index c4b88591d8..81b18c69db 100644 --- a/sopel/builtins/version.py +++ b/sopel/builtins/version.py @@ -36,7 +36,7 @@ def _read_commit(gitdir: str, head: str) -> str | None: head_file = os.path.join(gitdir, head_loc) if os.path.isfile(head_file): with open(head_file) as h: - sha = h.readline() + sha = h.readline().strip() if sha: result = sha