-
-
Notifications
You must be signed in to change notification settings - Fork 97
Expand file tree
/
Copy pathgit_utils.py
More file actions
121 lines (106 loc) · 4.28 KB
/
git_utils.py
File metadata and controls
121 lines (106 loc) · 4.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# ************************************************
# Git Utilities for displaying commit information
# ************************************************
# This module provides utilities for getting git commit information
# to help with debugging and version tracking in Runestone books.
import os
import subprocess
from typing import Optional
def get_git_commit_hash() -> Optional[str]:
"""
Get the current git commit hash.
This function attempts to get the git commit hash using multiple methods:
1. From environment variable GIT_COMMIT_HASH (useful for CI/CD)
2. From git command if available
3. From .git/refs/heads/<branch> file if .git directory exists
Returns:
str: The git commit hash (short form - first 7 characters) or None if not available
"""
# Method 1: Check environment variable (useful for CI/CD environments)
commit_hash = os.environ.get('GIT_COMMIT_HASH')
if commit_hash:
return commit_hash[:7] # Return short hash
# Method 2: Try using git command
try:
result = subprocess.run(
['git', 'rev-parse', '--short', 'HEAD'],
capture_output=True,
text=True,
timeout=10
)
if result.returncode == 0:
return result.stdout.strip()
except (subprocess.SubprocessError, FileNotFoundError, subprocess.TimeoutExpired):
pass
# Method 3: Try reading from .git directory directly
try:
# Get the current branch
git_head_file = '.git/HEAD'
if os.path.exists(git_head_file):
with open(git_head_file, 'r') as f:
head_content = f.read().strip()
# If HEAD contains a reference to a branch
if head_content.startswith('ref: '):
branch_ref = head_content[5:] # Remove 'ref: ' prefix
branch_file = os.path.join('.git', branch_ref)
if os.path.exists(branch_file):
with open(branch_file, 'r') as f:
commit_hash = f.read().strip()
return commit_hash[:7] # Return short hash
else:
# HEAD contains the commit hash directly (detached HEAD)
return head_content[:7]
except (OSError, IOError):
pass
return None
def get_git_commit_info() -> dict:
"""
Get comprehensive git commit information.
Returns:
dict: Dictionary containing git information including:
- hash: commit hash (short)
- available: whether git info is available
- source: source of the information (env, git_cmd, git_file)
"""
commit_hash = None
source = None
# Try environment variable first
if os.environ.get('GIT_COMMIT_HASH'):
commit_hash = os.environ['GIT_COMMIT_HASH'][:7]
source = 'env'
else:
# Try git command
try:
result = subprocess.run(
['git', 'rev-parse', '--short', 'HEAD'],
capture_output=True,
text=True,
timeout=10
)
if result.returncode == 0:
commit_hash = result.stdout.strip()
source = 'git_cmd'
except (subprocess.SubprocessError, FileNotFoundError, subprocess.TimeoutExpired):
# Try reading from .git files
try:
git_head_file = '.git/HEAD'
if os.path.exists(git_head_file):
with open(git_head_file, 'r') as f:
head_content = f.read().strip()
if head_content.startswith('ref: '):
branch_ref = head_content[5:]
branch_file = os.path.join('.git', branch_ref)
if os.path.exists(branch_file):
with open(branch_file, 'r') as f:
commit_hash = f.read().strip()[:7]
source = 'git_file'
else:
commit_hash = head_content[:7]
source = 'git_file'
except (OSError, IOError):
pass
return {
'hash': commit_hash,
'available': commit_hash is not None,
'source': source
}