chore(e2e): run the e2e dev server on native Linux
e2e.sh and gen_fixtures.py assumed WSL driving the Windows toolchain. They now detect WSL (a microsoft kernel with cargo.exe available) and otherwise use native tools: - e2e.sh: cargo/curl instead of cargo.exe/curl.exe, pgrep/pkill instead of tasklist/taskkill, Linux paths in the generated .env, and binaries without the .exe suffix. - gen_fixtures.py: picks the first ffmpeg that has the drawtext filter (a minimal build earlier on PATH may not; E2E_FFMPEG overrides), finds a monospace font with fc-match, and only translates paths with wslpath for .exe tools. - Quote USER_NAME in the generated .env: the unquoted space made the dotenv parser reject the line. - Mark the scripts executable. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
50dd9aa016
commit
b7943be022
3 files changed
+92
-28
No files matched your search
Regular → Executable
+53
-7
@@ -8,8 +8,9 @@ in a single exiftool batch. A `manifest.json` next to the media records
|
||||
what was generated and what the server should derive from it, so tests
|
||||
can assert against it instead of hardcoding counts.
|
||||
|
||||
The harness runs in WSL but the tools (ffmpeg.exe / exiftool.exe) are
|
||||
Windows binaries, so every path handed to them goes through `wslpath -w`.
|
||||
Runs on native Linux with ffmpeg / exiftool, or in WSL driving the Windows
|
||||
binaries (ffmpeg.exe / exiftool.exe), in which case every path handed to
|
||||
them goes through `wslpath -w`.
|
||||
|
||||
Usage: gen_fixtures.py <out_dir> [--import DIR]
|
||||
<out_dir>/media/ the pristine library (never served directly)
|
||||
@@ -30,11 +31,48 @@ from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
FFMPEG = shutil.which("ffmpeg.exe") or shutil.which("ffmpeg")
|
||||
|
||||
|
||||
def _find_ffmpeg() -> str | None:
|
||||
"""The first ffmpeg that can burn labels in (has `drawtext`, i.e. was
|
||||
built with freetype). E2E_FFMPEG overrides. Minimal builds earlier on
|
||||
PATH (e.g. a custom one in ~/bin) often lack it."""
|
||||
if os.environ.get("E2E_FFMPEG"):
|
||||
return os.environ["E2E_FFMPEG"]
|
||||
candidates = [shutil.which("ffmpeg.exe"), shutil.which("ffmpeg"), "/usr/bin/ffmpeg"]
|
||||
for cand in dict.fromkeys(c for c in candidates if c and os.path.exists(c)):
|
||||
try:
|
||||
filters = subprocess.run(
|
||||
[cand, "-hide_banner", "-filters"], capture_output=True, text=True
|
||||
).stdout
|
||||
except OSError:
|
||||
continue
|
||||
if " drawtext " in filters:
|
||||
return cand
|
||||
return None
|
||||
|
||||
|
||||
FFMPEG = _find_ffmpeg()
|
||||
EXIFTOOL = shutil.which("exiftool.exe") or shutil.which("exiftool")
|
||||
# drawtext needs an explicit font on Windows ffmpeg builds. The colon after
|
||||
# the drive letter must be escaped inside a filter argument.
|
||||
FONT = "C\\:/Windows/Fonts/consola.ttf"
|
||||
|
||||
def _font() -> str:
|
||||
"""A monospace font for ffmpeg's drawtext, as a filter-escaped path."""
|
||||
if FFMPEG and FFMPEG.endswith(".exe"):
|
||||
# Windows ffmpeg needs an explicit font; the colon after the drive
|
||||
# letter must be escaped inside a filter argument.
|
||||
return "C\\:/Windows/Fonts/consola.ttf"
|
||||
try:
|
||||
found = subprocess.check_output(
|
||||
["fc-match", "-f", "%{file}", "monospace"], text=True
|
||||
).strip()
|
||||
if found:
|
||||
return found
|
||||
except (OSError, subprocess.CalledProcessError):
|
||||
pass
|
||||
return "/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf"
|
||||
|
||||
|
||||
FONT = _font()
|
||||
|
||||
# The owner's display zone and the server zone the e2e env pins (TZ=...).
|
||||
# Naive fixture datetimes without GPS are walls in this zone.
|
||||
@@ -85,6 +123,10 @@ class Item:
|
||||
|
||||
|
||||
def win(p: Path) -> str:
|
||||
"""`p` as the external tools see it: a Windows path for WSL-driven
|
||||
.exe tools, unchanged for native ones."""
|
||||
if not (FFMPEG or "").endswith(".exe"):
|
||||
return str(p)
|
||||
return subprocess.check_output(["wslpath", "-w", str(p)], text=True).strip()
|
||||
|
||||
|
||||
@@ -288,7 +330,11 @@ def main() -> int:
|
||||
help="also copy this folder (read-only source) into media/imported/")
|
||||
a = ap.parse_args()
|
||||
if not FFMPEG or not EXIFTOOL:
|
||||
print("ffmpeg(.exe) and exiftool(.exe) must be on PATH", file=sys.stderr)
|
||||
print(
|
||||
"ffmpeg(.exe) with the drawtext filter (built with freetype) and "
|
||||
"exiftool(.exe) must be on PATH; set E2E_FFMPEG to pick an ffmpeg",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
out: Path = a.out_dir.resolve()
|
||||
|
||||
Reference in new issue
Block a user