115 lines
4.0 KiB
Python
115 lines
4.0 KiB
Python
# RepoSync/config/profile_manager.py
|
|
|
|
"""
|
|
Manages loading and saving of server connection profiles and application
|
|
settings from a JSON file.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Dict, List, Optional, Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
def get_config_path() -> Path:
|
|
"""
|
|
Gets the path to the configuration file inside a 'config' subdirectory
|
|
relative to the application's current working directory.
|
|
"""
|
|
base_path = Path.cwd()
|
|
config_dir = base_path / "config"
|
|
config_dir.mkdir(exist_ok=True)
|
|
return config_dir / "profiles.json"
|
|
|
|
|
|
class ProfileManager:
|
|
"""Handles CRUD for server profiles and app settings."""
|
|
|
|
def __init__(self):
|
|
self.profiles_path = get_config_path()
|
|
self.profiles: Dict[str, Dict] = {}
|
|
self.settings: Dict[str, Any] = {}
|
|
self.load_data()
|
|
|
|
def load_data(self):
|
|
"""Loads both profiles and settings from the JSON file."""
|
|
logger.info(f"Loading data from: {self.profiles_path}")
|
|
if not self.profiles_path.exists():
|
|
self.profiles = {}
|
|
self.settings = {
|
|
"bundle_path": str(Path.home() / "RepoSyncBundles"),
|
|
"git_timeout": 600 # Default: 10 minutes
|
|
}
|
|
logger.warning("Profiles file not found. Using default settings.")
|
|
return
|
|
|
|
try:
|
|
with open(self.profiles_path, "r", encoding="utf-8") as f:
|
|
data = json.load(f)
|
|
|
|
self.profiles = data.get("profiles", {})
|
|
self.settings = data.get("settings", {})
|
|
|
|
# Ensure defaults are set if they are missing from the file
|
|
if "bundle_path" not in self.settings:
|
|
self.settings["bundle_path"] = str(Path.home() / "RepoSyncBundles")
|
|
if "git_timeout" not in self.settings:
|
|
self.settings["git_timeout"] = 600
|
|
|
|
logger.info(f"Loaded {len(self.profiles)} profiles and app settings.")
|
|
except (json.JSONDecodeError, IOError) as e:
|
|
logger.error(f"Failed to load or parse profiles file: {e}. Starting fresh.")
|
|
self.profiles = {}
|
|
self.settings = {
|
|
"bundle_path": str(Path.home() / "RepoSyncBundles"),
|
|
"git_timeout": 600
|
|
}
|
|
|
|
def save_data(self):
|
|
"""Saves both profiles and settings to the JSON file."""
|
|
logger.info(f"Saving data to: {self.profiles_path}")
|
|
data_to_save = {
|
|
"profiles": self.profiles,
|
|
"settings": self.settings
|
|
}
|
|
try:
|
|
with open(self.profiles_path, "w", encoding="utf-8") as f:
|
|
json.dump(data_to_save, f, indent=4)
|
|
except IOError as e:
|
|
logger.error(f"Failed to save profiles file: {e}")
|
|
|
|
def get_profile(self, name: str) -> Optional[Dict]:
|
|
"""Retrieves a single profile by name."""
|
|
return self.profiles.get(name)
|
|
|
|
def get_all_profiles(self) -> Dict[str, Dict]:
|
|
"""Returns all loaded profiles."""
|
|
return self.profiles
|
|
|
|
def get_profile_names(self) -> List[str]:
|
|
"""Returns a list of all profile names."""
|
|
return list(self.profiles.keys())
|
|
|
|
def add_or_update_profile(self, name: str, data: Dict):
|
|
"""Adds a new profile or updates an existing one."""
|
|
if not name.strip(): raise ValueError("Profile name cannot be empty.")
|
|
self.profiles[name] = data
|
|
self.save_data()
|
|
|
|
def delete_profile(self, name: str):
|
|
"""Deletes a profile by name."""
|
|
if name in self.profiles:
|
|
del self.profiles[name]
|
|
self.save_data()
|
|
|
|
def get_setting(self, key: str, default: Any = None) -> Any:
|
|
"""Gets a specific application setting."""
|
|
return self.settings.get(key, default)
|
|
|
|
def set_setting(self, key: str, value: Any):
|
|
"""Sets an application setting and saves it."""
|
|
logger.info(f"Updating setting '{key}' to '{value}'")
|
|
self.settings[key] = value
|
|
self.save_data() |