🔧 FIX: Keine Changes-Marker nach dem Klonen + korrekte Berechtigungen (755/644)
docker-build-and-push / build (push) Successful in 19s
docker-build-and-push / build (push) Successful in 19s
This commit is contained in:
+31
-19
@@ -1,8 +1,33 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def set_permissions(path: str):
|
||||||
|
"""Setzt korrekte POSIX-Berechtigungen für ein Verzeichnis."""
|
||||||
|
try:
|
||||||
|
# Ordner = 755 (rwxr-xr-x)
|
||||||
|
os.chmod(str(path), 0o755)
|
||||||
|
|
||||||
|
# Rekursiv alle Teildateien bearbeiten
|
||||||
|
for root, dirs, files in os.walk(str(path)):
|
||||||
|
for d in dirs:
|
||||||
|
full_path = os.path.join(root, d)
|
||||||
|
try:
|
||||||
|
os.chmod(full_path, 0o755)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
for f in files:
|
||||||
|
full_path = os.path.join(root, f)
|
||||||
|
try:
|
||||||
|
os.chmod(full_path, 0o644)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warnung bei Berechtigungen: {e}")
|
||||||
|
|
||||||
|
|
||||||
def clone_repo(repo_url: str, target_dir: Path, token: str = None):
|
def clone_repo(repo_url: str, target_dir: Path, token: str = None):
|
||||||
"""Klont ein Repository in den Zielordner."""
|
"""Klont ein Repository in den Zielordner."""
|
||||||
if not target_dir.exists():
|
if not target_dir.exists():
|
||||||
@@ -18,36 +43,23 @@ def clone_repo(repo_url: str, target_dir: Path, token: str = None):
|
|||||||
text=True
|
text=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# ✅ BERECHTIGUNGEN SETZEN NACH DEM KLOONEN!
|
# ✅ BERECHTIGUNGEN NACH DEM KLOONEN SETZEN!
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
try:
|
set_permissions(str(target_dir))
|
||||||
os.chmod(str(target_dir), 0o755)
|
|
||||||
for root, dirs, files in os.walk(str(target_dir)):
|
|
||||||
for d in dirs:
|
|
||||||
os.chmod(os.path.join(root, d), 0o755)
|
|
||||||
for f in files:
|
|
||||||
os.chmod(os.path.join(root, f), 0o644)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Warnung bei Berechtigungen: {e}")
|
|
||||||
|
|
||||||
return {"success": result.returncode == 0, "output": result.stdout, "error": result.stderr}
|
return {"success": result.returncode == 0, "output": result.stdout, "error": result.stderr}
|
||||||
|
|
||||||
|
|
||||||
def unsubscribe_repo(target_dir: Path):
|
def unsubscribe_repo(project_name: str, projects_dir: Path):
|
||||||
"""Loescht ein abonniertes Projekt."""
|
"""Loeschen eines abonnierten Projekts inklusive Berechtigungen."""
|
||||||
import shutil
|
target_dir = projects_dir / project_name
|
||||||
|
|
||||||
if not target_dir.exists():
|
if not target_dir.exists():
|
||||||
return {"success": False, "error": "Projekt nicht gefunden"}
|
return {"success": False, "error": "Projekt nicht gefunden"}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# ✅ ALLE CHANGES MARKIERUNG LÖSCHEN
|
|
||||||
changes_marker = target_dir / ".gitea-changes.marker"
|
|
||||||
if changes_marker.exists():
|
|
||||||
changes_marker.unlink()
|
|
||||||
|
|
||||||
shutil.rmtree(str(target_dir))
|
shutil.rmtree(str(target_dir))
|
||||||
return {"success": True, "message": f"{target_dir.name} erfolgreich geloescht"}
|
return {"success": True, "message": f"{project_name} erfolgreich geloescht"}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return {"success": False, "error": str(e)}
|
return {"success": False, "error": str(e)}
|
||||||
|
|
||||||
|
|||||||
+16
-40
@@ -19,49 +19,37 @@ class UnsubscribeRequest(BaseModel):
|
|||||||
project_name: str
|
project_name: str
|
||||||
|
|
||||||
|
|
||||||
@router.get("/projects") #✅ Listet abonierte Projekte!
|
@router.get("/projects") # Listet abonierte Projekte!
|
||||||
async def list_projects():
|
async def list_projects():
|
||||||
"""Listet lokale (abonierte) Projekte an."""
|
"""Listet lokale (abonierte) Projekte an."""
|
||||||
from .main import PROJECTS_DIR, ACCESS_TOKEN
|
from .main import PROJECTS_DIR, ACCESS_TOKEN
|
||||||
|
|
||||||
projects = []
|
projects = []
|
||||||
unsubscribed_markers = set() #Fuer Deabonination Marker
|
|
||||||
|
|
||||||
if PROJECTS_DIR.exists() and str(PROJECTS_DIR).strip():
|
if PROJECTS_DIR.exists() and str(PROJECTS_DIR).strip():
|
||||||
# Suche nach .gitea-unsubscribe marker Dateien (fuer Deabbonation)
|
# Sortiere nach dem Status der Changes zuerst
|
||||||
for marker_file in PROJECTS_DIR.glob(".*.unsubscribe"):
|
|
||||||
project_name = marker_file.stem.replace(".gitea-unsubscribe", "")
|
|
||||||
unsubscribed_markers.add(project_name)
|
|
||||||
|
|
||||||
if PROJECTS_DIR.exists() and str(PROJECTS_DIR).strip():
|
|
||||||
# Sortiere: Abonnierte zuerst, dann alphabtsortiert
|
|
||||||
all_projects = []
|
all_projects = []
|
||||||
for project_dir in sorted(PROJECTS_DIR.iterdir()):
|
for project_dir in sorted(PROJECTS_DIR.iterdir()):
|
||||||
if project_dir.is_dir() and not project_dir.name.startswith('.'):
|
if project_dir.is_dir() and not project_dir.name.startswith('.'):
|
||||||
has_git = (project_dir / '.git').exists()
|
has_git = (project_dir / '.git').exists()
|
||||||
changes_marker = Path(project_dir / ".gitea-changes.marker")
|
|
||||||
has_changes = changes_marker.exists()
|
# Prüfe ob dieses Projekt bearbeitet werden darf (chmod-check)
|
||||||
|
can_write = os.access(str(project_dir), os.W_OK) if project_dir.exists() else False
|
||||||
|
|
||||||
all_projects.append({
|
all_projects.append({
|
||||||
"name": project_dir.name,
|
"name": project_dir.name,
|
||||||
"path": str(project_dir),
|
"path": str(project_dir),
|
||||||
"subscribed": True,
|
"subscribed": True,
|
||||||
"has_git": bool(has_git),
|
"has_git": bool(has_git),
|
||||||
"has_undiscovered_changes": has_changes,
|
"can_write": can_write #✅ NEU: Zeigt ob User Berechtigung hat!
|
||||||
"_sort_priority": 0 if not has_changes else 1 # ohne changes = priority höher (kommt zuerst)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
# Sortiere nach Changes-Status zuerst, dann alphabetisch
|
projects = all_projects
|
||||||
projects = sorted(all_projects, key=lambda x: (-x["_sort_priority"], x["name"]))
|
|
||||||
|
|
||||||
# Entferne Hilfsfeld für API-Ausgabe
|
|
||||||
for p in projects:
|
|
||||||
del p["_sort_priority"]
|
|
||||||
|
|
||||||
return {"projects": projects}
|
return {"projects": projects}
|
||||||
|
|
||||||
|
|
||||||
@router.post("/unsubscribe") #❌ NEU: Deabonination Endpoint!
|
@router.post("/unsubscribe") # Deabonination Endpoint!
|
||||||
async def unsubscribe_repo(req: UnsubscribeRequest):
|
async def unsubscribe_repo(req: UnsubscribeRequest):
|
||||||
"""Loeschen eines abonnierten Projekts."""
|
"""Loeschen eines abonnierten Projekts."""
|
||||||
from .main import PROJECTS_DIR
|
from .main import PROJECTS_DIR
|
||||||
@@ -71,20 +59,12 @@ async def unsubscribe_repo(req: UnsubscribeRequest):
|
|||||||
if not target_dir.exists():
|
if not target_dir.exists():
|
||||||
return {"success": False, "error": f"Projekt '{req.project_name}' nicht gefunden"}
|
return {"success": False, "error": f"Projekt '{req.project_name}' nicht gefunden"}
|
||||||
|
|
||||||
result = unsubscribe_repo(target_dir)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def unsubscribe_repo(target_dir: Path):
|
|
||||||
"""Loeschen eines abonnierten Projekts."""
|
|
||||||
import shutil
|
|
||||||
|
|
||||||
if not target_dir.exists():
|
|
||||||
return {"success": False, "error": "Projekt nicht gefunden"}
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
import shutil
|
||||||
shutil.rmtree(str(target_dir))
|
shutil.rmtree(str(target_dir))
|
||||||
marker_file = Path(str(target_dir) + ".unsubscribe")
|
|
||||||
|
# Erstelle Markierungsdatei um Deabonnierung zu tracken
|
||||||
|
marker_file = Path(str(PROJECTS_DIR) / f".deleted_{req.project_name}")
|
||||||
marker_file.touch()
|
marker_file.touch()
|
||||||
|
|
||||||
return {"success": True, "message": f"{target_dir.name} erfolgreich geloescht"}
|
return {"success": True, "message": f"{target_dir.name} erfolgreich geloescht"}
|
||||||
@@ -117,7 +97,7 @@ async def subscribe_repo(req: SubscribeRequest):
|
|||||||
effective_token = req.token_provided or ACCESS_TOKEN or ""
|
effective_token = req.token_provided or ACCESS_TOKEN or ""
|
||||||
|
|
||||||
if not effective_token:
|
if not effective_token:
|
||||||
raise HTTPException(status_code=401, detail="Kein TOKEN vorhanden! Bitte setze ACCESS_TOKEN Umgebungsvariable.")
|
raise HTTPException(status_code=401, detail="Kein TOKEN vorhanden!")
|
||||||
|
|
||||||
target_dir = Path("/projects") / req.target_name
|
target_dir = Path("/projects") / req.target_name
|
||||||
|
|
||||||
@@ -126,19 +106,15 @@ async def subscribe_repo(req: SubscribeRequest):
|
|||||||
if not result["success"]:
|
if not result["success"]:
|
||||||
return {"error": result.get("error"), "success": False}
|
return {"error": result.get("error"), "success": False}
|
||||||
|
|
||||||
(target_dir / ".gitea-changes.marker").touch()
|
# ✅ KEINE CHANGES-MARKER NACH DEM KLONEN MEHR!
|
||||||
|
|
||||||
generate_changelog(target_dir)
|
generate_changelog(target_dir)
|
||||||
|
|
||||||
# Loesche Deabonination-Marker wenn Projekt wieder abonniert wurde
|
|
||||||
marker_file = Path(str(target_dir) + ".unsubscribe")
|
|
||||||
if marker_file.exists():
|
|
||||||
marker_file.unlink()
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"message": f"✅ {req.target_name} geklont!",
|
"message": f"✅ {req.target_name} geklont!",
|
||||||
"path": str(target_dir),
|
"path": str(target_dir),
|
||||||
"success": True,
|
"success": True,
|
||||||
"token_used": bool(effective_token and not req.token_provided)
|
"can_write": os.access(str(target_dir), os.W_OK) if target_dir.exists() else False
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user