From 3a9d3da3e99ef22810450dd60abfa0b80e5c7cc6 Mon Sep 17 00:00:00 2001 From: Roland Date: Sun, 15 Feb 2026 17:30:11 -0700 Subject: [PATCH] Fixing bug where duplicate entries could be created when using FileGroup.merge. --- wrolpi/files/models.py | 6 +++++- wrolpi/files/test/test_lib.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/wrolpi/files/models.py b/wrolpi/files/models.py index 76e5567b..9ca97e64 100644 --- a/wrolpi/files/models.py +++ b/wrolpi/files/models.py @@ -518,14 +518,18 @@ class FileGroup(ModelHelper, Base): session = Session.object_session(self) collected_files = self.files.copy() + # Track filenames (strings) for proper deduplication + existing_filenames = {f['path'] for f in self.files} + for file_group in file_groups: if file_group.primary_path == self.primary_path: # Don't merge myself. continue for file in file_group.files: - if file['path'] not in self.my_paths(): + if file['path'] not in existing_filenames: collected_files.append(file) + existing_filenames.add(file['path']) # Track newly added # Move any applied Tags. for tag_file in file_group.tag_files: if tag_file.tag is not None and tag_file.tag.name not in self.tag_names: diff --git a/wrolpi/files/test/test_lib.py b/wrolpi/files/test/test_lib.py index b40cb5c4..1016c15c 100644 --- a/wrolpi/files/test/test_lib.py +++ b/wrolpi/files/test/test_lib.py @@ -747,6 +747,14 @@ async def test_file_group_merge(async_client, test_session, test_directory, make assert vid_group.mimetype == 'video/mp4' assert srt_group.mimetype == 'text/srt' + # Add srt to vid_group so both groups have it (simulates race condition scenario) + vid_group.append_files(srt) + test_session.commit() + + # Verify both groups have the srt file + assert 'vid.srt' in [f['path'] for f in vid_group.files] + assert 'vid.srt' in [f['path'] for f in srt_group.files] + # Both FileGroups are merged. vid = FileGroup.from_paths(test_session, vid, srt) test_session.commit() @@ -763,6 +771,10 @@ async def test_file_group_merge(async_client, test_session, test_directory, make assert vid.size > len(video_bytes) assert vid.mimetype == 'video/mp4' + # Verify no duplicate files were created during merge + filenames = [f['path'] for f in vid.files] + assert len(filenames) == len(set(filenames)), f"Duplicate files found: {filenames}" + @pytest.mark.asyncio async def test_move_directory(async_client, test_session, test_directory, make_files_structure,