Skip to content

Conversation

@gantoine
Copy link
Member

Description
Explain the changes or enhancements you are proposing with this pull request.

Checklist
Please check all that apply.

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @gantoine, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This hotfix addresses issues related to importing media from gamelist.xml by significantly refactoring the underlying file handling mechanisms. It introduces a new, centralized, and thread-safe file copying utility, which is then integrated across the media resource management components. This change aims to make the media import process more reliable and maintainable, especially for local file paths specified in gamelist.xml. Additionally, a small user interface adjustment was made in the scan view.

Highlights

  • Centralized File Copying: A new asynchronous method, copy_file, has been introduced in base_handler.py. This method provides a robust, thread-safe way to copy files, incorporating locking mechanisms for both source and destination paths, and handling directory creation.
  • Refactored Media Import Logic: The resources_handler.py has been updated to utilize the newly created copy_file method for handling all media types (covers, screenshots, manuals). This change replaces direct calls to shutil.copy2, streamlining file operations and removing the shutil import from this file.
  • Simplified Gamelist Media Parsing: The gamelist_handler.py now directly uses the media URLs provided in rom_metadata without pre-pending file:// or performing redundant path validations. This delegates the actual file system operations to the resources_handler, which now uses the centralized copy_file method.
  • Frontend UI Adjustment: A minor styling change was applied in Scan.vue to wrap the item name in a div with a left margin, improving the visual presentation.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new copy_file method to centralize file copying logic, which is a good refactoring. The main issue is that the new method, like other existing methods in base_handler.py, uses blocking I/O calls within an async function. This can severely impact the application's performance and responsiveness. I've added a high-severity comment with a suggested fix for the new copy_file method. I recommend applying a similar pattern to other blocking calls throughout the file (e.g., in move_file_or_folder, remove_file, make_directory, etc.) to make the filesystem handler truly asynchronous.

The changes in gamelist_handler.py are a good bugfix, correctly handling file:// URLs from gamelist.xml. The frontend change is a minor but useful UI improvement.

Overall, this is a valuable hotfix, but addressing the blocking I/O is critical for maintaining a healthy async application.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 10, 2025

Test Results

616 tests   615 ✅  1m 13s ⏱️
  1 suites    1 💤
  1 files      0 ❌

Results for commit d4e0f67.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 10, 2025

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
11250 7384 66% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
backend/handler/filesystem/base_handler.py 90% 🟢
backend/handler/filesystem/resources_handler.py 45% 🟢
backend/handler/metadata/gamelist_handler.py 28% 🟢
TOTAL 54% 🟢

updated for commit: d4e0f67 by action🐍

@gantoine
Copy link
Member Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a hotfix for importing media from gamelist.xml files. The changes refactor file system operations by adding a new copy_file method in base_handler.py and using it across resources_handler.py. This correctly handles local file:// URLs from gamelists. The PR also simplifies several file system checks by removing redundant .exists() calls. Overall, the changes are a good improvement and fix the intended bug. However, I've identified a significant performance issue in the new copy_file method where blocking I/O operations are used within an async function, which could harm application responsiveness. My review includes a suggestion to address this.

Comment on lines +478 to +479
dest_full_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(str(source_full_path), str(dest_full_path))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The copy_file method is async, but it uses dest_full_path.parent.mkdir() and shutil.copy2(), which are synchronous, blocking I/O operations. This will block the asyncio event loop, potentially for a long time if the file being copied is large, which can degrade the performance and responsiveness of the application. Blocking calls in async functions should be run in a separate thread to avoid this.

You can use anyio.to_thread.run_sync to execute these blocking calls without blocking the event loop. You will also need to add to_thread to your anyio import (e.g., from anyio import open_file, to_thread).

Suggested change
dest_full_path.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(str(source_full_path), str(dest_full_path))
await to_thread.run_sync(dest_full_path.parent.mkdir, parents=True, exist_ok=True)
await to_thread.run_sync(shutil.copy2, str(source_full_path), str(dest_full_path))

@gantoine gantoine merged commit 4c62e5f into master Nov 10, 2025
9 checks passed
@gantoine gantoine deleted the hotfix-media-import-gamelist-xml branch November 10, 2025 23:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants