From ad07de2e9a246cb40a63bf6f557523e21f10a034 Mon Sep 17 00:00:00 2001 From: jenstandstad Date: Sat, 9 May 2026 12:51:59 +0200 Subject: [PATCH] Git adding case insenstiive --- gnommo/parser.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/gnommo/parser.py b/gnommo/parser.py index 1664f73..1bb443a 100644 --- a/gnommo/parser.py +++ b/gnommo/parser.py @@ -25,6 +25,35 @@ def _read_json(path: Path) -> Any: return json.loads(text) if text else {} +def _resolve_case_insensitive(path: Path) -> Path: + """Return the real on-disk path, resolving each component case-insensitively. + + On case-insensitive filesystems (macOS) paths just work. On case-sensitive + ones (Linux/WSL) a mismatch between project.json and the actual directory + name causes a FileNotFoundError. This walks each component and picks the + first directory entry whose name matches case-insensitively, returning the + corrected path. If the path already exists, it is returned unchanged. + """ + if path.exists(): + return path + + resolved = path.anchor and Path(path.anchor) or Path(".") + for part in path.parts[len(Path(path.anchor).parts):]: + if (resolved / part).exists(): + resolved = resolved / part + else: + try: + match = next( + (p for p in resolved.iterdir() if p.name.lower() == part.lower()), + None, + ) + except (OSError, NotADirectoryError): + match = None + resolved = match if match else (resolved / part) + + return resolved + + def parse_manuscript( project_path: Path, ) -> tuple[str, list[str], list[tuple[int, str]], list[Citation]]: @@ -267,6 +296,9 @@ def parse_slides( else: local_slides_path = project_path / "slides.json" + # Resolve case-insensitively before cache lookup (handles Mac vs WSL casing). + local_slides_path = _resolve_case_insensitive(local_slides_path) + # Try cache fallback for reading JSON slides_path, _ = resolve_with_cache(local_slides_path, project_path) if not slides_path.exists():