Coverage for langsmith/env/_git.py: 22%

27 statements  

« prev     ^ index     » next       coverage.py v7.10.1, created at 2025-12-11 16:15 -0800

1"""Fetch information about any current git repo.""" 

2 

3import functools 

4import logging 

5import subprocess 

6from typing import List, Optional, TypeVar 

7 

8from typing_extensions import TypedDict 

9 

10logger = logging.getLogger(__name__) 

11 

12T = TypeVar("T") 

13 

14 

15def exec_git(command: List[str]) -> Optional[str]: 

16 try: 

17 return subprocess.check_output( 

18 ["git"] + command, encoding="utf-8", stderr=subprocess.DEVNULL 

19 ).strip() 

20 except BaseException: 

21 return None 

22 

23 

24class GitInfo(TypedDict, total=False): 

25 repo_name: Optional[str] 

26 remote_url: Optional[str] 

27 commit: Optional[str] 

28 branch: Optional[str] 

29 author_name: Optional[str] 

30 author_email: Optional[str] 

31 commit_time: Optional[str] 

32 dirty: Optional[bool] 

33 tags: Optional[str] 

34 

35 

36@functools.lru_cache(maxsize=1) 

37def get_git_info(remote: str = "origin") -> GitInfo: 

38 """Get information about the git repository.""" 

39 if not exec_git(["rev-parse", "--is-inside-work-tree"]): 

40 return GitInfo( 

41 remote_url=None, 

42 commit=None, 

43 branch=None, 

44 author_name=None, 

45 author_email=None, 

46 commit_time=None, 

47 dirty=None, 

48 tags=None, 

49 repo_name=None, 

50 ) 

51 

52 return { 

53 "remote_url": exec_git(["remote", "get-url", remote]), 

54 "commit": exec_git(["rev-parse", "HEAD"]), 

55 "commit_time": exec_git(["log", "-1", "--format=%ct"]), 

56 "branch": exec_git(["rev-parse", "--abbrev-ref", "HEAD"]), 

57 "tags": exec_git( 

58 ["describe", "--tags", "--exact-match", "--always", "--dirty"] 

59 ), 

60 "dirty": exec_git(["status", "--porcelain"]) != "", 

61 "author_name": exec_git(["log", "-1", "--format=%an"]), 

62 "author_email": exec_git(["log", "-1", "--format=%ae"]), 

63 "repo_name": (exec_git(["rev-parse", "--show-toplevel"]) or "").split("/")[-1], 

64 }