"""Projektliste: konfigurierte Pfade aus projekte.txt (eine Zeile = absoluter Pfad, #-Kommentare). Von Hand editierbar; hinzufuegen/entfernen bedienen die UI.""" from pathlib import Path import config def lade() -> list[dict]: """→ [{name, pfad, fehler?}]. Toter Pfad oder Basename-Kollision wird als Eintrag mit `fehler` gemeldet, nie still verschluckt.""" if not config.PROJEKTE_DATEI.is_file(): return [] out: list[dict] = [] gesehen: dict[str, str] = {} for zeile in config.PROJEKTE_DATEI.read_text(encoding="utf-8").splitlines(): zeile = zeile.strip() if not zeile or zeile.startswith("#"): continue pfad = Path(zeile).expanduser() name = pfad.name eintrag = {"name": name, "pfad": str(pfad)} if not pfad.is_dir(): eintrag["fehler"] = "Pfad existiert nicht" elif name in gesehen: eintrag["fehler"] = f"Namenskollision mit {gesehen[name]}" else: gesehen[name] = str(pfad) out.append(eintrag) return out def finde(name: str) -> Path | None: for p in lade(): if p["name"] == name and "fehler" not in p: return Path(p["pfad"]) return None def hinzufuegen(pfad: str) -> None: """Hängt einen Pfad an projekte.txt an. Wirft ValueError bei ungültigem Verzeichnis, Duplikat oder Basename-Kollision.""" p = Path(pfad).expanduser() if not p.is_absolute(): raise ValueError("Pfad muss absolut sein") if not p.is_dir(): raise ValueError(f"{p} ist kein Verzeichnis") for e in lade(): if e["pfad"] == str(p): raise ValueError(f"{p} ist schon eingetragen") if e["name"] == p.name: raise ValueError(f"Namenskollision mit {e['pfad']}") text = "" if config.PROJEKTE_DATEI.is_file(): text = config.PROJEKTE_DATEI.read_text(encoding="utf-8") if text and not text.endswith("\n"): text += "\n" config.PROJEKTE_DATEI.write_text(text + str(p) + "\n", encoding="utf-8") def entfernen(name: str) -> None: """Streicht den Eintrag aus projekte.txt — nur die Zeile; .planer/ im Repo bleibt unberührt. Wirft ValueError, wenn der Name nicht eingetragen ist.""" if not config.PROJEKTE_DATEI.is_file(): raise ValueError(f"'{name}' nicht in projekte.txt") rest, getroffen = [], False for zeile in config.PROJEKTE_DATEI.read_text(encoding="utf-8").splitlines(): s = zeile.strip() if s and not s.startswith("#") and Path(s).expanduser().name == name: getroffen = True continue rest.append(zeile) if not getroffen: raise ValueError(f"'{name}' nicht in projekte.txt") config.PROJEKTE_DATEI.write_text("\n".join(rest) + ("\n" if rest else ""), encoding="utf-8")