1717import sys
1818from typing import List
1919
20- from .commitlint import check_commit_message
21- from .messages import COMMIT_SUCCESSFUL
20+ from .commitlint import check_commit_message , remove_comments
21+ from .exceptions import CommitlintException
22+ from .git_helpers import get_commit_message_of_hash , get_commit_messages_of_hash_range
23+ from .messages import VALIDATION_SUCCESSFUL
2224
2325
2426def get_args () -> argparse .Namespace :
@@ -34,56 +36,130 @@ def get_args() -> argparse.Namespace:
3436 parser = argparse .ArgumentParser (
3537 description = "Check if a commit message follows the conventional commit format."
3638 )
37- parser .add_argument (
39+
40+ # for commit message check
41+ group = parser .add_mutually_exclusive_group (required = True )
42+ group .add_argument (
3843 "commit_message" , nargs = "?" , type = str , help = "The commit message to be checked."
3944 )
40- parser .add_argument (
45+ group .add_argument (
4146 "--file" , type = str , help = "Path to a file containing the commit message."
4247 )
48+ group .add_argument ("--hash" , type = str , help = "Commit hash" )
49+ group .add_argument ("--from-hash" , type = str , help = "From commit hash" )
50+ # --to-hash is optional
51+ parser .add_argument ("--to-hash" , type = str , help = "To commit hash" , default = "HEAD" )
4352
53+ # parsing args
4454 args = parser .parse_args ()
4555
46- if not args .file and not args .commit_message :
47- parser .error ("Please provide either a commit message or a file." )
48-
4956 return args
5057
5158
52- def _show_errors (errors : List [str ]) -> None :
59+ def _show_errors (commit_message : str , errors : List [str ]) -> None :
5360 """
5461 Display a formatted error message for a list of errors.
5562
5663 Args:
5764 errors (List[str]): A list of error messages to be displayed.
65+ """
66+ error_count = len (errors )
67+ commit_message = remove_comments (commit_message )
5868
59- Returns:
60- None
69+ sys .stderr .write (
70+ f"⧗ Input:\n { commit_message } \n \n ✖ Found { error_count } error(s).\n \n "
71+ )
72+ for index , error in enumerate (errors ):
73+ end_char = "" if index == error_count - 1 else "\n "
74+ sys .stderr .write (f"- { error } \n { end_char } " )
75+
76+
77+ def _get_commit_message_from_file (filepath : str ) -> str :
6178 """
62- sys .stderr .write (f"✖ Found { len (errors )} errors.\n \n " )
63- for error in errors :
64- sys .stderr .write (f"- { error } \n \n " )
79+ Reads and returns the commit message from the specified file.
6580
81+ Args:
82+ filepath (str): The path to the file containing the commit message.
6683
67- def main () -> None :
84+ Returns:
85+ str: The commit message read from the file.
86+
87+ Raises:
88+ FileNotFoundError: If the specified file does not exist.
89+ IOError: If there is an issue reading the file.
6890 """
69- Main function for cli to check a commit message.
91+ abs_filepath = os .path .abspath (filepath )
92+ with open (abs_filepath , encoding = "utf-8" ) as commit_message_file :
93+ commit_message = commit_message_file .read ().strip ()
94+ return commit_message
95+
96+
97+ def _handle_commit_message (commit_message : str ) -> None :
7098 """
71- args = get_args ()
99+ Handles a single commit message, checks its validity, and prints the result.
72100
73- if args .file :
74- commit_message_filepath = os .path .abspath (args .file )
75- with open (commit_message_filepath , encoding = "utf-8" ) as commit_message_file :
76- commit_message = commit_message_file .read ().strip ()
77- else :
78- commit_message = args .commit_message .strip ()
101+ Args:
102+ commit_message (str): The commit message to be handled.
79103
104+ Raises:
105+ SystemExit: If the commit message is invalid.
106+ """
80107 success , errors = check_commit_message (commit_message )
81108
82109 if success :
83- sys .stdout .write (f"{ COMMIT_SUCCESSFUL } \n " )
84- sys .exit (0 )
110+ sys .stdout .write (f"{ VALIDATION_SUCCESSFUL } \n " )
85111 else :
86- _show_errors (errors )
112+ _show_errors (commit_message , errors )
113+ sys .exit (1 )
114+
115+
116+ def _handle_multiple_commit_messages (commit_messages : List [str ]) -> None :
117+ """
118+ Handles multiple commit messages, checks their validity, and prints the result.
119+
120+ Args:
121+ commit_messages (List[str]): List of commit messages to be handled.
122+
123+ Raises:
124+ SystemExit: If any of the commit messages is invalid.
125+ """
126+ has_error = False
127+ for commit_message in commit_messages :
128+ success , errors = check_commit_message (commit_message )
129+ if not success :
130+ has_error = True
131+ _show_errors (commit_message , errors )
132+ sys .stderr .write ("\n " )
133+
134+ if has_error :
135+ sys .exit (1 )
136+ else :
137+ sys .stdout .write (f"{ VALIDATION_SUCCESSFUL } \n " )
138+
139+
140+ def main () -> None :
141+ """
142+ Main function for cli to check a commit message.
143+ """
144+ args = get_args ()
145+
146+ try :
147+ if args .file :
148+ commit_message = _get_commit_message_from_file (args .file )
149+ _handle_commit_message (commit_message )
150+ elif args .hash :
151+ commit_message = get_commit_message_of_hash (args .hash )
152+ _handle_commit_message (commit_message )
153+ elif args .from_hash :
154+ commit_messages = get_commit_messages_of_hash_range (
155+ args .from_hash , args .to_hash
156+ )
157+ _handle_multiple_commit_messages (commit_messages )
158+ else :
159+ commit_message = args .commit_message .strip ()
160+ _handle_commit_message (commit_message )
161+ except CommitlintException as ex :
162+ sys .stderr .write (f"{ ex } \n " )
87163 sys .exit (1 )
88164
89165
0 commit comments