Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 8 additions & 14 deletions commitizen/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,17 @@ def _resolve_config_candidates() -> list[BaseConfig]:
git_project_root = git.find_git_project_root()
cfg_search_paths = [Path(".")]

if git_project_root and not cfg_search_paths[0].samefile(git_project_root):
if git_project_root and cfg_search_paths[0].resolve() != git_project_root.resolve():
cfg_search_paths.append(git_project_root)

# The following algorithm is ugly, but we need to ensure that the order of the candidates are preserved before v5.
# Also, the number of possible config files is limited, so the complexity is not a problem.
candidates: list[BaseConfig] = []
for dir in cfg_search_paths:
for filename in defaults.CONFIG_FILES:
out_path = dir / Path(filename)
if (
out_path.exists()
and not any(
out_path.samefile(candidate.path) for candidate in candidates
)
and not (conf := _create_config_from_path(out_path)).is_empty_config
):
candidates.append(conf)
out_path = dir / filename
if out_path.is_file():
conf = _create_config_from_path(out_path)
if conf.contains_commitizen_section():
candidates.append(conf)
return candidates


Expand All @@ -43,10 +37,10 @@ def _create_config_from_path(path: Path) -> BaseConfig:
def read_cfg(filepath: str | None = None) -> BaseConfig:
if filepath is not None:
conf_path = Path(filepath)
if not conf_path.exists():
if not conf_path.is_file():
raise ConfigFileNotFound()
conf = _create_config_from_path(conf_path)
if conf.is_empty_config:
if not conf.contains_commitizen_section():
raise ConfigFileIsEmpty()
return conf

Expand Down
8 changes: 7 additions & 1 deletion commitizen/config/base_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,16 @@

class BaseConfig:
def __init__(self) -> None:
self.is_empty_config = False
self._settings: Settings = DEFAULT_SETTINGS.copy()
self._path: Path | None = None

def contains_commitizen_section(self) -> bool:
"""Check if the config file contains a commitizen section.
The implementation is different for each config file type.
"""
raise NotImplementedError()

@property
def settings(self) -> Settings:
return self._settings
Expand Down
9 changes: 7 additions & 2 deletions commitizen/config/json_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,19 @@ def __init__(self, *, data: bytes | str, path: Path) -> None:
self.path = path
self._parse_setting(data)

def contains_commitizen_section(self) -> bool:
with self.path.open("rb") as json_file:
config_doc = json.load(json_file)
return config_doc.get("commitizen") is not None

def init_empty_config_content(self) -> None:
with smart_open(
self.path, "a", encoding=self._settings["encoding"]
) as json_file:
json.dump({"commitizen": {}}, json_file)

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

config_doc["commitizen"][key] = value
Expand All @@ -59,4 +64,4 @@ def _parse_setting(self, data: bytes | str) -> None:
try:
self.settings.update(doc["commitizen"])
except KeyError:
self.is_empty_config = True
pass
7 changes: 6 additions & 1 deletion commitizen/config/toml_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ def __init__(self, *, data: bytes | str, path: Path) -> None:
self.path = path
self._parse_setting(data)

def contains_commitizen_section(self) -> bool:
with self.path.open("rb") as f:
config_doc = parse(f.read())
return config_doc.get("tool", {}).get("commitizen") is not None

def init_empty_config_content(self) -> None:
config_doc = TOMLDocument()
if os.path.isfile(self.path):
Expand Down Expand Up @@ -67,4 +72,4 @@ def _parse_setting(self, data: bytes | str) -> None:
try:
self.settings.update(doc["tool"]["commitizen"]) # type: ignore[index,typeddict-item] # TODO: fix this
except exceptions.NonExistentKey:
self.is_empty_config = True
pass
9 changes: 6 additions & 3 deletions commitizen/config/yaml_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ def init_empty_config_content(self) -> None:
) as json_file:
yaml.dump({"commitizen": {}}, json_file, explicit_start=True)

def contains_commitizen_section(self) -> bool:
with self.path.open("rb") as yaml_file:
config_doc = yaml.load(yaml_file, Loader=yaml.FullLoader)
return config_doc.get("commitizen") is not None

def _parse_setting(self, data: bytes | str) -> None:
"""We expect to have a section in cz.yaml looking like

Expand All @@ -40,8 +45,6 @@ def _parse_setting(self, data: bytes | str) -> None:
name: cz_conventional_commits
```
"""
import yaml.scanner

try:
doc = yaml.safe_load(data)
except yaml.YAMLError as e:
Expand All @@ -50,7 +53,7 @@ def _parse_setting(self, data: bytes | str) -> None:
try:
self.settings.update(doc["commitizen"])
except (KeyError, TypeError):
self.is_empty_config = True
pass

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