22
33import os
44import shutil
5- from typing import Any
65
76import questionary
87import yaml
1413from commitizen .defaults import DEFAULT_SETTINGS , config_files
1514from commitizen .exceptions import InitFailedError , NoAnswersError
1615from commitizen .git import get_latest_tag_name , get_tag_names , smart_open
17- from commitizen .version_schemes import KNOWN_SCHEMES , Version , get_version_scheme
16+ from commitizen .version_schemes import (
17+ KNOWN_SCHEMES ,
18+ Version ,
19+ VersionScheme ,
20+ get_version_scheme ,
21+ )
1822
1923
2024class ProjectInfo :
@@ -63,16 +67,6 @@ def is_npm_package(self) -> bool:
6367 def is_php_composer (self ) -> bool :
6468 return os .path .isfile ("composer.json" )
6569
66- @property
67- def latest_tag (self ) -> str | None :
68- return get_latest_tag_name ()
69-
70- def tags (self ) -> list | None :
71- """Not a property, only use if necessary"""
72- if self .latest_tag is None :
73- return None
74- return get_tag_names ()
75-
7670 @property
7771 def is_pre_commit_installed (self ) -> bool :
7872 return bool (shutil .which ("pre-commit" ))
@@ -113,98 +107,79 @@ def __call__(self):
113107 except KeyboardInterrupt :
114108 raise InitFailedError ("Stopped by user" )
115109
116- # Initialize configuration
117- if "toml" in config_path :
118- self .config = TomlConfig (data = "" , path = config_path )
119- elif "json" in config_path :
120- self .config = JsonConfig (data = "{}" , path = config_path )
121- elif "yaml" in config_path :
122- self .config = YAMLConfig (data = "" , path = config_path )
123- values_to_add = {}
124- values_to_add ["name" ] = cz_name
125- values_to_add ["tag_format" ] = tag_format
126- values_to_add ["version_scheme" ] = version_scheme
127-
128- if version_provider == "commitizen" :
129- values_to_add ["version" ] = version .public
130- else :
131- values_to_add ["version_provider" ] = version_provider
110+ self ._init_config (config_path )
132111
133- if update_changelog_on_bump :
134- values_to_add ["update_changelog_on_bump" ] = update_changelog_on_bump
112+ self ._init_pre_commit_hook ()
135113
136- if major_version_zero :
137- values_to_add ["major_version_zero" ] = major_version_zero
138-
139- # Collect hook data
140- hook_types = questionary .checkbox (
141- "What types of pre-commit hook you want to install? (Leave blank if you don't want to install)" ,
142- choices = [
143- questionary .Choice ("commit-msg" , checked = False ),
144- questionary .Choice ("pre-push" , checked = False ),
145- ],
146- ).unsafe_ask ()
147- if hook_types :
148- try :
149- self ._install_pre_commit_hook (hook_types )
150- except InitFailedError as e :
151- raise InitFailedError (f"Failed to install pre-commit hook.\n { e } " )
152-
153- # Create and initialize config
154114 self .config .init_empty_config_content ()
155- self ._update_config_file (values_to_add )
115+ self ._update_config_file (
116+ version_provider ,
117+ version ,
118+ name = cz_name ,
119+ tag_format = tag_format ,
120+ version_scheme = version_scheme ,
121+ update_changelog_on_bump = update_changelog_on_bump ,
122+ major_version_zero = major_version_zero ,
123+ )
156124
157125 out .write ("\n You can bump the version running:\n " )
158126 out .info ("\t cz bump\n " )
159127 out .success ("Configuration complete 🚀" )
160128
161129 def _ask_config_path (self ) -> str :
162- default_path = ".cz.toml"
163- if self .project_info .has_pyproject :
164- default_path = "pyproject.toml"
165-
166- name : str = questionary .select (
167- "Please choose a supported config file: " ,
168- choices = config_files ,
169- default = default_path ,
170- style = self .cz .style ,
171- ).unsafe_ask ()
172- return name
130+ default_path = (
131+ "pyproject.toml" if self .project_info .has_pyproject else ".cz.toml"
132+ )
133+
134+ return str (
135+ questionary .select (
136+ "Please choose a supported config file: " ,
137+ choices = config_files ,
138+ default = default_path ,
139+ style = self .cz .style ,
140+ ).unsafe_ask ()
141+ )
173142
174143 def _ask_name (self ) -> str :
175- name : str = questionary .select (
176- "Please choose a cz (commit rule): (default: cz_conventional_commits)" ,
177- choices = list (registry .keys ()),
178- default = "cz_conventional_commits" ,
179- style = self .cz .style ,
180- ).unsafe_ask ()
181- return name
144+ return str (
145+ questionary .select (
146+ "Please choose a cz (commit rule): (default: cz_conventional_commits)" ,
147+ choices = list (registry .keys ()),
148+ default = "cz_conventional_commits" ,
149+ style = self .cz .style ,
150+ ).unsafe_ask ()
151+ )
182152
183153 def _ask_tag (self ) -> str :
184- latest_tag = self . project_info . latest_tag
154+ latest_tag = get_latest_tag_name ()
185155 if not latest_tag :
186156 out .error ("No Existing Tag. Set tag to v0.0.1" )
187157 return "0.0.1"
188158
189159 is_correct_tag = questionary .confirm (
190160 f"Is { latest_tag } the latest tag?" , style = self .cz .style , default = False
191161 ).unsafe_ask ()
192- if not is_correct_tag :
193- tags = self .project_info .tags ()
194- if not tags :
195- out .error ("No Existing Tag. Set tag to v0.0.1" )
196- return "0.0.1"
197-
198- # the latest tag is most likely with the largest number. Thus list the tags in reverse order makes more sense
199- sorted_tags = sorted (tags , reverse = True )
200- latest_tag = questionary .select (
162+ if is_correct_tag :
163+ return latest_tag
164+
165+ tags = get_tag_names ()
166+ if not tags :
167+ out .error ("No Existing Tag. Set tag to v0.0.1" )
168+ return "0.0.1"
169+
170+ # Tags are sorted in reverse order to get the most recent tag first,
171+ # which is typically the one we want to use as a reference.
172+ latest_tag = str (
173+ questionary .select (
201174 "Please choose the latest tag: " ,
202- choices = sorted_tags ,
175+ choices = sorted ( tags , reverse = True ) ,
203176 style = self .cz .style ,
204177 ).unsafe_ask ()
178+ )
179+
180+ if not latest_tag :
181+ raise NoAnswersError ("Tag is required!" )
205182
206- if not latest_tag :
207- raise NoAnswersError ("Tag is required!" )
208183 return latest_tag
209184
210185 def _ask_tag_format (self , latest_tag ) -> str :
@@ -215,16 +190,16 @@ def _ask_tag_format(self, latest_tag) -> str:
215190 f'Is "{ tag_format } " the correct tag format?' , style = self .cz .style
216191 ).unsafe_ask ()
217192
193+ if is_correct_format :
194+ return tag_format
195+
218196 default_format = DEFAULT_SETTINGS ["tag_format" ]
219- if not is_correct_format :
220- tag_format = questionary .text (
221- f'Please enter the correct version format: (default: "{ default_format } ")' ,
222- style = self .cz .style ,
223- ).unsafe_ask ()
197+ tag_format = questionary .text (
198+ f'Please enter the correct version format: (default: "{ default_format } ")' ,
199+ style = self .cz .style ,
200+ ).unsafe_ask ()
224201
225- if not tag_format :
226- tag_format = default_format
227- return tag_format
202+ return tag_format or default_format
228203
229204 def _ask_version_provider (self ) -> str :
230205 """Ask for setting: version_provider"""
@@ -323,7 +298,31 @@ def _gen_pre_commit_cmd(self, hook_types: list[str]) -> str:
323298 )
324299 return cmd_str
325300
326- def _install_pre_commit_hook (self , hook_types : list [str ] | None = None ):
301+ def _init_config (self , config_path : str ):
302+ if "toml" in config_path :
303+ self .config = TomlConfig (data = "" , path = config_path )
304+ elif "json" in config_path :
305+ self .config = JsonConfig (data = "{}" , path = config_path )
306+ elif "yaml" in config_path :
307+ self .config = YAMLConfig (data = "" , path = config_path )
308+
309+ def _init_pre_commit_hook (self ):
310+ hook_types = questionary .checkbox (
311+ "What types of pre-commit hook you want to install? (Leave blank if you don't want to install)" ,
312+ choices = [
313+ questionary .Choice ("commit-msg" , checked = False ),
314+ questionary .Choice ("pre-push" , checked = False ),
315+ ],
316+ ).unsafe_ask ()
317+ try :
318+ self ._install_pre_commit_hook (hook_types )
319+ except InitFailedError as e :
320+ raise InitFailedError (f"Failed to install pre-commit hook.\n { e } " )
321+
322+ def _install_pre_commit_hook (self , hook_types : list [str ] | None ):
323+ if not hook_types :
324+ return
325+
327326 pre_commit_config_filename = ".pre-commit-config.yaml"
328327 cz_hook_config = {
329328 "repo" : "https://github.com/commitizen-tools/commitizen" ,
@@ -364,11 +363,18 @@ def _install_pre_commit_hook(self, hook_types: list[str] | None = None):
364363
365364 if not self .project_info .is_pre_commit_installed :
366365 raise InitFailedError ("pre-commit is not installed in current environment." )
367- if hook_types is None :
368- hook_types = ["commit-msg" , "pre-push" ]
366+
369367 self ._exec_install_pre_commit_hook (hook_types )
370368 out .write ("commitizen pre-commit hook is now installed in your '.git'\n " )
371369
372- def _update_config_file (self , values : dict [str , Any ]):
373- for key , value in values .items ():
374- self .config .set_key (key , value )
370+ def _update_config_file (
371+ self , version_provider : str , version : VersionScheme , ** kwargs
372+ ):
373+ for key , value in kwargs .items ():
374+ if value :
375+ self .config .set_key (key , value )
376+
377+ if version_provider == "commitizen" :
378+ self .config .set_key ("version" , version .public )
379+ else :
380+ self .config .set_key ("version_provider" , version_provider )
0 commit comments