diff --git a/app/git_manager.py b/app/git_manager.py index c2c9958..90ede92 100644 --- a/app/git_manager.py +++ b/app/git_manager.py @@ -5,8 +5,37 @@ import stat from pathlib import Path +def force_remove_all(path: str): + """Erzwingt das Loeschen von Dateien und Ordnern mit chmod 0o666 fuer ALLE.""" + path = Path(path) + + if not path.exists(): + return + + # ✅ ZUERST: Alles auf Schreibbar setzen (auch schreibgeschuetzte .git files!) + for root, dirs, files in os.walk(str(path), topdown=False): + for d in dirs: + try: + dir_path = Path(root) / d + dir_path.chmod(0o755 | stat.S_IWUSR) + except Exception: + pass + for f in files: + try: + file_path = Path(root) / f + file_path.chmod(0o666) # Wichtig: Alles beschreibbar fuer Loeschen! + except Exception: + pass + + # Jetzt die Root-Ordner auch beschreibbar machen + try: + path.chmod(0o755 | stat.S_IWUSR) + except Exception: + pass + + def set_permissions(path: str): - """Setzt korrekte POSIX-Berechtigungen fuer ein Verzeichnis.""" + """Setzt korrekte POSIX-Berechtigungen fuer ein Verzeichnis nach dem Klonen.""" try: # Ordner = 755 (rwxr-xr-x) os.chmod(str(path), 0o755) @@ -22,13 +51,13 @@ def set_permissions(path: str): for f in files: full_path = os.path.join(root, f) try: - # Setze WRITE permission damit wir es loeschen können! + # Nur les- und schreibbar fuer owner, sonst nur lesen os.chmod(full_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) except Exception: pass # Nachher auch den Hauptordner beschreiben machen - os.chmod(str(path), 0o755 | stat.S_ISVTX) # Sticky-Bit hilft beim Loeschen + os.chmod(str(path), 0o755) except Exception as e: print(f"Warnung bei Berechtigungen: {e}") @@ -63,45 +92,21 @@ def unsubscribe_repo(project_name: str, projects_dir: Path): return {"success": False, "error": "Projekt nicht gefunden"} try: - # ✅ SCHRITT 1: Alle Berechtigungen normalisieren damit wir es loeschen können! - set_permissions(str(target_dir)) - - # ✅ SCHRITT 2: Mit REMOVE-TREATMENTS einen Ordner mit root-Besitzern loeschen - # Dies schreibt neu und zwingt das Loeschen: - for root, dirs, files in os.walk(str(target_dir), topdown=False): - for d in dirs: - dir_path = Path(root) / d - try: - dir_path.chmod(0o755) # Schreibrechte wiederherstellen - except Exception: - pass - for f in files: - file_path = Path(root) / f - try: - file_path.unlink() # Datei loeschen - except Exception: - pass + # ✅ SCHRITT 1: Alles CHMOD 0o666 fuer LOESCHEN! + force_remove_all(str(target_dir)) + # ✅ SCHRITT 2: Erst jetzt.loeschen shutil.rmtree(str(target_dir)) + return {"success": True, "message": f"{project_name} erfolgreich geloescht"} - except PermissionError as e: - # Fallback: Versuche mit FERZWUNGSLÖSCHUNG! - try: - import subprocess as sp - sp.run(["rm", "-rf", str(target_dir)], check=True) # UNIX-force-loeschen - return {"success": True, "message": f"{project_name} geloescht (force-mode)"} - except Exception as e2: - return {"success": False, "error": f"Permission denied even after fix: {e}"} - except Exception as e: - # Letzter Versuch mit rm -rf + # Fallback mit rm -rf try: - import subprocess as sp - sp.run(["rm", "-rf", str(target_dir)], check=True) - return {"success": True, "message": f"{project_name} geloescht (force-mode)"} + subprocess.run(["rm", "-rf", str(target_dir)], check=True) + return {"success": True, "message": f"{project_name} geloescht (Force)"} except Exception as e2: - return {"success": False, "error": str(e)} + return {"success": False, "error": f"Konnte nicht loeschen: {e}"} def push_changes(repo_path: Path, message: str = "Update 🧠"):