Skip to content

Commit 33a06e9

Browse files
Merge branch 'master' into feature/custom-validation
2 parents 904f200 + 3e21ac5 commit 33a06e9

27 files changed

+541
-293
lines changed

.github/workflows/homebrewpublish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
run: |
2525
echo "project_version=$(cz version --project)" >> $GITHUB_ENV
2626
- name: Update Homebrew formula
27-
uses: dawidd6/action-homebrew-bump-formula@v3
27+
uses: dawidd6/action-homebrew-bump-formula@v4
2828
with:
2929
token: ${{secrets.PERSONAL_ACCESS_TOKEN}}
3030
formula: commitizen

.github/workflows/pythonpackage.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ jobs:
66
python-check:
77
strategy:
88
matrix:
9-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13-dev"]
9+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
1010
platform: [ubuntu-20.04, macos-latest, windows-latest]
1111
runs-on: ${{ matrix.platform }}
1212
steps:
@@ -30,7 +30,7 @@ jobs:
3030
shell: bash
3131
- name: Upload coverage to Codecov
3232
if: runner.os == 'Linux'
33-
uses: codecov/codecov-action@v4
33+
uses: codecov/codecov-action@v5
3434
with:
3535
token: ${{ secrets.CODECOV_TOKEN }}
3636
file: ./coverage.xml

.pre-commit-config.yaml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ default_install_hook_types:
44
- pre-push
55

66
default_stages:
7-
- commit
8-
- push
7+
- pre-commit
8+
- pre-push
99

1010
repos:
1111
- repo: meta
@@ -49,13 +49,13 @@ repos:
4949
- tomli
5050

5151
- repo: https://github.com/commitizen-tools/commitizen
52-
rev: v3.29.1 # automatically updated by Commitizen
52+
rev: v3.31.0 # automatically updated by Commitizen
5353
hooks:
5454
- id: commitizen
5555
- id: commitizen-branch
5656
stages:
5757
- post-commit
58-
- push
58+
- pre-push
5959

6060
- repo: local
6161
hooks:
@@ -70,6 +70,6 @@ repos:
7070
name: linter and test
7171
language: system
7272
pass_filenames: false
73-
stages: [ push ]
73+
stages: [ pre-push ]
7474
entry: ./scripts/test
7575
types: [ python ]

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,32 @@
1+
## v3.31.0 (2024-11-16)
2+
3+
### Feat
4+
5+
- **commitizen**: document '--' double dash in '--help'
6+
7+
### Fix
8+
9+
- **commit**: avoid warnings with 'always_signoff' configuration
10+
- **commit**: resolve 'always_signoff' configuration and '-s' CLI issues
11+
12+
## v3.30.1 (2024-11-10)
13+
14+
### Refactor
15+
16+
- **cli**: replace magic number 0 with ExitCode.EXPECTED_EXIT
17+
- **defaults**: disallow style as None
18+
- **cz_customize**: return empty string for info, example, schema and schema_pattern if not provided
19+
20+
## v3.30.0 (2024-10-23)
21+
22+
### Feat
23+
24+
- **commands/commit**: add force-edit functionality after answering questions
25+
26+
### Refactor
27+
28+
- remove redundant return None
29+
130
## v3.29.1 (2024-09-26)
231

332
### Fix

commitizen/__version__.py

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

commitizen/cli.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,24 @@ def __call__(
156156
"action": "store_true",
157157
"help": "Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.",
158158
},
159+
{
160+
"name": ["-e", "--edit"],
161+
"action": "store_true",
162+
"default": False,
163+
"help": "edit the commit message before committing",
164+
},
159165
{
160166
"name": ["-l", "--message-length-limit"],
161167
"type": int,
162168
"default": 0,
163169
"help": "length limit of the commit message; 0 for no limit",
164170
},
171+
{
172+
"name": ["--"],
173+
"action": "store_true",
174+
"dest": "double_dash",
175+
"help": "Positional arguments separator (recommended)",
176+
},
165177
],
166178
},
167179
{
@@ -541,7 +553,7 @@ def commitizen_excepthook(
541553
original_excepthook(type, value, traceback)
542554
exit_code = value.exit_code
543555
if exit_code in no_raise:
544-
exit_code = 0
556+
exit_code = ExitCode.EXPECTED_EXIT
545557
sys.exit(exit_code)
546558
else:
547559
original_excepthook(type, value, traceback)

commitizen/commands/check.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def _valid_command_argument(self):
5353
for arg in (self.commit_msg_file, self.commit_msg, self.rev_range)
5454
)
5555
if num_exclusive_args_provided == 0 and not sys.stdin.isatty():
56-
self.commit_msg: str | None = sys.stdin.read()
56+
self.commit_msg = sys.stdin.read()
5757
elif num_exclusive_args_provided != 1:
5858
raise InvalidCommandArgumentError(
5959
"Only one of --rev-range, --message, and --commit-msg-file is permitted by check command! "
@@ -106,7 +106,9 @@ def _get_commits(self):
106106
return [git.GitCommit(rev="", title="", body=msg)]
107107

108108
# Get commit messages from git log (--rev-range)
109-
return git.get_commits(end=self.rev_range)
109+
if self.rev_range:
110+
return git.get_commits(end=self.rev_range)
111+
return git.get_commits()
110112

111113
@staticmethod
112114
def _filter_comments(msg: str) -> str:

commitizen/commands/commit.py

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
import contextlib
44
import os
5+
import shutil
6+
import subprocess
7+
import tempfile
58

69
import questionary
710

@@ -72,9 +75,27 @@ def prompt_commit_questions(self) -> str:
7275

7376
return message
7477

78+
def manual_edit(self, message: str) -> str:
79+
editor = git.get_core_editor()
80+
if editor is None:
81+
raise RuntimeError("No 'editor' value given and no default available.")
82+
exec_path = shutil.which(editor)
83+
if exec_path is None:
84+
raise RuntimeError(f"Editor '{editor}' not found.")
85+
with tempfile.NamedTemporaryFile(mode="w", delete=False) as file:
86+
file.write(message)
87+
file_path = file.name
88+
argv = [exec_path, file_path]
89+
subprocess.call(argv)
90+
with open(file_path) as temp_file:
91+
message = temp_file.read().strip()
92+
file.unlink()
93+
return message
94+
7595
def __call__(self):
7696
dry_run: bool = self.arguments.get("dry_run")
7797
write_message_to_file: bool = self.arguments.get("write_message_to_file")
98+
manual_edit: bool = self.arguments.get("edit")
7899

79100
is_all: bool = self.arguments.get("all")
80101
if is_all:
@@ -101,6 +122,9 @@ def __call__(self):
101122
else:
102123
m = self.prompt_commit_questions()
103124

125+
if manual_edit:
126+
m = self.manual_edit(m)
127+
104128
out.info(f"\n{m}\n")
105129

106130
if write_message_to_file:
@@ -110,17 +134,18 @@ def __call__(self):
110134
if dry_run:
111135
raise DryRunExit()
112136

113-
signoff: bool = (
114-
self.arguments.get("signoff") or self.config.settings["always_signoff"]
115-
)
137+
always_signoff: bool = self.config.settings["always_signoff"]
138+
signoff: bool = self.arguments.get("signoff")
139+
140+
extra_args = self.arguments.get("extra_cli_args", "")
116141

117142
if signoff:
118143
out.warn(
119144
"signoff mechanic is deprecated, please use `cz commit -- -s` instead."
120145
)
121-
extra_args = self.arguments.get("extra_cli_args", "--") + " -s"
122-
else:
123-
extra_args = self.arguments.get("extra_cli_args", "")
146+
147+
if always_signoff or signoff:
148+
extra_args = f"{extra_args} -s".strip()
124149

125150
c = git.commit(m, args=extra_args)
126151

commitizen/cz/base.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class BaseCommitizen(metaclass=ABCMeta):
6767
template_loader: BaseLoader = PackageLoader("commitizen", "templates")
6868
template_extras: dict[str, Any] = {}
6969

70-
def __init__(self, config: BaseConfig):
70+
def __init__(self, config: BaseConfig) -> None:
7171
self.config = config
7272
if not self.config.settings.get("style"):
7373
self.config.settings.update({"style": BaseCommitizen.default_style_config})
@@ -89,15 +89,15 @@ def style(self):
8989
]
9090
)
9191

92-
def example(self) -> str | None:
92+
def example(self) -> str:
9393
"""Example of the commit message."""
9494
raise NotImplementedError("Not Implemented yet")
9595

96-
def schema(self) -> str | None:
96+
def schema(self) -> str:
9797
"""Schema definition of the commit message."""
9898
raise NotImplementedError("Not Implemented yet")
9999

100-
def schema_pattern(self) -> str | None:
100+
def schema_pattern(self) -> str:
101101
"""Regex matching the schema used for message validation."""
102102
raise NotImplementedError("Not Implemented yet")
103103

@@ -142,7 +142,7 @@ def format_exception_message(
142142
f"pattern: {self.schema_pattern()}"
143143
)
144144

145-
def info(self) -> str | None:
145+
def info(self) -> str:
146146
"""Information about the standardized commit message."""
147147
raise NotImplementedError("Not Implemented yet")
148148

commitizen/cz/customize/customize.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
from __future__ import annotations
22

3-
try:
3+
from typing import TYPE_CHECKING
4+
5+
if TYPE_CHECKING:
46
from jinja2 import Template
5-
except ImportError:
6-
from string import Template # type: ignore
7+
else:
8+
try:
9+
from jinja2 import Template
10+
except ImportError:
11+
from string import Template
712

813

914
from commitizen import defaults
@@ -68,16 +73,16 @@ def message(self, answers: dict) -> str:
6873
else:
6974
return message_template.render(**answers)
7075

71-
def example(self) -> str | None:
72-
return self.custom_settings.get("example")
76+
def example(self) -> str:
77+
return self.custom_settings.get("example") or ""
7378

74-
def schema_pattern(self) -> str | None:
75-
return self.custom_settings.get("schema_pattern")
79+
def schema_pattern(self) -> str:
80+
return self.custom_settings.get("schema_pattern") or ""
7681

77-
def schema(self) -> str | None:
78-
return self.custom_settings.get("schema")
82+
def schema(self) -> str:
83+
return self.custom_settings.get("schema") or ""
7984

80-
def info(self) -> str | None:
85+
def info(self) -> str:
8186
info_path = self.custom_settings.get("info_path")
8287
info = self.custom_settings.get("info")
8388
if info_path:
@@ -86,4 +91,4 @@ def info(self) -> str | None:
8691
return content
8792
elif info:
8893
return info
89-
return None
94+
return ""

0 commit comments

Comments
 (0)