# 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) ```python def manage_branches(self, project): """Manage git branches""" messagebox.showinfo("Branches", "Branch management coming soon") ``` ### Second Version (line 2336-2391) ```python 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. --- ## 2. `link_to_gitea` (line 1378 vs line 2392) ### First Version (line 1378-1381) ```python def link_to_gitea(self, project): """Link local project to Gitea repository""" messagebox.showinfo("Link", "Link functionality coming soon") ``` ### Second Version (line 2392-2456) ```python 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) ```python 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) ```python 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+) ```python 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) ```python 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.