change gui with notebook tab

This commit is contained in:
VALLONGOL 2025-04-14 09:02:34 +02:00
parent 23a5c593ed
commit a982c35c7d
7 changed files with 2682 additions and 2681 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,17 @@
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(
['GitUtility.py'],
pathex=[],
binaries=[],
datas=[('git_svn_sync.ini', '.')],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
a = Analysis(scripts=['C:\\src\\____GitProjects\\GitUtility\\GitUtility.py'], pathex=['C:\\src\\____GitProjects\\GitUtility'], binaries=[], datas=[('C:\\src\\____GitProjects\\GitUtility\\git_svn_sync.ini', '.')], hiddenimports=[], hookspath=[], runtime_hooks=[], excludes=[], win_no_prefer_redirects=False, win_private_assemblies=False, cipher=None, noarchive=False,)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='GitUtility',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='GitUtility',
)
pyz = PYZ(a.pure, a.zipped_data, cipher=None)
exe = EXE(pyz, a.scripts, a.binaries, a.zipfiles, a.datas, [], name='GitUtility',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,)
coll = COLLECT(exe, a.binaries, a.zipfiles, a.datas, strip=False, upx=True, upx_exclude=[], name='GitUtility',)

View File

@ -6,10 +6,13 @@ import os
from git_commands import GitCommands, GitCommandError
from backup_handler import BackupHandler
class ActionHandler:
"""Handles the execution logic for core application actions."""
def __init__(self, logger, git_commands: GitCommands, backup_handler: BackupHandler):
def __init__(
self, logger, git_commands: GitCommands, backup_handler: BackupHandler
):
"""
Initializes the ActionHandler.
@ -22,10 +25,15 @@ class ActionHandler:
self.git_commands = git_commands
self.backup_handler = backup_handler
def _perform_backup_if_enabled(self, svn_path, profile_name,
autobackup_enabled, backup_base_dir,
excluded_extensions, excluded_dirs):
def _perform_backup_if_enabled(
self,
svn_path,
profile_name,
autobackup_enabled,
backup_base_dir,
excluded_extensions,
excluded_dirs,
):
"""
Performs backup if enabled. Raises IOError on backup failure.
@ -42,7 +50,7 @@ class ActionHandler:
"""
if not autobackup_enabled:
self.logger.debug("Autobackup disabled, skipping backup.")
return # Backup not needed, proceed successfully
return # Backup not needed, proceed successfully
self.logger.info("Autobackup enabled. Starting backup...")
try:
@ -53,18 +61,17 @@ class ActionHandler:
backup_base_dir,
profile_name,
excluded_extensions,
excluded_dirs
excluded_dirs,
)
# Log success if backup handler doesn't raise an error
self.logger.info(f"Backup completed successfully: {backup_path}")
# No explicit return value needed on success
except Exception as backup_e:
# Log error and re-raise as IOError to signal critical failure
self.logger.error(f"Backup failed: {backup_e}", exc_info=True)
# Standardize on IOError for backup failures passed up
raise IOError(f"Autobackup failed: {backup_e}") from backup_e
# Log error and re-raise as IOError to signal critical failure
self.logger.error(f"Backup failed: {backup_e}", exc_info=True)
# Standardize on IOError for backup failures passed up
raise IOError(f"Autobackup failed: {backup_e}") from backup_e
def execute_prepare_repo(self, svn_path):
"""
@ -98,11 +105,18 @@ class ActionHandler:
self.logger.error(f"Failed to prepare repository: {e}", exc_info=True)
raise
def execute_create_bundle(self, svn_path, bundle_full_path, profile_name,
autobackup_enabled, backup_base_dir,
autocommit_enabled, commit_message,
excluded_extensions, excluded_dirs):
def execute_create_bundle(
self,
svn_path,
bundle_full_path,
profile_name,
autobackup_enabled,
backup_base_dir,
autocommit_enabled,
commit_message,
excluded_extensions,
excluded_dirs,
):
"""
Executes 'create bundle', including backup and commit logic.
@ -126,8 +140,12 @@ class ActionHandler:
# --- Backup Step ---
# _perform_backup_if_enabled raises IOError on failure
self._perform_backup_if_enabled(
svn_path, profile_name, autobackup_enabled, backup_base_dir,
excluded_extensions, excluded_dirs
svn_path,
profile_name,
autobackup_enabled,
backup_base_dir,
excluded_extensions,
excluded_dirs,
)
# --- Autocommit Step ---
@ -139,9 +157,14 @@ class ActionHandler:
if has_changes:
self.logger.info("Changes detected, performing autocommit...")
# Use provided message or generate default
commit_msg_to_use = commit_message if commit_message else \
f"Autocommit '{profile_name}' before bundle"
self.logger.debug(f"Using autocommit message: '{commit_msg_to_use}'")
commit_msg_to_use = (
commit_message
if commit_message
else f"Autocommit '{profile_name}' before bundle"
)
self.logger.debug(
f"Using autocommit message: '{commit_msg_to_use}'"
)
# Perform commit (raises error on failure, returns bool)
self.git_commands.git_commit(svn_path, commit_msg_to_use)
# Log based on return value? git_commit already logs detail.
@ -162,27 +185,33 @@ class ActionHandler:
bundle_exists = os.path.exists(bundle_full_path)
bundle_not_empty = bundle_exists and os.path.getsize(bundle_full_path) > 0
if bundle_exists and bundle_not_empty:
self.logger.info("Git bundle created successfully.")
return bundle_full_path # Return path on success
self.logger.info("Git bundle created successfully.")
return bundle_full_path # Return path on success
else:
# Bundle empty or not created (logged by GitCommands)
self.logger.warning("Bundle file not created or is empty.")
if bundle_exists and not bundle_not_empty:
# Clean up empty file
try:
os.remove(bundle_full_path)
except OSError:
self.logger.warning("Could not remove empty bundle file.")
return None # Indicate non-fatal issue (empty bundle)
# Bundle empty or not created (logged by GitCommands)
self.logger.warning("Bundle file not created or is empty.")
if bundle_exists and not bundle_not_empty:
# Clean up empty file
try:
os.remove(bundle_full_path)
except OSError:
self.logger.warning("Could not remove empty bundle file.")
return None # Indicate non-fatal issue (empty bundle)
except Exception as bundle_e:
# Log and re-raise bundle creation errors
self.logger.error(f"Bundle creation failed: {bundle_e}", exc_info=True)
raise bundle_e
# Log and re-raise bundle creation errors
self.logger.error(f"Bundle creation failed: {bundle_e}", exc_info=True)
raise bundle_e
def execute_fetch_bundle(self, svn_path, bundle_full_path, profile_name,
autobackup_enabled, backup_base_dir,
excluded_extensions, excluded_dirs):
def execute_fetch_bundle(
self,
svn_path,
bundle_full_path,
profile_name,
autobackup_enabled,
backup_base_dir,
excluded_extensions,
excluded_dirs,
):
"""
Executes the 'fetch bundle' action, including backup logic.
@ -195,8 +224,12 @@ class ActionHandler:
# --- Backup Step ---
# Raises IOError on failure
self._perform_backup_if_enabled(
svn_path, profile_name, autobackup_enabled, backup_base_dir,
excluded_extensions, excluded_dirs
svn_path,
profile_name,
autobackup_enabled,
backup_base_dir,
excluded_extensions,
excluded_dirs,
)
# --- Fetch and Merge Step ---
@ -207,10 +240,9 @@ class ActionHandler:
self.logger.info("Fetch/merge process completed successfully.")
# No return needed, success indicated by no exception
except Exception as fetch_e:
# Log and re-raise any error from fetch/merge
self.logger.error(f"Fetch/merge failed: {fetch_e}", exc_info=True)
raise fetch_e
# Log and re-raise any error from fetch/merge
self.logger.error(f"Fetch/merge failed: {fetch_e}", exc_info=True)
raise fetch_e
def execute_manual_commit(self, svn_path, commit_message):
"""
@ -227,9 +259,9 @@ class ActionHandler:
GitCommandError/Exception: If commit command fails.
"""
if not commit_message:
# This validation should ideally happen before calling this method
self.logger.error("Manual commit attempt with empty message.")
raise ValueError("Commit message cannot be empty.")
# This validation should ideally happen before calling this method
self.logger.error("Manual commit attempt with empty message.")
raise ValueError("Commit message cannot be empty.")
self.logger.info(f"Executing manual commit for: {svn_path}")
try:
@ -242,7 +274,6 @@ class ActionHandler:
self.logger.error(f"Manual commit failed: {e}", exc_info=True)
raise
def execute_create_tag(self, svn_path, commit_message, tag_name, tag_message):
"""
Executes tag creation, including pre-commit using commit_message if needed.
@ -270,22 +301,23 @@ class ActionHandler:
# Block if changes exist but no message provided
msg = "Changes exist. Commit message required before tagging."
self.logger.error(f"Tag creation blocked: {msg}")
raise ValueError(msg) # Raise error for UI layer
raise ValueError(msg) # Raise error for UI layer
# Perform the pre-tag commit with the provided message
self.logger.debug(f"Performing pre-tag commit: '{commit_message}'")
# git_commit raises error on failure, returns bool otherwise
commit_made = self.git_commands.git_commit(svn_path, commit_message)
# Log based on return value? git_commit logs details.
self.logger.info(f"Pre-tag commit attempt finished (made={commit_made}).")
self.logger.info(
f"Pre-tag commit attempt finished (made={commit_made})."
)
else:
self.logger.info("No uncommitted changes detected before tagging.")
except Exception as e:
# Catch errors during status check or commit
self.logger.error(f"Error during pre-tag commit step: {e}",
exc_info=True)
raise # Re-raise commit-related errors
self.logger.error(f"Error during pre-tag commit step: {e}", exc_info=True)
raise # Re-raise commit-related errors
# --- Create Tag Step ---
self.logger.info(f"Proceeding to create tag '{tag_name}'...")
@ -294,13 +326,11 @@ class ActionHandler:
# It raises ValueError for invalid name, GitCommandError for exists/fail
self.git_commands.create_tag(svn_path, tag_name, tag_message)
self.logger.info(f"Tag '{tag_name}' created successfully.")
return True # Indicate success
return True # Indicate success
except Exception as e:
# Catch errors during tag creation
self.logger.error(f"Failed to create tag '{tag_name}': {e}",
exc_info=True)
raise # Re-raise tag creation errors
self.logger.error(f"Failed to create tag '{tag_name}': {e}", exc_info=True)
raise # Re-raise tag creation errors
def execute_checkout_tag(self, svn_path, tag_name):
"""
@ -327,31 +357,30 @@ class ActionHandler:
if has_changes:
msg = "Uncommitted changes exist. Commit or stash first."
self.logger.error(f"Checkout blocked: {msg}")
raise ValueError(msg) # Raise specific error for UI
raise ValueError(msg) # Raise specific error for UI
self.logger.debug("No uncommitted changes found.")
except Exception as e:
# Catch errors during status check
self.logger.error(f"Status check error before checkout: {e}",
exc_info=True)
raise # Re-raise status check errors
# Catch errors during status check
self.logger.error(f"Status check error before checkout: {e}", exc_info=True)
raise # Re-raise status check errors
# --- Execute Checkout ---
try:
# git_commands.checkout_tag raises error on failure
checkout_success = self.git_commands.checkout_tag(svn_path, tag_name)
if checkout_success:
self.logger.info(f"Tag '{tag_name}' checked out.")
return True
self.logger.info(f"Tag '{tag_name}' checked out.")
return True
else:
# This path should theoretically not be reached
self.logger.error("Checkout command reported failure unexpectedly.")
raise GitCommandError("Checkout failed for unknown reason.")
# This path should theoretically not be reached
self.logger.error("Checkout command reported failure unexpectedly.")
raise GitCommandError("Checkout failed for unknown reason.")
except Exception as e:
# Catch errors during checkout (e.g., tag not found)
self.logger.error(f"Failed to checkout tag '{tag_name}': {e}",
exc_info=True)
raise # Re-raise checkout errors
self.logger.error(
f"Failed to checkout tag '{tag_name}': {e}", exc_info=True
)
raise # Re-raise checkout errors
# --- Branch Actions ---
def execute_create_branch(self, svn_path, branch_name, start_point=None):
@ -363,8 +392,10 @@ class ActionHandler:
Returns: True on success.
Raises: GitCommandError/ValueError/Exception on failure.
"""
self.logger.info(f"Executing create branch '{branch_name}' "
f"from '{start_point or 'HEAD'}'.")
self.logger.info(
f"Executing create branch '{branch_name}' "
f"from '{start_point or 'HEAD'}'."
)
try:
# Delegate to git_commands, raises error on failure
self.git_commands.create_branch(svn_path, branch_name, start_point)
@ -374,7 +405,6 @@ class ActionHandler:
self.logger.error(f"Failed to create branch: {e}", exc_info=True)
raise
def execute_switch_branch(self, svn_path, branch_name):
"""
Executes branch switch after checking for changes.
@ -394,13 +424,12 @@ class ActionHandler:
if has_changes:
msg = "Uncommitted changes exist. Commit or stash first."
self.logger.error(f"Switch blocked: {msg}")
raise ValueError(msg) # Raise specific error for UI
raise ValueError(msg) # Raise specific error for UI
self.logger.debug("No uncommitted changes found.")
except Exception as e:
# Catch errors during status check
self.logger.error(f"Status check error before switch: {e}",
exc_info=True)
raise # Re-raise status check errors
# Catch errors during status check
self.logger.error(f"Status check error before switch: {e}", exc_info=True)
raise # Re-raise status check errors
# --- Execute Switch ---
try:
@ -409,11 +438,11 @@ class ActionHandler:
return success
except Exception as e:
# Catch errors during switch (e.g., branch not found)
self.logger.error(f"Failed switch to branch '{branch_name}': {e}",
exc_info=True)
self.logger.error(
f"Failed switch to branch '{branch_name}': {e}", exc_info=True
)
raise
def execute_delete_branch(self, svn_path, branch_name, force=False):
"""
Executes branch deletion.
@ -434,11 +463,11 @@ class ActionHandler:
return success
except Exception as e:
# Catch errors (like not merged, needs force)
self.logger.error(f"Failed delete branch '{branch_name}': {e}",
exc_info=True)
self.logger.error(
f"Failed delete branch '{branch_name}': {e}", exc_info=True
)
raise
def execute_delete_tag(self, svn_path, tag_name):
"""
Executes deletion for the specified tag.
@ -461,9 +490,8 @@ class ActionHandler:
# Delegate deletion to GitCommands method
# This raises GitCommandError if tag not found or other git error
success = self.git_commands.delete_tag(svn_path, tag_name)
return success # Should be True if no exception
return success # Should be True if no exception
except Exception as e:
# Catch and re-raise errors from git_commands.delete_tag
self.logger.error(f"Failed to delete tag '{tag_name}': {e}",
exc_info=True)
raise # Re-raise for the UI layer to handle
self.logger.error(f"Failed to delete tag '{tag_name}': {e}", exc_info=True)
raise # Re-raise for the UI layer to handle

View File

@ -4,6 +4,7 @@ import datetime
import zipfile
import logging
class BackupHandler:
"""Handles the creation of ZIP backups with exclusions."""
@ -20,8 +21,14 @@ class BackupHandler:
# to ConfigManager based on the current profile selected in the UI.
# The create_zip_backup method now receives the parsed exclusions directly.
def create_zip_backup(self, source_repo_path, backup_base_dir,
profile_name, excluded_extensions, excluded_dirs_base):
def create_zip_backup(
self,
source_repo_path,
backup_base_dir,
profile_name,
excluded_extensions,
excluded_dirs_base,
):
"""
Creates a timestamped ZIP backup of the source repository directory,
respecting provided exclusions.
@ -60,16 +67,17 @@ class BackupHandler:
# exist_ok=True prevents error if directory already exists
os.makedirs(backup_base_dir, exist_ok=True)
except OSError as e:
self.logger.error(f"Cannot create backup directory: {e}",
exc_info=True)
self.logger.error(f"Cannot create backup directory: {e}", exc_info=True)
# Re-raise as IOError for the caller to potentially handle differently
raise IOError(f"Could not create backup directory: {e}") from e
# --- 2. Construct Backup Filename ---
now_str = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
# Sanitize profile name for use in filename (remove potentially invalid chars)
safe_profile = "".join(c for c in profile_name
if c.isalnum() or c in '_-').rstrip() or "profile"
safe_profile = (
"".join(c for c in profile_name if c.isalnum() or c in "_-").rstrip()
or "profile"
)
backup_filename = f"{now_str}_backup_{safe_profile}.zip"
backup_full_path = os.path.join(backup_base_dir, backup_filename)
self.logger.info(f"Target backup ZIP file: {backup_full_path}")
@ -78,13 +86,13 @@ class BackupHandler:
files_added = 0
files_excluded = 0
dirs_excluded = 0
zip_f = None # Initialize zip file object outside try block
zip_f = None # Initialize zip file object outside try block
try:
# Open ZIP file with settings for compression and large files
zip_f = zipfile.ZipFile(backup_full_path, 'w',
compression=zipfile.ZIP_DEFLATED,
allowZip64=True)
zip_f = zipfile.ZipFile(
backup_full_path, "w", compression=zipfile.ZIP_DEFLATED, allowZip64=True
)
# Walk through the source directory tree
for root, dirs, files in os.walk(source_repo_path, topdown=True):
@ -101,8 +109,8 @@ class BackupHandler:
if excluded_dirs_now:
dirs_excluded += len(excluded_dirs_now)
for ex_dir in excluded_dirs_now:
path_excluded = os.path.join(root, ex_dir)
self.logger.debug(f"Excluding directory: {path_excluded}")
path_excluded = os.path.join(root, ex_dir)
self.logger.debug(f"Excluding directory: {path_excluded}")
# --- File Exclusion and Addition ---
for filename in files:
@ -111,12 +119,14 @@ class BackupHandler:
file_ext_lower = file_ext.lower()
# Check exclusion rules (case-insensitive filename or extension)
if filename.lower() in excluded_dirs_base or \
file_ext_lower in excluded_extensions:
if (
filename.lower() in excluded_dirs_base
or file_ext_lower in excluded_extensions
):
path_excluded = os.path.join(root, filename)
self.logger.debug(f"Excluding file: {path_excluded}")
files_excluded += 1
continue # Skip this file
continue # Skip this file
# If not excluded, add file to ZIP
file_full_path = os.path.join(root, filename)
@ -129,14 +139,14 @@ class BackupHandler:
files_added += 1
# Log progress periodically for large backups
if files_added % 500 == 0:
self.logger.debug(f"Added {files_added} files...")
self.logger.debug(f"Added {files_added} files...")
except Exception as write_e:
# Log error writing a specific file but allow backup to continue
self.logger.error(
f"Error writing file '{file_full_path}' to ZIP: {write_e}",
exc_info=True
)
# Consider marking the backup as potentially incomplete
# Log error writing a specific file but allow backup to continue
self.logger.error(
f"Error writing file '{file_full_path}' to ZIP: {write_e}",
exc_info=True,
)
# Consider marking the backup as potentially incomplete
# Log final summary after successful walk and write attempts
self.logger.info(f"Backup ZIP creation finished: {backup_full_path}")
@ -148,15 +158,15 @@ class BackupHandler:
return backup_full_path
except (OSError, zipfile.BadZipFile) as e:
# Handle OS errors (permissions, disk space) and ZIP format errors
self.logger.error(f"Error creating backup ZIP: {e}", exc_info=True)
# Re-raise as IOError for the caller to potentially handle specifically
raise IOError(f"Failed to create backup ZIP: {e}") from e
# Handle OS errors (permissions, disk space) and ZIP format errors
self.logger.error(f"Error creating backup ZIP: {e}", exc_info=True)
# Re-raise as IOError for the caller to potentially handle specifically
raise IOError(f"Failed to create backup ZIP: {e}") from e
except Exception as e:
# Catch any other unexpected error during the process
self.logger.exception(f"Unexpected error during ZIP backup: {e}")
# Re-raise the original exception
raise
# Catch any other unexpected error during the process
self.logger.exception(f"Unexpected error during ZIP backup: {e}")
# Re-raise the original exception
raise
finally:
# Ensure the ZIP file is always closed, even if errors occurred
if zip_f:
@ -167,16 +177,16 @@ class BackupHandler:
zip_exists = os.path.exists(backup_full_path)
# Check if zip exists but no files were actually added
if zip_exists and files_added == 0:
self.logger.warning(f"Backup ZIP is empty: {backup_full_path}")
try:
# Attempt to remove the empty zip file
os.remove(backup_full_path)
self.logger.info("Removed empty backup ZIP file.")
except OSError as rm_e:
# Log error if removal fails, but don't stop execution
self.logger.error(f"Failed remove empty backup ZIP: {rm_e}")
self.logger.warning(f"Backup ZIP is empty: {backup_full_path}")
try:
# Attempt to remove the empty zip file
os.remove(backup_full_path)
self.logger.info("Removed empty backup ZIP file.")
except OSError as rm_e:
# Log error if removal fails, but don't stop execution
self.logger.error(f"Failed remove empty backup ZIP: {rm_e}")
elif not zip_exists and files_added > 0:
# This case indicates an issue if files were supposedly added
# but the zip file doesn't exist at the end (perhaps deleted?)
self.logger.error("Backup process finished but ZIP file missing.")
# Consider raising an error here if this state is critical
# This case indicates an issue if files were supposedly added
# but the zip file doesn't exist at the end (perhaps deleted?)
self.logger.error("Backup process finished but ZIP file missing.")
# Consider raising an error here if this state is critical

File diff suppressed because it is too large Load Diff

1747
gui.py

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,10 @@
# profile_handler.py
import logging
# Assuming ConfigManager handles its own constants now
from config_manager import ConfigManager, DEFAULT_PROFILE, DEFAULT_BACKUP_DIR
class ProfileHandler:
"""Handles loading, saving, adding, removing profiles via ConfigManager."""
@ -50,15 +52,16 @@ class ProfileHandler:
# Convert loaded string values back to appropriate types if needed
# Example: Booleans
profile_data["autocommit"] = \
profile_data["autocommit"] = (
str(profile_data.get("autocommit", "False")).lower() == "true"
profile_data["autobackup"] = \
)
profile_data["autobackup"] = (
str(profile_data.get("autobackup", "False")).lower() == "true"
)
self.logger.debug(f"Loaded data for '{profile_name}': {profile_data}")
return profile_data
def save_profile_data(self, profile_name, profile_data):
"""
Saves the provided data dictionary to the specified profile name.
@ -90,21 +93,19 @@ class ProfileHandler:
# Assume other types can be directly converted to string
value_to_save = str(value) if value is not None else ""
self.config_manager.set_profile_option(
profile_name, key, value_to_save
)
self.config_manager.set_profile_option(profile_name, key, value_to_save)
# Persist changes to the configuration file
self.config_manager.save_config()
self.logger.info(f"Profile '{profile_name}' saved successfully.")
return True
except Exception as e:
self.logger.error(f"Error saving profile '{profile_name}': {e}",
exc_info=True)
self.logger.error(
f"Error saving profile '{profile_name}': {e}", exc_info=True
)
# Let the caller (main app) show the error message
return False
def add_new_profile(self, profile_name):
"""
Adds a new profile with default settings.
@ -129,13 +130,13 @@ class ProfileHandler:
defaults = self.config_manager._get_expected_keys_with_defaults()
defaults["bundle_name"] = f"{profile_name}_repo.bundle"
defaults["bundle_name_updated"] = f"{profile_name}_update.bundle"
defaults["svn_working_copy_path"] = "" # Start empty
defaults["usb_drive_path"] = "" # Start empty
defaults["svn_working_copy_path"] = "" # Start empty
defaults["usb_drive_path"] = "" # Start empty
# Set all options for the new profile section
# ConfigManager.set_profile_option creates the section if needed
for key, value in defaults.items():
self.config_manager.set_profile_option(profile_name, key, value)
self.config_manager.set_profile_option(profile_name, key, value)
# Save the configuration file
self.config_manager.save_config()
@ -143,11 +144,11 @@ class ProfileHandler:
return True
except Exception as e:
# Log unexpected errors during profile addition
self.logger.error(f"Error adding profile '{profile_name}': {e}",
exc_info=True)
self.logger.error(
f"Error adding profile '{profile_name}': {e}", exc_info=True
)
return False
def remove_existing_profile(self, profile_name):
"""
Removes an existing profile (cannot remove the default profile).
@ -180,10 +181,13 @@ class ProfileHandler:
return True
else:
# ConfigManager should log the reason for failure
self.logger.error(f"ConfigManager reported failure removing '{profile_name}'.")
self.logger.error(
f"ConfigManager reported failure removing '{profile_name}'."
)
return False
except Exception as e:
# Log unexpected errors during removal
self.logger.error(f"Error removing profile '{profile_name}': {e}",
exc_info=True)
self.logger.error(
f"Error removing profile '{profile_name}': {e}", exc_info=True
)
return False