11from __future__ import annotations
22
33import os
4- from enum import Enum
5- from os import linesep
64from pathlib import Path
75from tempfile import NamedTemporaryFile
86
97from commitizen import cmd , out
108from commitizen .exceptions import GitCommandError
119
12- UNIX_EOL = "\n "
13- WINDOWS_EOL = "\r \n "
14-
15-
16- class EOLTypes (Enum ):
17- """The EOL type from `git config core.eol`."""
18-
19- LF = "lf"
20- CRLF = "crlf"
21- NATIVE = "native"
22-
23- def get_eol_for_open (self ) -> str :
24- """Get the EOL character for `open()`."""
25- map = {
26- EOLTypes .CRLF : WINDOWS_EOL ,
27- EOLTypes .LF : UNIX_EOL ,
28- EOLTypes .NATIVE : linesep ,
29- }
30-
31- return map [self ]
10+ _UNIX_EOL = "\n "
11+ _WINDOWS_EOL = "\r \n "
3212
3313
3414class GitObject :
@@ -37,9 +17,7 @@ class GitObject:
3717 date : str
3818
3919 def __eq__ (self , other ) -> bool :
40- if not hasattr (other , "rev" ):
41- return False
42- return self .rev == other .rev # type: ignore
20+ return hasattr (other , "rev" ) and self .rev == other .rev
4321
4422
4523class GitCommit (GitObject ):
@@ -63,6 +41,20 @@ def __init__(
6341 def message (self ):
6442 return f"{ self .title } \n \n { self .body } " .strip ()
6543
44+ @classmethod
45+ def from_rev_and_commit (cls , rev_and_commit : str ) -> GitCommit :
46+ rev , parents , title , author , author_email , * body_list = rev_and_commit .split (
47+ "\n "
48+ )
49+ return cls (
50+ rev = rev .strip (),
51+ title = title .strip (),
52+ body = "\n " .join (body_list ).strip (),
53+ author = author ,
54+ author_email = author_email ,
55+ parents = [p for p in parents .strip ().split (" " ) if p ],
56+ )
57+
6658 def __repr__ (self ):
6759 return f"{ self .title } ({ self .rev } )"
6860
@@ -101,13 +93,11 @@ def tag(
10193 # according to https://git-scm.com/book/en/v2/Git-Basics-Tagging,
10294 # we're not able to create lightweight tag with message.
10395 # by adding message, we make it a annotated tags
104- c = cmd .run (f'git tag { _opt } "{ tag if _opt == "" or msg is None else msg } "' )
105- return c
96+ return cmd .run (f'git tag { _opt } "{ tag if _opt == "" or msg is None else msg } "' )
10697
10798
10899def add (* args : str ) -> cmd .Command :
109- c = cmd .run (f"git add { ' ' .join (args )} " )
110- return c
100+ return cmd .run (f"git add { ' ' .join (args )} " )
111101
112102
113103def commit (
@@ -140,24 +130,10 @@ def get_commits(
140130) -> list [GitCommit ]:
141131 """Get the commits between start and end."""
142132 git_log_entries = _get_log_as_str_list (start , end , args )
143- git_commits = []
144- for rev_and_commit in git_log_entries :
145- if not rev_and_commit :
146- continue
147- rev , parents , title , author , author_email , * body_list = rev_and_commit .split (
148- "\n "
149- )
150- if rev_and_commit :
151- git_commit = GitCommit (
152- rev = rev .strip (),
153- title = title .strip (),
154- body = "\n " .join (body_list ).strip (),
155- author = author ,
156- author_email = author_email ,
157- parents = [p for p in parents .strip ().split (" " ) if p ],
158- )
159- git_commits .append (git_commit )
160- return git_commits
133+ return [
134+ GitCommit .from_rev_and_commit (rev_and_commit )
135+ for rev_and_commit in filter (None , git_log_entries )
136+ ]
161137
162138
163139def get_filenames_in_commit (git_reference : str = "" ):
@@ -170,8 +146,7 @@ def get_filenames_in_commit(git_reference: str = ""):
170146 c = cmd .run (f"git show --name-only --pretty=format: { git_reference } " )
171147 if c .return_code == 0 :
172148 return c .out .strip ().split ("\n " )
173- else :
174- raise GitCommandError (c .err )
149+ raise GitCommandError (c .err )
175150
176151
177152def get_tags (
@@ -197,16 +172,11 @@ def get_tags(
197172 if c .err :
198173 out .warn (f"Attempting to proceed after: { c .err } " )
199174
200- if not c .out :
201- return []
202-
203- git_tags = [
175+ return [
204176 GitTag .from_line (line = line , inner_delimiter = inner_delimiter )
205177 for line in c .out .split ("\n " )[:- 1 ]
206178 ]
207179
208- return git_tags
209-
210180
211181def tag_exist (tag : str ) -> bool :
212182 c = cmd .run (f"git tag --list { tag } " )
@@ -231,18 +201,18 @@ def get_tag_message(tag: str) -> str | None:
231201 return c .out .strip ()
232202
233203
234- def get_tag_names () -> list [str | None ]:
204+ def get_tag_names () -> list [str ]:
235205 c = cmd .run ("git tag --list" )
236206 if c .err :
237207 return []
238- return [ tag .strip () for tag in c .out .split ("\n " ) if tag . strip ()]
208+ return list ( filter ( None , ( tag .strip () for tag in c .out .split ("\n " ))))
239209
240210
241211def find_git_project_root () -> Path | None :
242212 c = cmd .run ("git rev-parse --show-toplevel" )
243- if not c .err :
244- return Path ( c . out . strip ())
245- return None
213+ if c .err :
214+ return None
215+ return Path ( c . out . strip ())
246216
247217
248218def is_staging_clean () -> bool :
@@ -253,32 +223,19 @@ def is_staging_clean() -> bool:
253223
254224def is_git_project () -> bool :
255225 c = cmd .run ("git rev-parse --is-inside-work-tree" )
256- if c .out .strip () == "true" :
257- return True
258- return False
226+ return c .out .strip () == "true"
259227
260228
261- def get_eol_style () -> EOLTypes :
229+ def get_eol_for_open () -> str :
230+ # See: https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreeol
262231 c = cmd .run ("git config core.eol" )
263232 eol = c .out .strip ().lower ()
264233
265- # We enumerate the EOL types of the response of
266- # `git config core.eol`, and map it to our enumration EOLTypes.
267- #
268- # It is just like the variant of the "match" syntax.
269- map = {
270- "lf" : EOLTypes .LF ,
271- "crlf" : EOLTypes .CRLF ,
272- "native" : EOLTypes .NATIVE ,
273- }
274-
275- # If the response of `git config core.eol` is in the map:
276- if eol in map :
277- return map [eol ]
278- else :
279- # The default value is "native".
280- # https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreeol
281- return map ["native" ]
234+ if eol == "lf" :
235+ return _UNIX_EOL
236+ if eol == "crlf" :
237+ return _WINDOWS_EOL
238+ return os .linesep
282239
283240
284241def get_core_editor () -> str | None :
@@ -288,22 +245,18 @@ def get_core_editor() -> str | None:
288245 return None
289246
290247
291- def smart_open (* args , ** kargs ):
248+ def smart_open (* args , ** kwargs ):
292249 """Open a file with the EOL style determined from Git."""
293- return open (* args , newline = get_eol_style (). get_eol_for_open (), ** kargs )
250+ return open (* args , newline = get_eol_for_open (), ** kwargs )
294251
295252
296253def _get_log_as_str_list (start : str | None , end : str , args : str ) -> list [str ]:
297254 """Get string representation of each log entry"""
298255 delimiter = "----------commit-delimiter----------"
299256 log_format : str = "%H%n%P%n%s%n%an%n%ae%n%b"
300- git_log_cmd = (
301- f"git -c log.showSignature=False log --pretty={ log_format } { delimiter } { args } "
302- )
303- if start :
304- command = f"{ git_log_cmd } { start } ..{ end } "
305- else :
306- command = f"{ git_log_cmd } { end } "
257+ command_range = f"{ start } ..{ end } " if start else end
258+ command = f"git -c log.showSignature=False log --pretty={ log_format } { delimiter } { args } { command_range } "
259+
307260 c = cmd .run (command )
308261 if c .return_code != 0 :
309262 raise GitCommandError (c .err )
0 commit comments