Files
ClaudeProjectManager-main/duplicate_methods_analysis.md
Claude Project Manager ec92da8a64 Initial commit
2025-07-07 22:11:38 +02:00

23 KiB

Duplicate Methods Analysis Report - gui/main_window.py

Overview

This report analyzes the duplicate methods found in gui/main_window.py to determine their differences and whether they can be safely consolidated.

1. manage_branches (line 1374 vs line 2336)

First Version (line 1374-1377)

def manage_branches(self, project):
    """Manage git branches"""
    messagebox.showinfo("Branches", "Branch management coming soon")

Second Version (line 2336-2391)

def manage_branches(self, project):
    """Manage branches for a project"""
    from tkinter import simpledialog
    
    git_ops = self.repo_manager.git_ops
    
    # Get current branches
    success, branches = git_ops.branch(Path(project.path), list_all=True)
    
    if success:
        current_branch = None
        branch_list = []
        for line in branches.strip().split('\n'):
            if line.startswith('*'):
                current_branch = line[2:].strip()
                branch_list.append(f"{line.strip()} (aktuell)")
            else:
                branch_list.append(line.strip())
        
        # Show options
        action = messagebox.askyesnocancel(
            "Branch-Verwaltung",
            f"Aktuelle Branches:\n{chr(10).join(branch_list)}\n\n"
            "Ja = Neuen Branch erstellen\n"
            "Nein = Zu anderem Branch wechseln\n"
            "Abbrechen = Schließen"
        )
        
        if action is True:  # Create new branch
            branch_name = simpledialog.askstring(
                "Neuer Branch",
                "Name des neuen Branches:",
                parent=self.root
            )
            if branch_name:
                success, result = git_ops.checkout(Path(project.path), branch_name, create=True)
                if success:
                    messagebox.showinfo("Erfolg", f"Branch '{branch_name}' erstellt und gewechselt")
                else:
                    messagebox.showerror("Fehler", f"Branch-Erstellung fehlgeschlagen: {result}")
                    
        elif action is False:  # Switch branch
            branch_name = simpledialog.askstring(
                "Branch wechseln",
                "Zu welchem Branch wechseln?",
                parent=self.root
            )
            if branch_name:
                success, result = git_ops.checkout(Path(project.path), branch_name)
                if success:
                    messagebox.showinfo("Erfolg", f"Zu Branch '{branch_name}' gewechselt")
                else:
                    messagebox.showerror("Fehler", f"Branch-Wechsel fehlgeschlagen: {result}")
    else:
        messagebox.showerror("Fehler", f"Konnte Branches nicht abrufen: {branches}")

Differences

  • First version: Placeholder implementation showing "coming soon" message
  • Second version: Full implementation with branch listing, creation, and switching functionality
  • Language: First version uses English, second version uses German

Called From

  • Line 1516: self.manage_branches(project) in gitea_operation method

Recommendation

Safe to consolidate: Keep the second version (line 2336) as it contains the actual implementation. The first version is just a placeholder.


First Version (line 1378-1381)

def link_to_gitea(self, project):
    """Link local project to Gitea repository"""
    messagebox.showinfo("Link", "Link functionality coming soon")

Second Version (line 2392-2456)

def link_to_gitea(self, project):
    """Link local project to Gitea repository"""
    from tkinter import simpledialog
    
    # Ask for repository name
    repo_name = simpledialog.askstring(
        "Mit Gitea verknüpfen",
        "Name des Gitea-Repositories:",
        initialvalue=project.name,
        parent=self.root
    )
    
    if repo_name:
        git_ops = self.repo_manager.git_ops
        
        # Check if repo exists on Gitea
        try:
            repo = self.repo_manager.client.get_repository(
                self.repo_manager.client.config.username,
                repo_name
            )
            
            # Add remote
            success, msg = git_ops.add_remote_to_existing_repo(
                Path(project.path),
                self.repo_manager.client.config.username,
                repo_name
            )
            
            if success:
                # Update project with Gitea repo reference
                project.gitea_repo = f"{self.repo_manager.client.config.username}/{repo_name}"
                self.project_manager.update_project(project.id, gitea_repo=project.gitea_repo)
                messagebox.showinfo("Erfolg", f"Erfolgreich mit Repository '{repo_name}' verknüpft!")
            else:
                messagebox.showerror("Fehler", f"Verknüpfung fehlgeschlagen: {msg}")
                
        except Exception as e:
            # Repository doesn't exist, offer to create
            create = messagebox.askyesno(
                "Repository nicht gefunden",
                f"Repository '{repo_name}' existiert nicht.\n\nMöchten Sie es erstellen?"
            )
            
            if create:
                try:
                    # Create repository
                    new_repo = self.repo_manager.create_repository(repo_name, auto_init=False)
                    
                    # Add remote
                    success, msg = git_ops.add_remote_to_existing_repo(
                        Path(project.path),
                        self.repo_manager.client.config.username,
                        repo_name
                    )
                    
                    if success:
                        # Update project
                        project.gitea_repo = f"{self.repo_manager.client.config.username}/{repo_name}"
                        self.project_manager.update_project(project.id, gitea_repo=project.gitea_repo)
                        messagebox.showinfo("Erfolg", 
                                          f"Repository '{repo_name}' erstellt und verknüpft!")
                    else:
                        messagebox.showerror("Fehler", f"Verknüpfung fehlgeschlagen: {msg}")
                        
                except Exception as create_error:
                    messagebox.showerror("Fehler", 
                                       f"Repository-Erstellung fehlgeschlagen: {str(create_error)}")

Differences

  • First version: Placeholder implementation showing "coming soon" message
  • Second version: Full implementation with repository linking, checking existence, and creation option
  • Language: First version uses English, second version uses German

Called From

  • Line 1514: self.link_to_gitea(project) in gitea_operation method

Recommendation

Safe to consolidate: Keep the second version (line 2392) as it contains the actual implementation. The first version is just a placeholder.


3. test_gitea_connection (line 1757 vs line 2457)

First Version (line 1757-1791)

def test_gitea_connection(self, project):
    """Test Gitea connection and show permissions"""
    try:
        # Test API connection
        user_info = self.repo_manager.client.get_user_info()
        
        info = "Gitea-Verbindung erfolgreich!\n\n"
        info += f"Benutzer: {user_info.get('username', 'Unknown')}\n"
        info += f"E-Mail: {user_info.get('email', 'Unknown')}\n"
        info += f"Admin: {'Ja' if user_info.get('is_admin', False) else 'Nein'}\n\n"
        
        # Check organizations
        orgs = self.repo_manager.client.list_user_organizations()
        if orgs:
            info += "Organisationen:\n"
            for org in orgs:
                org_name = org.get('username', org.get('name', 'Unknown'))
                info += f"  • {org_name}"
                
                # Check teams/permissions in org
                teams = self.repo_manager.client.get_user_teams_in_org(org_name)
                if teams:
                    team_names = [t.get('name', 'Unknown') for t in teams]
                    info += f" (Teams: {', '.join(team_names)})"
                info += "\n"
        else:
            info += "Keine Organisationen\n"
        
        info += f"\nServer: {self.repo_manager.client.config.base_url}"
        
        messagebox.showinfo("Verbindungstest", info)
        
    except Exception as e:
        messagebox.showerror("Verbindungsfehler", f"Konnte keine Verbindung zu Gitea herstellen:\n\n{str(e)}")

Second Version (line 2457-2554)

def test_gitea_connection(self, project=None):
    """Test Gitea connection and show detailed information"""
    try:
        # Test basic connection
        user_info = self.repo_manager.client.get_user_info()
        username = user_info.get('username', 'Unknown')
        
        # Get organizations
        orgs = self.repo_manager.client.list_user_organizations()
        org_names = [org['username'] for org in orgs]
        
        # Build info message
        info = f"✅ Gitea Verbindung erfolgreich!\n\n"
        info += f"Benutzer: {username}\n"
        info += f"Server: {self.repo_manager.client.config.base_url}\n"
        info += f"Organisationen: {', '.join(org_names) if org_names else 'Keine'}\n\n"
        
        # Check organization permissions if in org mode
        if hasattr(self, 'gitea_explorer') and self.gitea_explorer.view_mode == "organization":
            org_name = self.gitea_explorer.organization_name
            if org_name:
                teams = self.repo_manager.client.get_user_teams_in_org(org_name)
                if teams:
                    info += f"Teams in {org_name}:\n"
                    for team in teams:
                        info += f"  - {team.get('name', 'Unknown')} "
                        perms = []
                        if team.get('can_create_org_repo'):
                            perms.append("kann Repos erstellen")
                        if team.get('permission') == 'admin':
                            perms.append("Admin")
                        elif team.get('permission') == 'write':
                            perms.append("Schreiben")
                        elif team.get('permission') == 'read':
                            perms.append("Lesen")
                        info += f"({', '.join(perms) if perms else 'keine Rechte'})\n"
                else:
                    info += f"⚠️ Keine Teams in Organisation {org_name} gefunden!\n"
                    info += "Dies könnte der Grund sein, warum Repositories nicht erstellt werden können.\n"
        
        info += "\n"
        
        # If we have a project, show its remote info
        if project:
            project_path = Path(project.path) if hasattr(project, 'path') else Path(project['path'])
            if project_path.exists():
                success, remotes = self.repo_manager.git_ops.remote_list(project_path)
                if success and remotes:
                    info += f"Git Remote URLs:\n{remotes}\n\n"
                
                # Check if .git exists
                if (project_path / '.git').exists():
                    # Get current branch
                    success, branch_out = self.repo_manager.git_ops._run_git_command(
                        ["git", "branch", "--show-current"], cwd=project_path
                    )
                    if success:
                        info += f"Aktueller Branch: {branch_out.strip()}\n"
        
        # List repositories in current mode
        info += "Repositories:\n"
        try:
            if hasattr(self, 'gitea_explorer'):
                if self.gitea_explorer.view_mode == "organization" and self.gitea_explorer.organization_name:
                    # List org repos
                    org_repos = self.repo_manager.list_organization_repositories(self.gitea_explorer.organization_name)
                    info += f"In Organisation {self.gitea_explorer.organization_name}: {len(org_repos)} Repositories\n"
                    for repo in org_repos[:5]:  # Show first 5
                        info += f"  - {repo['name']}\n"
                    if len(org_repos) > 5:
                        info += f"  ... und {len(org_repos) - 5} weitere\n"
                else:
                    # List user repos
                    user_repos = self.repo_manager.list_all_repositories()
                    info += f"Benutzer Repositories: {len(user_repos)}\n"
                    for repo in user_repos[:5]:  # Show first 5
                        info += f"  - {repo['name']} (Owner: {repo.get('owner', {}).get('username', 'Unknown')})\n"
                    if len(user_repos) > 5:
                        info += f"  ... und {len(user_repos) - 5} weitere\n"
        except Exception as e:
            info += f"Fehler beim Abrufen der Repositories: {str(e)}\n"
        
        # Show log file location
        log_file = Path.home() / ".claude_project_manager" / "gitea_operations.log"
        info += f"\nLog-Datei: {log_file}"
        
        messagebox.showinfo("Gitea Verbindungstest", info)
        
    except Exception as e:
        error_msg = f"❌ Gitea Verbindung fehlgeschlagen!\n\n"
        error_msg += f"Fehler: {str(e)}\n\n"
        error_msg += f"Server: {self.repo_manager.client.config.base_url}\n"
        error_msg += "\nBitte prüfen Sie:\n"
        error_msg += "- Netzwerkverbindung\n"
        error_msg += "- API Token Gültigkeit\n"
        error_msg += "- Server Erreichbarkeit"
        
        messagebox.showerror("Gitea Verbindungstest", error_msg)

Key Differences

  • Parameter: First version requires project, second version has project=None (optional)
  • Detail level: Second version shows much more information including:
    • Team permissions with detailed permission levels
    • Project-specific git remote info if project is provided
    • Current branch information
    • Repository listings (user/org mode aware)
    • Log file location
  • UI elements: First version shows email and admin status, second version doesn't
  • Error handling: Second version has more detailed error messages with checkmark/cross emojis

Called From

  • Line 1522: self.test_gitea_connection(project) in gitea_operation method

Recommendation

Requires careful consolidation: The second version is more comprehensive but has an optional parameter. Since the call from gitea_operation always passes a project, we should keep the enhanced functionality of the second version but ensure it works correctly when a project is provided.


4. verify_repository_on_gitea (line 1792 vs line 2556)

First Version (line 1792-1849+)

def verify_repository_on_gitea(self, project):
    """Verify if repository exists on Gitea and show detailed info"""
    import re
    from pathlib import Path
    
    project_path = Path(project.path)
    
    # Check if it's a git repo
    if not (project_path / ".git").exists():
        messagebox.showinfo("Info", "Dies ist kein Git-Repository.")
        return
    
    # Get remote info
    git_ops = self.repo_manager.git_ops
    success, remotes = git_ops.remote_list(project_path)
    
    if not success or not remotes:
        messagebox.showinfo("Info", "Kein Remote-Repository konfiguriert.")
        return
    
    # Extract owner and repo name from remote URL
    match = re.search(r'gitea-undso\.intelsight\.de[:/]([^/]+)/([^/\.]+)', remotes)
    if not match:
        messagebox.showwarning("Warnung", f"Konnte Repository-Info nicht aus Remote-URL extrahieren:\n{remotes}")
        return
    
    remote_owner = match.group(1)
    remote_repo = match.group(2)
    
    info = f"Suche Repository: {remote_owner}/{remote_repo}\n\n"
    
    # Check if repo exists under detected owner
    try:
        repo = self.repo_manager.client.get_repository(remote_owner, remote_repo)
        info += "✅ Repository gefunden!\n\n"
        info += f"Name: {repo.get('name', 'Unknown')}\n"
        info += f"Owner: {repo.get('owner', {}).get('username', 'Unknown')}\n"
        info += f"URL: {repo.get('html_url', 'Unknown')}\n"
        info += f"Clone URL: {repo.get('clone_url', 'Unknown')}\n"
        info += f"Privat: {'Ja' if repo.get('private', False) else 'Nein'}\n"
        info += f"Größe: {repo.get('size', 0) / 1024:.1f} KB\n"
        info += f"Default Branch: {repo.get('default_branch', 'Keiner')}\n"
        info += f"Erstellt: {repo.get('created_at', 'Unknown')}\n"
        info += f"Zuletzt aktualisiert: {repo.get('updated_at', 'Unknown')}\n"
        
        # Check for content
        has_content = repo.get('size', 0) > 0 or repo.get('default_branch')
        if not has_content:
            info += "\n⚠️ WARNUNG: Repository scheint leer zu sein!\n"
        
    except Exception as e:
        info += f"❌ Repository nicht unter {remote_owner}/{remote_repo} gefunden!\n"
        info += f"Fehler: {str(e)}\n\n"
        
        # Search in all locations
        info += "Suche in allen verfügbaren Orten:\n\n"
        
        # Check user repos
        # ... (continues beyond visible range)

Second Version (line 2556-2656)

def verify_repository_on_gitea(self, project):
    """Verify if repository exists on Gitea and show detailed info"""
    project_name = project.name if hasattr(project, 'name') else project.get('name', 'Unknown')
    project_path = Path(project.path) if hasattr(project, 'path') else Path(project['path'])
    
    info = f"Repository Verifizierung für: {project_name}\n"
    info += "=" * 50 + "\n\n"
    
    # Check git remotes
    git_ops = self.repo_manager.git_ops
    success, remotes = git_ops.remote_list(project_path)
    if success and remotes:
        info += f"Git Remote URLs:\n{remotes}\n\n"
        
        # Extract repo name and owner from remote
        import re
        match = re.search(r'gitea-undso\.intelsight\.de[:/]([^/]+)/([^/\.]+)', remotes)
        if match:
            remote_owner = match.group(1)
            remote_repo = match.group(2)
            info += f"Remote zeigt auf: {remote_owner}/{remote_repo}\n\n"
            
            # Search for repository
            info += "Suche Repository auf Gitea:\n"
            
            # 1. Check exact location
            try:
                repo = self.repo_manager.client.get_repository(remote_owner, remote_repo)
                info += f"✅ Gefunden unter {remote_owner}/{remote_repo}\n"
                info += f"   URL: {repo.get('html_url', 'Unknown')}\n"
                info += f"   Größe: {repo.get('size', 0)} bytes\n"
                info += f"   Erstellt: {repo.get('created_at', 'Unknown')}\n"
                info += f"   Aktualisiert: {repo.get('updated_at', 'Unknown')}\n"
                info += f"   Default Branch: {repo.get('default_branch', 'Unknown')}\n"
                info += f"   Privat: {'Ja' if repo.get('private') else 'Nein'}\n"
            except Exception as e:
                info += f"❌ Nicht gefunden unter {remote_owner}/{remote_repo}\n"
                info += f"   Fehler: {str(e)}\n"
            
            # 2. Search in all user repos
            info += "\nSuche in allen Benutzer-Repositories:\n"
            try:
                user_repos = self.repo_manager.list_all_repositories()
                matching_repos = [r for r in user_repos if r['name'] == remote_repo or r['name'] == project_name]
                if matching_repos:
                    for repo in matching_repos:
                        info += f"✅ Gefunden: {repo['owner']['username']}/{repo['name']}\n"
                        info += f"   URL: {repo.get('html_url', 'Unknown')}\n"
                else:
                    info += "❌ Nicht in Benutzer-Repositories gefunden\n"
            except Exception as e:
                info += f"❌ Fehler beim Durchsuchen: {str(e)}\n"
            
            # 3. Search in organization
            if hasattr(self, 'gitea_explorer') and self.gitea_explorer.organization_name:
                info += f"\nSuche in Organisation {self.gitea_explorer.organization_name}:\n"
                try:
                    org_repos = self.repo_manager.list_organization_repositories(self.gitea_explorer.organization_name)
                    matching_repos = [r for r in org_repos if r['name'] == remote_repo or r['name'] == project_name]
                    if matching_repos:
                        for repo in matching_repos:
                            info += f"✅ Gefunden: {repo['name']}\n"
                            info += f"   URL: {repo.get('html_url', 'Unknown')}\n"
                    else:
                        info += "❌ Nicht in Organisation gefunden\n"
                except Exception as e:
                    info += f"❌ Fehler beim Durchsuchen: {str(e)}\n"
    else:
        info += "❌ Keine Git Remote gefunden!\n"
    
    # Check for debug file
    debug_file = project_path / "gitea_push_debug.txt"
    if debug_file.exists():
        info += f"\n\n📄 Debug-Datei gefunden: {debug_file}\n"
        try:
            with open(debug_file, 'r', encoding='utf-8') as f:
                debug_content = f.read()
            info += "Debug-Inhalt:\n" + "-" * 30 + "\n"
            info += debug_content[:1000]  # First 1000 chars
            if len(debug_content) > 1000:
                info += "\n... (gekürzt)"
        except:
            info += "Konnte Debug-Datei nicht lesen\n"
    
    # Show in scrollable dialog
    dialog = ctk.CTkToplevel(self.root)
    dialog.title("Repository Verifizierung")
    dialog.geometry("800x600")
    
    text_widget = ctk.CTkTextbox(dialog, wrap="word")
    text_widget.pack(fill="both", expand=True, padx=10, pady=10)
    text_widget.insert("1.0", info)
    text_widget.configure(state="disabled")
    
    close_btn = ctk.CTkButton(
        dialog,
        text="Schließen",
        command=dialog.destroy
    )
    close_btn.pack(pady=10)

Key Differences

  • Project access: Second version handles both object attributes and dictionary access for project data
  • Pre-checks: First version checks if it's a git repo and has remotes before proceeding
  • Display method: First version shows info in messagebox, second version uses a scrollable CTkToplevel dialog
  • Additional features: Second version includes:
    • Debug file checking and display
    • More structured repository search (exact location, user repos, org repos)
    • Header with project name
  • Size display: First version shows size in KB, second version in bytes

Called From

  • Line 1524: self.verify_repository_on_gitea(project) in gitea_operation method
  • Line 1987: self.verify_repository_on_gitea(project) in fix_repository_issues method (nested function check_on_gitea)

Recommendation

Requires careful consolidation: Both versions have valuable features. The second version's scrollable dialog is better for displaying detailed information, but the first version's pre-checks are important. Combine both:

  • Keep pre-checks from first version
  • Keep the enhanced display and debug file checking from second version
  • Ensure consistent project data access

Summary and Recommendations

  1. manage_branches: Delete first version (placeholder), keep second version
  2. link_to_gitea: Delete first version (placeholder), keep second version
  3. test_gitea_connection: Merge both versions, keeping the enhanced functionality of the second while ensuring it works with required project parameter
  4. verify_repository_on_gitea: Merge both versions, combining pre-checks from first with enhanced display from second

All duplicates are called from the same gitea_operation method, so consolidation is safe. The first versions of manage_branches and link_to_gitea are just placeholders that were later implemented fully in the second versions.