Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 24f0f27

Browse files
committed
Merge branch 'master' of github.com:commitizen-tools/commitizen into add-hooks-for-bump-command
2 parents cf0ac80 + de5c39c commit 24f0f27

17 files changed

+430
-243
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ repos:
1414
- id: no-commit-to-branch
1515

1616
- repo: https://github.com/commitizen-tools/commitizen
17-
rev: v2.38.0 # automatically updated by Commitizen
17+
rev: v2.39.1 # automatically updated by Commitizen
1818
hooks:
1919
- id: commitizen
2020
- id: commitizen-branch

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,25 @@
11

2+
## v2.39.1 (2022-12-31)
3+
4+
### Fix
5+
6+
- filter git diff from commit message
7+
8+
## v2.39.0 (2022-12-31)
9+
10+
### Feat
11+
12+
- **init**: allow user to select which type of pre commit hooks to install
13+
14+
### Fix
15+
16+
- **init**: space between `--hook-type` options
17+
- **init**: report error when hook installation failed
18+
19+
### Refactor
20+
21+
- **init**: `_install_pre_commit_hook` raise error when failed
22+
223
## v2.38.0 (2022-12-12)
324

425
### Feat

commitizen/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "2.38.0"
1+
__version__ = "2.39.1"

commitizen/commands/check.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
import re
33
import sys
4-
from typing import Dict, Optional
4+
from typing import Any, Dict, Optional
55

66
from commitizen import factory, git, out
77
from commitizen.config import BaseConfig
@@ -15,7 +15,7 @@
1515
class Check:
1616
"""Check if the current commit msg matches the commitizen format."""
1717

18-
def __init__(self, config: BaseConfig, arguments: Dict[str, str], cwd=os.getcwd()):
18+
def __init__(self, config: BaseConfig, arguments: Dict[str, Any], cwd=os.getcwd()):
1919
"""Initial check command.
2020
2121
Args:
@@ -98,8 +98,35 @@ def _get_commits(self):
9898
# Get commit messages from git log (--rev-range)
9999
return git.get_commits(end=self.rev_range)
100100

101-
def _filter_comments(self, msg: str) -> str:
102-
lines = [line for line in msg.split("\n") if not line.startswith("#")]
101+
@staticmethod
102+
def _filter_comments(msg: str) -> str:
103+
"""Filter the commit message by removing comments.
104+
105+
When using `git commit --verbose`, we exclude the diff that is going to
106+
generated, like the following example:
107+
108+
```bash
109+
...
110+
# ------------------------ >8 ------------------------
111+
# Do not modify or remove the line above.
112+
# Everything below it will be ignored.
113+
diff --git a/... b/...
114+
...
115+
```
116+
117+
Args:
118+
msg: The commit message to filter.
119+
120+
Returns:
121+
The filtered commit message without comments.
122+
"""
123+
124+
lines = []
125+
for line in msg.split("\n"):
126+
if "# ------------------------ >8 ------------------------" in line:
127+
break
128+
if not line.startswith("#"):
129+
lines.append(line)
103130
return "\n".join(lines)
104131

105132
def validate_commit_message(self, commit_msg: str, pattern: str) -> bool:

commitizen/commands/init.py

Lines changed: 78 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import os
2+
import shutil
3+
from typing import Any, Dict, List, Optional
24

35
import questionary
46
import yaml
@@ -9,7 +11,7 @@
911
from commitizen.config import BaseConfig, JsonConfig, TomlConfig, YAMLConfig
1012
from commitizen.cz import registry
1113
from commitizen.defaults import config_files
12-
from commitizen.exceptions import NoAnswersError
14+
from commitizen.exceptions import InitFailedError, NoAnswersError
1315
from commitizen.git import get_latest_tag_name, get_tag_names, smart_open
1416

1517

@@ -19,34 +21,43 @@ def __init__(self, config: BaseConfig, *args):
1921
self.cz = factory.commiter_factory(self.config)
2022

2123
def __call__(self):
22-
values_to_add = {}
24+
if self.config.path:
25+
out.line(f"Config file {self.config.path} already exists")
26+
return
2327

2428
# No config for commitizen exist
25-
if not self.config.path:
26-
config_path = self._ask_config_path()
27-
if "toml" in config_path:
28-
self.config = TomlConfig(data="", path=config_path)
29-
elif "json" in config_path:
30-
self.config = JsonConfig(data="{}", path=config_path)
31-
elif "yaml" in config_path:
32-
self.config = YAMLConfig(data="", path=config_path)
33-
34-
self.config.init_empty_config_content()
35-
36-
values_to_add["name"] = self._ask_name()
37-
tag = self._ask_tag()
38-
values_to_add["version"] = Version(tag).public
39-
values_to_add["tag_format"] = self._ask_tag_format(tag)
40-
self._update_config_file(values_to_add)
41-
42-
if questionary.confirm("Do you want to install pre-commit hook?").ask():
43-
self._install_pre_commit_hook()
44-
45-
out.write("You can bump the version and create changelog running:\n")
46-
out.info("cz bump --changelog")
47-
out.success("The configuration are all set.")
48-
else:
49-
out.line(f"Config file {self.config.path} already exists")
29+
config_path = self._ask_config_path()
30+
if "toml" in config_path:
31+
self.config = TomlConfig(data="", path=config_path)
32+
elif "json" in config_path:
33+
self.config = JsonConfig(data="{}", path=config_path)
34+
elif "yaml" in config_path:
35+
self.config = YAMLConfig(data="", path=config_path)
36+
self.config.init_empty_config_content()
37+
38+
values_to_add = {}
39+
values_to_add["name"] = self._ask_name()
40+
tag = self._ask_tag()
41+
values_to_add["version"] = Version(tag).public
42+
values_to_add["tag_format"] = self._ask_tag_format(tag)
43+
self._update_config_file(values_to_add)
44+
45+
hook_types = questionary.checkbox(
46+
"What types of pre-commit hook you want to install? (Leave blank if you don't want to install)",
47+
choices=[
48+
questionary.Choice("commit-msg", checked=True),
49+
questionary.Choice("pre-push", checked=True),
50+
],
51+
).ask()
52+
if hook_types:
53+
try:
54+
self._install_pre_commit_hook(hook_types)
55+
except InitFailedError as e:
56+
raise InitFailedError(f"Failed to install pre-commit hook.\n{e}")
57+
58+
out.write("You can bump the version and create changelog running:\n")
59+
out.info("cz bump --changelog")
60+
out.success("The configuration are all set.")
5061

5162
def _ask_config_path(self) -> str:
5263
name: str = questionary.select(
@@ -109,17 +120,45 @@ def _ask_tag_format(self, latest_tag) -> str:
109120
tag_format = "$version"
110121
return tag_format
111122

112-
def _install_pre_commit_hook(self):
123+
def _search_pre_commit(self) -> bool:
124+
"""Check whether pre-commit is installed"""
125+
return shutil.which("pre-commit") is not None
126+
127+
def _exec_install_pre_commit_hook(self, hook_types: List[str]):
128+
cmd_str = self._gen_pre_commit_cmd(hook_types)
129+
c = cmd.run(cmd_str)
130+
if c.return_code != 0:
131+
err_msg = (
132+
f"Error running {cmd_str}."
133+
"Outputs are attached below:\n"
134+
f"stdout: {c.out}\n"
135+
f"stderr: {c.err}"
136+
)
137+
raise InitFailedError(err_msg)
138+
139+
def _gen_pre_commit_cmd(self, hook_types: List[str]) -> str:
140+
"""Generate pre-commit command according to given hook types"""
141+
if not hook_types:
142+
raise ValueError("At least 1 hook type should be provided.")
143+
cmd_str = "pre-commit install " + " ".join(
144+
f"--hook-type {ty}" for ty in hook_types
145+
)
146+
return cmd_str
147+
148+
def _install_pre_commit_hook(self, hook_types: Optional[List[str]] = None):
113149
pre_commit_config_filename = ".pre-commit-config.yaml"
114150
cz_hook_config = {
115151
"repo": "https://github.com/commitizen-tools/commitizen",
116152
"rev": f"v{__version__}",
117-
"hooks": [{"id": "commitizen"}],
153+
"hooks": [
154+
{"id": "commitizen"},
155+
{"id": "commitizen-branch", "stages": ["push"]},
156+
],
118157
}
119158

120159
config_data = {}
121160
if not os.path.isfile(pre_commit_config_filename):
122-
# .pre-commit-config does not exist
161+
# .pre-commit-config.yaml does not exist
123162
config_data["repos"] = [cz_hook_config]
124163
else:
125164
with open(pre_commit_config_filename) as config_file:
@@ -135,23 +174,21 @@ def _install_pre_commit_hook(self):
135174
else:
136175
config_data["repos"].append(cz_hook_config)
137176
else:
138-
# .pre-commit-config exists but there's no "repos" key
177+
# .pre-commit-config.yaml exists but there's no "repos" key
139178
config_data["repos"] = [cz_hook_config]
140179

141180
with smart_open(pre_commit_config_filename, "w") as config_file:
142181
yaml.safe_dump(config_data, stream=config_file)
143182

144-
c = cmd.run("pre-commit install --hook-type commit-msg")
145-
if c.return_code == 127:
146-
out.error(
147-
"pre-commit is not installed in current environement.\n"
148-
"Run 'pre-commit install --hook-type commit-msg' again after it's installed"
183+
if not self._search_pre_commit():
184+
raise InitFailedError(
185+
"pre-commit is not installed in current environement."
149186
)
150-
elif c.return_code != 0:
151-
out.error(c.err)
152-
else:
153-
out.write("commitizen pre-commit hook is now installed in your '.git'\n")
187+
if hook_types is None:
188+
hook_types = ["commit-msg", "pre-push"]
189+
self._exec_install_pre_commit_hook(hook_types)
190+
out.write("commitizen pre-commit hook is now installed in your '.git'\n")
154191

155-
def _update_config_file(self, values):
192+
def _update_config_file(self, values: Dict[str, Any]):
156193
for key, value in values.items():
157194
self.config.set_key(key, value)

commitizen/exceptions.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class ExitCode(enum.IntEnum):
2929
UNRECOGNIZED_CHARACTERSET_ENCODING = 22
3030
GIT_COMMAND_ERROR = 23
3131
INVALID_MANUAL_VERSION = 24
32-
RUN_HOOK_FAILED = 25
32+
INIT_FAILED = 25
33+
RUN_HOOK_FAILED = 26
3334

3435

3536
class CommitizenException(Exception):
@@ -166,5 +167,9 @@ class InvalidManualVersion(CommitizenException):
166167
exit_code = ExitCode.INVALID_MANUAL_VERSION
167168

168169

170+
class InitFailedError(CommitizenException):
171+
exit_code = ExitCode.INIT_FAILED
172+
173+
169174
class RunHookError(CommitizenException):
170175
exit_code = ExitCode.RUN_HOOK_FAILED

commitizen/hooks.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
from commitizen import cmd, out
24
from commitizen.exceptions import RunHookError
35

@@ -20,10 +22,11 @@ def run(hooks, _env_prefix="CZ_", **env):
2022
raise RunHookError(f"Running hook '{hook}' failed")
2123

2224

23-
def _format_env(prefix: str, env: dict[str, str]) -> dict[str, str]:
25+
def _format_env(prefix, env):
2426
"""_format_env() prefixes all given environment variables with the given
25-
prefix so it can be passed directly to cmd.run()."""
26-
penv = dict()
27+
prefix and adds them to the current OS environment variables, so it can be
28+
passed directly to cmd.run()."""
29+
penv = os.environ.copy()
2730
for name, value in env.items():
2831
name = prefix + name.upper()
2932
value = str(value) if value is not None else ""

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tool.commitizen]
2-
version = "2.38.0"
2+
version = "2.39.1"
33
tag_format = "v$version"
44
version_files = [
55
"pyproject.toml:version",
@@ -30,7 +30,7 @@ exclude = '''
3030

3131
[tool.poetry]
3232
name = "commitizen"
33-
version = "2.38.0"
33+
version = "2.39.1"
3434
description = "Python commitizen client tool"
3535
authors = ["Santiago Fraire <santiwilly@gmail.com>"]
3636
license = "MIT"

0 commit comments

Comments
 (0)