@@ -31,7 +31,7 @@ class JiraPattern:
3131 making sure it gets compiled only once."""
3232
3333 __pattern = re .compile (
34- r"(?:GEOPY|GI|GA|GMS|VPem1D|VPem3D|VPmg|UBCGIF|LICMGR)-\d+"
34+ r"(?:\w*!)?\s*\S?\b((?: GEOPY|GI|GA|GMS|VPem1D|VPem3D|VPmg|UBCGIF|LICMGR|DEVOPS|QA )-\d+) "
3535 )
3636
3737 @staticmethod
@@ -41,8 +41,29 @@ def get():
4141
4242 # use re.match() rather than re.search() to enforce the JIRA reference to be at the beginning
4343 match = re .match (JiraPattern .get (), text .strip ())
44- return match .group (0 ) if match else ""
44+ return match .group (1 ) if match else ""
4545
46+ def get_message_prefix_bang (line : str ) -> str :
47+ """Capture the standard commit message prefix, if any, such as 'fixup!', 'amend!',
48+ etc.
49+
50+ :return: the standard commit message prefix if found, else empty string.
51+ """
52+ class BangPattern :
53+ """Internal class that encapsulates the regular expression for the Bnag pattern,
54+ making sure it gets compiled only once."""
55+
56+ __pattern = re .compile (
57+ r"(\w*!\s)"
58+ )
59+
60+ @staticmethod
61+ def get ():
62+ """:return: the compiled regular expression for the JIRA pattern"""
63+ return BangPattern .__pattern
64+ # use re.match() rather than re.search() to enforce pattern at the beginning
65+ match = re .match (BangPattern .get (), line .strip ())
66+ return match .group (1 ) if match else ""
4667
4768def get_branch_name () -> str | None :
4869 """:return: the name of the current branch"""
@@ -51,6 +72,7 @@ def get_branch_name() -> str | None:
5172 shlex .split ("git branch --list" ),
5273 stdout = subprocess .PIPE ,
5374 text = True ,
75+ check = False
5476 )
5577
5678 if git_proc .returncode != 0 :
@@ -100,18 +122,20 @@ def check_commit_message(filepath: str) -> tuple[bool, str]:
100122
101123 message_jira_id = ""
102124 first_line = None
103- with open (filepath ) as message_file :
125+ with open (filepath , encoding = "utf-8" ) as message_file :
104126 for line in message_file :
105127 if not line .startswith ("#" ) and len (line .strip ()) > 0 :
106128 # test only the first non-comment line that is not empty
107129 # (should we reject messages with empty first line?)
108- first_line = line
130+ first_line = line .strip ()
131+ prefix_bang = get_message_prefix_bang (first_line )
132+ first_line = first_line [len (prefix_bang ) :].strip ()
109133 message_jira_id = get_jira_id (first_line )
110134 break
111135 assert first_line is not None
112136
113137 if not branch_jira_id and not (
114- message_jira_id or first_line .strip (). lower ().startswith ("merge" )
138+ message_jira_id or ( not prefix_bang and first_line .lower ().startswith ("merge" ) )
115139 ):
116140 return (
117141 False ,
@@ -121,7 +145,8 @@ def check_commit_message(filepath: str) -> tuple[bool, str]:
121145 if branch_jira_id and message_jira_id and branch_jira_id != message_jira_id :
122146 return (
123147 False ,
124- f"Different JIRA ID in commit message { message_jira_id } and in branch name { branch_jira_id } ." ,
148+ f"Different JIRA ID in commit message { message_jira_id } "
149+ f"and in branch name { branch_jira_id } ." ,
125150 )
126151
127152 stripped_message_line = ""
@@ -176,24 +201,31 @@ def prepare_commit_msg(filepath: str, source: str | None = None) -> None:
176201 if source not in [None , "message" , "template" ]:
177202 return
178203
204+ prefix_bang = ""
179205 with open (
180206 filepath ,
181207 "r+" ,
208+ encoding = "utf-8"
182209 ) as message_file :
183210 message_has_jira_id = False
184211 message_lines = message_file .readlines ()
185212 for line_index , line_content in enumerate (message_lines ):
186213 if not line_content .startswith ("#" ):
187214 # test only the first non-comment line
215+ line_content = line_content .strip ()
216+ prefix_bang = get_message_prefix_bang (line_content )
217+ line_content = line_content [len (prefix_bang ):].strip ()
188218 message_jira_id = get_jira_id (line_content )
189219 if not message_jira_id :
190- message_lines [line_index ] = branch_jira_id + ": " + line_content
220+ message_lines [line_index ] = (
221+ f"{ prefix_bang } [{ branch_jira_id } ] { line_content } \n "
222+ )
191223 message_has_jira_id = True
192224 break
193225
194226 if not message_has_jira_id :
195227 # message is empty or all lines are comments: insert JIRA ID at the very beginning
196- message_lines .insert (0 , branch_jira_id + ": " )
228+ message_lines .insert (0 , f" { prefix_bang } [ { branch_jira_id } ] \n " )
197229
198230 message_file .seek (0 , 0 )
199231 message_file .write ("" .join (message_lines ))
0 commit comments