Skip to content

Commit c3228cc

Browse files
committed
feat(cli): add config option to specify config file path
Issue #656
1 parent 669080c commit c3228cc

File tree

4 files changed

+48
-3
lines changed

4 files changed

+48
-3
lines changed

commitizen/cli.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ def __call__(
9292
),
9393
"formatter_class": argparse.RawDescriptionHelpFormatter,
9494
"arguments": [
95+
{
96+
"name": "--config",
97+
"help": "specify file path if config file is not in root folder",
98+
},
9599
{"name": "--debug", "action": "store_true", "help": "use debug mode"},
96100
{
97101
"name": ["-n", "--name"],
@@ -534,9 +538,7 @@ def parse_no_raise(comma_separated_no_raise: str) -> list[int]:
534538

535539

536540
def main():
537-
conf = config.read_cfg()
538541
parser = cli(data)
539-
540542
argcomplete.autocomplete(parser)
541543
# Show help if no arg provided
542544
if len(sys.argv) == 1:
@@ -576,6 +578,11 @@ def main():
576578
extra_args = " ".join(unknown_args[1:])
577579
arguments["extra_cli_args"] = extra_args
578580

581+
if args.config:
582+
conf = config.read_cfg(args.config)
583+
else:
584+
conf = config.read_cfg()
585+
579586
if args.name:
580587
conf.update({"name": args.name})
581588
elif not args.name and not conf.path:

commitizen/config/__init__.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,39 @@
33
from pathlib import Path
44

55
from commitizen import defaults, git
6+
from commitizen.exceptions import ConfigFileNotFound
67

78
from .base_config import BaseConfig
89
from .json_config import JsonConfig
910
from .toml_config import TomlConfig
1011
from .yaml_config import YAMLConfig
1112

1213

13-
def read_cfg() -> BaseConfig:
14+
def read_cfg(filepath: str | None = None) -> BaseConfig:
1415
conf = BaseConfig()
1516

1617
git_project_root = git.find_git_project_root()
18+
19+
if filepath is not None:
20+
given_cfg_path = Path(filepath)
21+
22+
if not given_cfg_path.exists():
23+
raise ConfigFileNotFound()
24+
25+
with open(given_cfg_path, "rb") as f:
26+
given_cfg_data: bytes = f.read()
27+
28+
given_cfg: TomlConfig | JsonConfig | YAMLConfig
29+
30+
if "toml" in given_cfg_path.suffix:
31+
given_cfg = TomlConfig(data=given_cfg_data, path=given_cfg_path)
32+
elif "json" in given_cfg_path.suffix:
33+
given_cfg = JsonConfig(data=given_cfg_data, path=given_cfg_path)
34+
elif "yaml" in given_cfg_path.suffix:
35+
given_cfg = YAMLConfig(data=given_cfg_data, path=given_cfg_path)
36+
37+
return given_cfg
38+
1739
cfg_search_paths = [Path(".")]
1840
if git_project_root:
1941
cfg_search_paths.append(git_project_root)

commitizen/exceptions.py

+6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class ExitCode(enum.IntEnum):
3434
VERSION_PROVIDER_UNKNOWN = 27
3535
VERSION_SCHEME_UNKNOWN = 28
3636
CHANGELOG_FORMAT_UNKNOWN = 29
37+
CONFIG_FILE_NOT_FOUND = 30
3738

3839

3940
class CommitizenException(Exception):
@@ -189,3 +190,8 @@ class VersionSchemeUnknown(CommitizenException):
189190
class ChangelogFormatUnknown(CommitizenException):
190191
exit_code = ExitCode.CHANGELOG_FORMAT_UNKNOWN
191192
message = "Unknown changelog format identifier"
193+
194+
195+
class ConfigFileNotFound(CommitizenException):
196+
exit_code = ExitCode.CONFIG_FILE_NOT_FOUND
197+
message = "Cannot found the config file, please check your file path again."

tests/test_cli.py

+10
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
NoCommandFoundError,
1313
NotAGitProjectError,
1414
InvalidCommandArgumentError,
15+
ConfigFileNotFound,
1516
)
1617

1718

@@ -25,6 +26,15 @@ def test_sysexit_no_argv(mocker: MockFixture, capsys):
2526
assert out.startswith("usage")
2627

2728

29+
def test_cz_config_file_without_correct_file_path(mocker: MockFixture, capsys):
30+
testargs = ["cz", "--config", "./config/pyproject.toml", "example"]
31+
mocker.patch.object(sys, "argv", testargs)
32+
33+
with pytest.raises(ConfigFileNotFound) as excinfo:
34+
cli.main()
35+
assert "Cannot found the config file" in str(excinfo.value)
36+
37+
2838
def test_cz_with_arg_but_without_command(mocker: MockFixture):
2939
testargs = ["cz", "--name", "cz_jira"]
3040
mocker.patch.object(sys, "argv", testargs)

0 commit comments

Comments
 (0)