# --- FILE: remote_actions.py --- import os import log_handler from git_commands import GitCommands, GitCommandError class RemoteActionHandler: """ Handles the execution logic for remote Git repository actions. """ def __init__(self, git_commands: GitCommands): """ Initializes the RemoteActionHandler. Args: git_commands (GitCommands): Instance for executing Git commands. Raises: TypeError: If git_commands argument is not a GitCommands instance. """ if not isinstance(git_commands, GitCommands): raise TypeError("RemoteActionHandler requires a GitCommands instance.") self.git_commands = git_commands log_handler.log_debug("RemoteActionHandler initialized.", func_name="__init__") def apply_remote_config(self, repo_path: str, remote_name: str, remote_url: str): """ Ensures the specified remote configuration exists in the local repository. Adds the remote if it doesn't exist, or updates the URL if the name exists but the URL is different. Args: repo_path (str): Path to the local repository. remote_name (str): The desired name for the remote (e.g., 'origin'). remote_url (str): The URL of the remote repository. Returns: bool: True if the configuration was applied successfully or already existed, False otherwise. Raises: ValueError: If input arguments are invalid. GitCommandError: If Git commands fail. """ func_name = "apply_remote_config" log_handler.log_info( f"Applying remote config in '{repo_path}': Name='{remote_name}', URL='{remote_url}'", func_name=func_name, ) # --- Input Validation --- if not repo_path or not os.path.isdir(repo_path): raise ValueError(f"Invalid repository path: '{repo_path}'") if not remote_name or remote_name.isspace(): raise ValueError("Remote name cannot be empty.") if not remote_url or remote_url.isspace(): # Allow removing remote by setting empty URL? Maybe not here. Assume URL is required. raise ValueError("Remote URL cannot be empty.") if not os.path.exists(os.path.join(repo_path, ".git")): raise ValueError(f"Directory '{repo_path}' is not a Git repository.") try: # Check existing remotes existing_remotes = self.git_commands.get_remotes( repo_path ) # Need to implement this in GitCommands if remote_name in existing_remotes: # Remote name exists, check if URL matches current_url = existing_remotes[remote_name] if current_url == remote_url: log_handler.log_info( f"Remote '{remote_name}' already configured correctly.", func_name=func_name, ) return True # Nothing to do else: # URL differs, update it log_handler.log_info( f"Updating URL for existing remote '{remote_name}'.", func_name=func_name, ) log_handler.log_debug( f" Old URL: {current_url}", func_name=func_name ) log_handler.log_debug( f" New URL: {remote_url}", func_name=func_name ) success = self.git_commands.set_remote_url( repo_path, remote_name, remote_url ) if success: log_handler.log_info( f"URL for remote '{remote_name}' updated successfully.", func_name=func_name, ) return True else: # set_remote_url should raise on error, but check anyway log_handler.log_error( f"Failed to update URL for remote '{remote_name}'.", func_name=func_name, ) return False else: # Remote name does not exist, add it log_handler.log_info( f"Adding new remote '{remote_name}' with URL '{remote_url}'.", func_name=func_name, ) success = self.git_commands.add_remote( repo_path, remote_name, remote_url ) if success: log_handler.log_info( f"Remote '{remote_name}' added successfully.", func_name=func_name, ) return True else: # add_remote should raise on error log_handler.log_error( f"Failed to add remote '{remote_name}'.", func_name=func_name ) return False except (GitCommandError, ValueError) as e: log_handler.log_error( f"Failed to apply remote config for '{remote_name}': {e}", func_name=func_name, ) raise # Re-raise the specific error for the caller (worker) to handle except Exception as e: log_handler.log_exception( f"Unexpected error applying remote config for '{remote_name}': {e}", func_name=func_name, ) # Wrap unexpected errors in GitCommandError or a custom one if needed raise GitCommandError(f"Unexpected error: {e}") from e # --- Placeholder for future remote methods --- def execute_remote_fetch(self, repo_path: str, remote_name: str): # To be implemented: Calls git_commands.git_fetch pass def execute_remote_pull(self, repo_path: str, remote_name: str, branch_name: str): # To be implemented: Calls git_commands.git_pull, handles conflicts pass def execute_remote_push(self, repo_path: str, remote_name: str, branch_name: str): # To be implemented: Calls git_commands.git_push, handles upstream/errors pass def execute_push_tags(self, repo_path: str, remote_name: str): # To be implemented: Calls git_commands.git_push_tags pass # --- END OF FILE remote_actions.py ---