Skip to content

Commit db8a778

Browse files
authored
handle missing gracefully (#13)
1 parent 7709a67 commit db8a778

1 file changed

Lines changed: 51 additions & 12 deletions

File tree

src/htmlcmp/compare_output_server.py

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,30 @@ def root():
272272

273273
has_comparator = Config.comparator is not None
274274

275+
def collect_one_sided(existing: Path, root: Path, message: str) -> list[dict]:
276+
"""Walk a directory present on only one side.
277+
278+
Emits one row per comparable file inside it so each file stays viewable
279+
(on the present side) and copyable to the reference, just like a missing
280+
file. Recurses into nested directories.
281+
"""
282+
entries = []
283+
284+
for child in sorted(existing.iterdir(), key=lambda p: p.name):
285+
if child.is_dir():
286+
entries.extend(collect_one_sided(child, root, message))
287+
elif child.is_file() and comparable_file(child):
288+
entries.append(
289+
{
290+
"path": str(child.relative_to(root)),
291+
"comparable": True,
292+
"message": message,
293+
"result": "different",
294+
}
295+
)
296+
297+
return entries
298+
275299
def collect(a: Path, b: Path) -> list[dict]:
276300
"""Single O(n) walk producing flat leaf rows.
277301
@@ -311,7 +335,7 @@ def collect(a: Path, b: Path) -> list[dict]:
311335
entries.append(
312336
{
313337
"path": str(rel),
314-
"comparable": False,
338+
"comparable": True,
315339
"message": "missing in reference (A)",
316340
"result": "different",
317341
}
@@ -320,23 +344,25 @@ def collect(a: Path, b: Path) -> list[dict]:
320344
entries.append(
321345
{
322346
"path": str(rel),
323-
"comparable": False,
347+
"comparable": True,
324348
"message": "missing in monitored (B)",
325349
"result": "different",
326350
}
327351
)
328352

329353
for name in sorted(left_dirs ^ right_dirs):
330-
rel = common_path / name
331-
where = "reference (A)" if name in right_dirs else "monitored (B)"
332-
entries.append(
333-
{
334-
"path": str(rel) + "/",
335-
"comparable": False,
336-
"message": f"directory missing in {where}",
337-
"result": "different",
338-
}
339-
)
354+
if name in left_dirs:
355+
entries.extend(
356+
collect_one_sided(
357+
a / name, Config.path_a, "missing in monitored (B)"
358+
)
359+
)
360+
else:
361+
entries.extend(
362+
collect_one_sided(
363+
b / name, Config.path_b, "missing in reference (A)"
364+
)
365+
)
340366

341367
for name in sorted(left_dirs & right_dirs):
342368
entries.extend(collect(a / name, b / name))
@@ -638,6 +664,9 @@ def image_diff(path: str):
638664
if Config.driver is None:
639665
return "Image diff not available without browser driver", 404
640666

667+
if not (Config.path_a / path).is_file() or not (Config.path_b / path).is_file():
668+
return "Image diff not available: file missing on one side", 404
669+
641670
diff, _ = html_render_diff(
642671
Config.path_a / path,
643672
Config.path_b / path,
@@ -659,6 +688,16 @@ def file(variant: str, path: str):
659688
raise ValueError("Variant must be 'a' or 'b'")
660689

661690
variant_root = Config.path_a if variant == "a" else Config.path_b
691+
692+
if not (variant_root / path).is_file():
693+
side = "reference (A)" if variant == "a" else "monitored (B)"
694+
return (
695+
"<!DOCTYPE html><html><body style='margin:0;display:flex;"
696+
"align-items:center;justify-content:center;height:100vh;"
697+
"font-family:sans-serif;color:#5f6368;background:#fafafa;'>"
698+
f"<div>file missing in {side}</div></body></html>"
699+
)
700+
662701
return send_from_directory(variant_root, path)
663702

664703

0 commit comments

Comments
 (0)