Skip to content

Commit ddadf1b

Browse files
committed
refactor(config): replace is_empty_config with contains_commitizen_section, improve multi config resolution algorithm
1 parent 26e5d80 commit ddadf1b

File tree

5 files changed

+33
-20
lines changed

5 files changed

+33
-20
lines changed

commitizen/config/__init__.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,17 @@ def _resolve_config_candidates() -> list[BaseConfig]:
1313
git_project_root = git.find_git_project_root()
1414
cfg_search_paths = [Path(".")]
1515

16-
if git_project_root and not cfg_search_paths[0].samefile(git_project_root):
16+
if git_project_root and cfg_search_paths[0].resolve() != git_project_root.resolve():
1717
cfg_search_paths.append(git_project_root)
1818

19-
# The following algorithm is ugly, but we need to ensure that the order of the candidates are preserved before v5.
20-
# Also, the number of possible config files is limited, so the complexity is not a problem.
2119
candidates: list[BaseConfig] = []
2220
for dir in cfg_search_paths:
2321
for filename in defaults.CONFIG_FILES:
2422
out_path = dir / Path(filename)
25-
if (
26-
out_path.exists()
27-
and not any(
28-
out_path.samefile(candidate.path) for candidate in candidates
29-
)
30-
and not (conf := _create_config_from_path(out_path)).is_empty_config
31-
):
32-
candidates.append(conf)
23+
if out_path.is_file():
24+
conf = _create_config_from_path(out_path)
25+
if conf.contains_commitizen_section():
26+
candidates.append(conf)
3327
return candidates
3428

3529

@@ -43,10 +37,10 @@ def _create_config_from_path(path: Path) -> BaseConfig:
4337
def read_cfg(filepath: str | None = None) -> BaseConfig:
4438
if filepath is not None:
4539
conf_path = Path(filepath)
46-
if not conf_path.exists():
40+
if not conf_path.is_file():
4741
raise ConfigFileNotFound()
4842
conf = _create_config_from_path(conf_path)
49-
if conf.is_empty_config:
43+
if not conf.contains_commitizen_section():
5044
raise ConfigFileIsEmpty()
5145
return conf
5246

commitizen/config/base_config.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,16 @@
1717

1818
class BaseConfig:
1919
def __init__(self) -> None:
20-
self.is_empty_config = False
2120
self._settings: Settings = DEFAULT_SETTINGS.copy()
2221
self._path: Path | None = None
2322

23+
def contains_commitizen_section(self) -> bool:
24+
"""Check if the config file contains a commitizen section.
25+
26+
The implementation is different for each config file type.
27+
"""
28+
raise NotImplementedError()
29+
2430
@property
2531
def settings(self) -> Settings:
2632
return self._settings

commitizen/config/json_config.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,19 @@ def __init__(self, *, data: bytes | str, path: Path) -> None:
2525
self.path = path
2626
self._parse_setting(data)
2727

28+
def contains_commitizen_section(self) -> bool:
29+
with self.path.open("rb") as json_file:
30+
config_doc = json.load(json_file)
31+
return config_doc.get("commitizen") is not None
32+
2833
def init_empty_config_content(self) -> None:
2934
with smart_open(
3035
self.path, "a", encoding=self._settings["encoding"]
3136
) as json_file:
3237
json.dump({"commitizen": {}}, json_file)
3338

3439
def set_key(self, key: str, value: object) -> Self:
35-
with open(self.path, "rb") as f:
40+
with self.path.open("rb") as f:
3641
config_doc = json.load(f)
3742

3843
config_doc["commitizen"][key] = value
@@ -59,4 +64,4 @@ def _parse_setting(self, data: bytes | str) -> None:
5964
try:
6065
self.settings.update(doc["commitizen"])
6166
except KeyError:
62-
self.is_empty_config = True
67+
pass

commitizen/config/toml_config.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ def __init__(self, *, data: bytes | str, path: Path) -> None:
2626
self.path = path
2727
self._parse_setting(data)
2828

29+
def contains_commitizen_section(self) -> bool:
30+
with self.path.open("rb") as f:
31+
config_doc = parse(f.read())
32+
return config_doc.get("tool", {}).get("commitizen") is not None
33+
2934
def init_empty_config_content(self) -> None:
3035
config_doc = TOMLDocument()
3136
if os.path.isfile(self.path):
@@ -67,4 +72,4 @@ def _parse_setting(self, data: bytes | str) -> None:
6772
try:
6873
self.settings.update(doc["tool"]["commitizen"]) # type: ignore[index,typeddict-item] # TODO: fix this
6974
except exceptions.NonExistentKey:
70-
self.is_empty_config = True
75+
pass

commitizen/config/yaml_config.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ def init_empty_config_content(self) -> None:
3232
) as json_file:
3333
yaml.dump({"commitizen": {}}, json_file, explicit_start=True)
3434

35+
def contains_commitizen_section(self) -> bool:
36+
with self.path.open("rb") as yaml_file:
37+
config_doc = yaml.load(yaml_file, Loader=yaml.FullLoader)
38+
return config_doc.get("commitizen") is not None
39+
3540
def _parse_setting(self, data: bytes | str) -> None:
3641
"""We expect to have a section in cz.yaml looking like
3742
@@ -40,8 +45,6 @@ def _parse_setting(self, data: bytes | str) -> None:
4045
name: cz_conventional_commits
4146
```
4247
"""
43-
import yaml.scanner
44-
4548
try:
4649
doc = yaml.safe_load(data)
4750
except yaml.YAMLError as e:
@@ -50,7 +53,7 @@ def _parse_setting(self, data: bytes | str) -> None:
5053
try:
5154
self.settings.update(doc["commitizen"])
5255
except (KeyError, TypeError):
53-
self.is_empty_config = True
56+
pass
5457

5558
def set_key(self, key: str, value: object) -> Self:
5659
with open(self.path, "rb") as yaml_file:

0 commit comments

Comments
 (0)