126 lines
3.7 KiB
Python
126 lines
3.7 KiB
Python
"""Configuration management for local-commit-message-generator."""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Any, Dict, Optional
|
|
|
|
import tomlkit
|
|
|
|
|
|
class ConfigError(Exception):
|
|
"""Raised when configuration errors occur."""
|
|
pass
|
|
|
|
|
|
DEFAULT_TYPE_RULES: Dict[str, list[str]] = {
|
|
"feat": ["src/", "lib/", "app/", "controllers/", "models/"],
|
|
"fix": ["src/", "lib/", "bug", "fix", "issue", "hotfix"],
|
|
"docs": [".md", ".rst", "docs/", "documentation/"],
|
|
"style": [".css", ".scss", ".sass", ".less", "styles/"],
|
|
"refactor": ["refactor/", "rewrite/", "restructure/"],
|
|
"test": ["test/", "tests/", "__tests__/", ".test.", ".spec."],
|
|
"chore": ["package.json", "pyproject.toml", "requirements", ".gitignore", "Makefile"],
|
|
"perf": ["performance/", "perf/", "optimize/", "optimization/"],
|
|
"ci": [".github/", ".gitlab-ci.yml", ".travis.yml", "Jenkinsfile", "tox.ini"],
|
|
"build": ["build/", "webpack/", "vite.config", "babel.config", "rollup.config"],
|
|
}
|
|
|
|
DEFAULT_CONFIG: Dict[str, Any] = {
|
|
"type_rules": DEFAULT_TYPE_RULES,
|
|
"template": "{type}{scope}: {description}",
|
|
"scopes": {},
|
|
"description_length": 72,
|
|
"max_files": 5,
|
|
"include_file_list": True,
|
|
"file_list_template": "\n\nFiles changed:\n{files}",
|
|
}
|
|
|
|
|
|
def get_config_path() -> Path:
|
|
"""Get the path to the user configuration file."""
|
|
home = Path.home()
|
|
return home / ".local_commit_gen.toml"
|
|
|
|
|
|
def load_config(config_path: Optional[Path] = None) -> Dict[str, Any]:
|
|
"""Load configuration from file.
|
|
|
|
Args:
|
|
config_path: Optional path to config file. If not provided, uses default path.
|
|
|
|
Returns:
|
|
Dictionary containing configuration.
|
|
"""
|
|
if config_path is None:
|
|
config_path = get_config_path()
|
|
|
|
if not config_path.exists():
|
|
return DEFAULT_CONFIG.copy()
|
|
|
|
try:
|
|
with open(config_path, "r") as f:
|
|
config = tomlkit.parse(f.read())
|
|
except tomlkit.exceptions.ParseError as e:
|
|
raise ConfigError(f"Invalid TOML syntax in config file: {e}")
|
|
|
|
merged = DEFAULT_CONFIG.copy()
|
|
for key, value in config.items():
|
|
if key == "type_rules" and isinstance(value, dict):
|
|
merged["type_rules"] = {**DEFAULT_TYPE_RULES, **value}
|
|
else:
|
|
merged[key] = value
|
|
|
|
return merged
|
|
|
|
|
|
def save_config(config: Dict[str, Any], config_path: Optional[Path] = None) -> None:
|
|
"""Save configuration to file.
|
|
|
|
Args:
|
|
config: Configuration dictionary to save.
|
|
config_path: Optional path to config file. If not provided, uses default path.
|
|
"""
|
|
if config_path is None:
|
|
config_path = get_config_path()
|
|
|
|
try:
|
|
with open(config_path, "w") as f:
|
|
tomlkit.dump(config, f)
|
|
except OSError as e:
|
|
raise ConfigError(f"Failed to write config file: {e}")
|
|
|
|
|
|
def ensure_config_exists() -> None:
|
|
"""Ensure default config file exists."""
|
|
config_path = get_config_path()
|
|
if not config_path.exists():
|
|
save_config(DEFAULT_CONFIG.copy())
|
|
|
|
|
|
def get_type_rules(config: Optional[Dict[str, Any]] = None) -> Dict[str, list[str]]:
|
|
"""Get type rules from configuration.
|
|
|
|
Args:
|
|
config: Optional configuration dictionary. If not provided, loads from file.
|
|
|
|
Returns:
|
|
Dictionary mapping commit types to patterns.
|
|
"""
|
|
if config is None:
|
|
config = load_config()
|
|
return config.get("type_rules", DEFAULT_TYPE_RULES)
|
|
|
|
|
|
def get_template(config: Optional[Dict[str, Any]] = None) -> str:
|
|
"""Get message template from configuration.
|
|
|
|
Args:
|
|
config: Optional configuration dictionary. If not provided, loads from file.
|
|
|
|
Returns:
|
|
Message template string.
|
|
"""
|
|
if config is None:
|
|
config = load_config()
|
|
return config.get("template", DEFAULT_CONFIG["template"])
|