Fix endless Filmotéka hardlink churn and show pool/output paths in the status bar
This commit is contained in:
@@ -169,6 +169,45 @@ class TestHardlinkManager:
|
||||
assert (temp_output_dir / "- Dle roku" / "1968" / "file1.txt").exists()
|
||||
assert not (temp_output_dir / "Dle roku").exists()
|
||||
|
||||
def test_sync_replaces_orphan_squatting_the_expected_name(
|
||||
self, temp_source_dir, temp_output_dir, tag_manager
|
||||
):
|
||||
"""An orphan link with the *expected name* but a stale inode is replaced.
|
||||
|
||||
Regression: when a movie is re-imported (new inode), the old hardlink
|
||||
keeps the correct name but points at the dead inode. Name-only obsolete
|
||||
detection spared it and forced the real link to a ``_1`` suffix, which
|
||||
was then swept every run — an endless created==removed churn. Obsolete
|
||||
detection now matches the inode too, so the orphan is removed and the
|
||||
base name is restored, stably.
|
||||
"""
|
||||
f = File(temp_source_dir / "file1.txt", tag_manager)
|
||||
f.tags.clear()
|
||||
f.add_tag(Tag("žánr", "Drama"))
|
||||
roots = {"žánr": ""}
|
||||
manager = HardlinkManager(temp_output_dir)
|
||||
manager.sync_structure([f], category_roots=roots)
|
||||
link = temp_output_dir / "Drama" / "file1.txt"
|
||||
assert link.stat().st_ino == f.file_path.stat().st_ino
|
||||
|
||||
# Simulate a re-import: the expected name now points at a *different*
|
||||
# (orphan) inode, exactly as a replaced movie leaves behind.
|
||||
orphan_src = temp_source_dir / "orphan.txt"
|
||||
orphan_src.write_text("old content")
|
||||
link.unlink()
|
||||
os.link(orphan_src, link)
|
||||
assert link.stat().st_ino != f.file_path.stat().st_ino
|
||||
|
||||
created, _, removed, _ = manager.sync_structure([f], category_roots=roots)
|
||||
# The orphan was swept and the correct link recreated under the base name.
|
||||
assert removed >= 1 and created >= 1
|
||||
assert link.stat().st_ino == f.file_path.stat().st_ino
|
||||
assert not (temp_output_dir / "Drama" / "file1_1.txt").exists()
|
||||
|
||||
# And it is now stable: a second run touches nothing (no churn).
|
||||
created2, _, removed2, _ = manager.sync_structure([f], category_roots=roots)
|
||||
assert (created2, removed2) == (0, 0)
|
||||
|
||||
def test_sync_removes_root_genre_folder_when_last_movie_drops_tag(
|
||||
self, temp_source_dir, temp_output_dir, tag_manager
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user