@@ -37,91 +37,34 @@ def __init__(self, cmd):
3737 )
3838
3939
40- class GitBase :
41- """
42- Base class for gitbdiff functionality
43- """
40+ class GitBDiff :
41+ """Class which generates a branch diff."""
42+
43+ # Name of primary branch - default is main
44+ primary_branch = "main"
45+
46+ # Match hex commit IDs
47+ _hash_pattern = re .compile (r"^\s*([0-9a-f]{40})\s*$" )
4448
4549 # Match branch names. This should catch all valid names but may
4650 # also some invalid names through. This should matter given that
4751 # it is being used to match git command output. For a complete
4852 # overview of the naming scheme, see man git check-ref-format
4953 _branch_pattern = re .compile (r"^\s*([^\s~\^\:\?\*\[]+[^.])\s*$" )
5054
51- # Text returned if in a detached head
52- detached_head_reference = "detched_head_state"
53-
5455 def __init__ (self , parent = None , repo = None ):
56+ self .parent = parent or self .primary_branch
57+
5558 if repo is None :
5659 self ._repo = None
5760 else :
5861 self ._repo = Path (repo )
5962 if not self ._repo .is_dir ():
6063 raise GitBDiffError (f"{ repo } is not a directory" )
6164
62- def get_branch_name (self ):
63- """Get the name of the current branch."""
64- result = None
65- for line in self .run_git (["branch" , "--show-current" ]):
66- if m := self ._branch_pattern .match (line ):
67- result = m .group (1 )
68- break
69- else :
70- # Check for being in a Detached Head state
71- for line in self .run_git (["branch" ]):
72- if "HEAD detached" in line :
73- result = self .detached_head_reference
74- break
75- else :
76- raise GitBDiffError ("unable to get branch name" )
77- return result
78-
79- def run_git (self , args ):
80- """Run a git command and yield the output."""
81-
82- if not isinstance (args , list ):
83- raise TypeError ("args must be a list" )
84- cmd = ["git" ] + args
85-
86- # Run the the command in the repo directory, capture the
87- # output, and check for errors. The build in error check is
88- # not used to allow specific git errors to be treated more
89- # precisely
90- proc = subprocess .run (
91- cmd , capture_output = True , check = False , shell = False , cwd = self ._repo
92- )
93-
94- for line in proc .stderr .decode ("utf-8" ).split ("\n " ):
95- if line .startswith ("fatal: not a git repository" ):
96- raise GitBDiffNotGit (cmd )
97- if line .startswith ("fatal: " ):
98- raise GitBDiffError (line [7 :])
99-
100- if proc .returncode != 0 :
101- raise GitBDiffError (f"command returned { proc .returncode } " )
102-
103- yield from proc .stdout .decode ("utf-8" ).split ("\n " )
104-
105-
106- class GitBDiff (GitBase ):
107- """Class which generates a branch diff."""
108-
109- # Name of primary branch - default is main
110- primary_branch = "main"
111-
112- # Match hex commit IDs
113- _hash_pattern = re .compile (r"^\s*([0-9a-f]{40})\s*$" )
114-
115- def __init__ (self , parent = None , repo = None ):
116- self .parent = parent or self .primary_branch
117-
118- super ().__init__ (parent , repo )
119-
12065 self .ancestor = self .get_branch_point ()
12166 self .current = self .get_latest_commit ()
12267 self .branch = self .get_branch_name ()
123- if self .branch == self .detached_head_reference :
124- raise GitBDiffError ("Can't get a diff for a repo in detached head state" )
12568
12669 def get_branch_point (self ):
12770 """Get the branch point from the parent repo.
@@ -153,6 +96,17 @@ def get_latest_commit(self):
15396 raise GitBDiffError ("current revision not found" )
15497 return result
15598
99+ def get_branch_name (self ):
100+ """Get the name of the current branch."""
101+ result = None
102+ for line in self .run_git (["branch" , "--show-current" ]):
103+ if m := self ._branch_pattern .match (line ):
104+ result = m .group (1 )
105+ break
106+ else :
107+ raise GitBDiffError ("unable to get branch name" )
108+ return result
109+
156110 @property
157111 def is_branch (self ):
158112 """Whether this is a branch or main."""
@@ -172,24 +126,28 @@ def files(self):
172126 if line != "" :
173127 yield line
174128
129+ def run_git (self , args ):
130+ """Run a git command and yield the output."""
175131
176- class GitInfo (GitBase ):
177- """
178- Class to contain info of a git repo
179- """
132+ if not isinstance (args , list ):
133+ raise TypeError ("args must be a list" )
134+ cmd = ["git" ] + args
180135
181- def __init__ (self , repo = None ):
182- super ().__init__ (repo = repo )
136+ # Run the the command in the repo directory, capture the
137+ # output, and check for errors. The build in error check is
138+ # not used to allow specific git errors to be treated more
139+ # precisely
140+ proc = subprocess .run (
141+ cmd , capture_output = True , check = False , shell = False , cwd = self ._repo
142+ )
183143
184- self .branch = self .get_branch_name ()
144+ for line in proc .stderr .decode ("utf-8" ).split ("\n " ):
145+ if line .startswith ("fatal: not a git repository" ):
146+ raise GitBDiffNotGit (cmd )
147+ if line .startswith ("fatal: " ):
148+ raise GitBDiffError (line [7 :])
185149
186- def is_main (self ):
187- """
188- Returns true if branch matches a main-like branch name as defined below
189- Count detached head as main-like as we cannot get a diff for this
190- """
150+ if proc .returncode != 0 :
151+ raise GitBDiffError (f"command returned { proc .returncode } " )
191152
192- main_like = ("main" , "stable" , "trunk" , "master" , self .detached_head_reference )
193- if self .branch in main_like :
194- return True
195- return False
153+ yield from proc .stdout .decode ("utf-8" ).split ("\n " )
0 commit comments