146 lines
6.7 KiB
Python
146 lines
6.7 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Handles the business logic for the repository transformation workflow.
|
|
|
|
This handler validates user input, confirms destructive actions, and orchestrates
|
|
the asynchronous execution of the transformation process, which includes
|
|
history rewriting, repository renaming, and updating the local Gitea remote.
|
|
"""
|
|
|
|
from typing import TYPE_CHECKING, Dict, Any, Optional
|
|
import os
|
|
|
|
from gitutility.async_tasks import async_workers
|
|
from gitutility.logging_setup import log_handler
|
|
from gitutility.commands.git_commands import GitCommandError
|
|
|
|
# Forward reference for type hinting to avoid circular import
|
|
if TYPE_CHECKING:
|
|
from ..app import GitSvnSyncApp
|
|
|
|
|
|
class TransformationHandler:
|
|
"""
|
|
Manages the logic for the repository transformation feature.
|
|
"""
|
|
|
|
def __init__(self, app: "GitSvnSyncApp"):
|
|
"""
|
|
Initializes the TransformationHandler.
|
|
|
|
Args:
|
|
app: The main application instance.
|
|
"""
|
|
self.app = app
|
|
self.main_frame = app.main_frame
|
|
self.git_commands = app.git_commands
|
|
self.config_manager = app.config_manager
|
|
log_handler.log_debug("TransformationHandler initialized.", func_name="__init__")
|
|
|
|
def start_transformation(self, target_details: Dict[str, str]) -> None:
|
|
"""
|
|
Validates inputs and starts the asynchronous repository transformation process.
|
|
|
|
Args:
|
|
target_details: A dictionary containing 'repo_name', 'author_name',
|
|
and 'author_email' for the target identity.
|
|
"""
|
|
func_name = "start_transformation"
|
|
log_handler.log_info(f"--- Action Triggered: Start Repository Transformation ---", func_name=func_name)
|
|
|
|
# --- 1. Validazione degli Input e dello Stato del Sistema ---
|
|
|
|
# Valida i dettagli forniti dall'utente
|
|
target_repo_name = target_details.get("repo_name")
|
|
target_author_name = target_details.get("author_name")
|
|
target_author_email = target_details.get("author_email")
|
|
|
|
if not all([target_repo_name, target_author_name, target_author_email]):
|
|
self.main_frame.show_error("Input Error", "All target identity fields are required.")
|
|
log_handler.log_error("Validation failed: Missing target identity details.", func_name=func_name)
|
|
return
|
|
|
|
# Valida il repository sorgente (quello del profilo corrente)
|
|
source_repo_path = self.app._get_and_validate_svn_path("Repository Transformation")
|
|
if not source_repo_path or not self.app._is_repo_ready(source_repo_path):
|
|
self.main_frame.show_error("Repository Error", "The current profile's repository is not valid or not ready.")
|
|
log_handler.log_error("Validation failed: Source repository not valid.", func_name=func_name)
|
|
return
|
|
|
|
source_repo_basename = os.path.basename(source_repo_path)
|
|
# If the target name equals the source, allow the user to proceed with
|
|
# an author-only transformation (no folder/profile rename) or cancel.
|
|
rename_repo = True
|
|
if source_repo_basename == target_repo_name:
|
|
# Ask the user whether to continue with author-only rewrite
|
|
proceed_msg = (
|
|
"The target repository name is the SAME as the source repository.\n\n"
|
|
"You can either:\n"
|
|
" - Cancel and change the target repository name, or\n"
|
|
" - Proceed with an AUTHOR-ONLY transformation (this will rewrite commit authors/emails but WILL NOT rename the repository folder nor create a new profile).\n\n"
|
|
"Do you want to proceed with AUTHOR-ONLY transformation?"
|
|
)
|
|
if not self.main_frame.ask_yes_no("Same Repository Name", proceed_msg):
|
|
self.main_frame.update_status_bar("Transformation cancelled.")
|
|
log_handler.log_info("User cancelled the transformation due to same repository name.", func_name=func_name)
|
|
return
|
|
rename_repo = False
|
|
|
|
# Controlla se il repository ha modifiche non committate
|
|
try:
|
|
if self.git_commands.git_status_has_changes(source_repo_path):
|
|
self.main_frame.show_warning(
|
|
"Action Blocked",
|
|
"The repository has uncommitted changes. Please commit or stash them before starting a transformation."
|
|
)
|
|
log_handler.log_warning("Validation failed: Repository is not clean.", func_name=func_name)
|
|
return
|
|
except GitCommandError as e:
|
|
self.main_frame.show_error("Git Error", f"Failed to check repository status:\n{e}")
|
|
log_handler.log_error(f"Validation failed: Could not get repo status. {e}", func_name=func_name)
|
|
return
|
|
|
|
# --- 2. Dialogo di Conferma Finale ---
|
|
|
|
confirmation_message = (
|
|
f"You are about to perform a PERMANENT and DESTRUCTIVE transformation.\n\n"
|
|
f"1. Source Repository: '{source_repo_basename}'\n"
|
|
f" at path: '{source_repo_path}'\n\n"
|
|
f"2. All commits will be rewritten with author:\n"
|
|
f" '{target_author_name} <{target_author_email}>'\n\n"
|
|
f"3. The local repository folder will be RENAMED to:\n"
|
|
f" '{target_repo_name}'\n\n"
|
|
f"4. A new profile '{target_repo_name}' will be created in this tool.\n\n"
|
|
f"This action CANNOT be undone. It is strongly advised to have a backup.\n\n"
|
|
f"Are you absolutely sure you want to proceed?"
|
|
)
|
|
|
|
if not self.main_frame.ask_yes_no("Confirm Destructive Transformation", confirmation_message):
|
|
self.main_frame.update_status_bar("Transformation cancelled.")
|
|
log_handler.log_info("User cancelled the transformation.", func_name=func_name)
|
|
return
|
|
|
|
# --- 3. Avvio del Worker Asincrono ---
|
|
|
|
log_handler.log_info("User confirmed. Starting asynchronous transformation worker.", func_name=func_name)
|
|
|
|
# Prepara gli argomenti per il worker
|
|
args = (
|
|
# Passeremo le istanze necessarie, non solo i valori, per dare flessibilità al worker
|
|
self.git_commands,
|
|
self.config_manager,
|
|
source_repo_path,
|
|
target_repo_name,
|
|
target_author_name,
|
|
target_author_email,
|
|
rename_repo,
|
|
)
|
|
|
|
self.app._start_async_operation(
|
|
worker_func=async_workers.run_repository_transformation_async, # Creeremo questo worker tra poco
|
|
args_tuple=args,
|
|
context_dict={
|
|
"context": "repository_transformation",
|
|
"status_msg": f"Transforming '{source_repo_basename}' to '{target_repo_name}'...",
|
|
},
|
|
) |