Skip to content

transfers: Prevent receiver directory wiping and data loss (#240) - #263

Open
ronitgupta138 wants to merge 1 commit into
linuxmint:masterfrom
ronitgupta138:fix/prevent-receiver-directory-wiping-data-loss
Open

ronitgupta138 wants to merge 1 commit into
linuxmint:masterfrom
ronitgupta138:fix/prevent-receiver-directory-wiping-data-loss

Conversation

@ronitgupta138

Copy link
Copy Markdown

Resolves #240

Problem & Root Cause

When transferring files or folders, FileReceiver.clean_existing_files() called rm_any() which executed shutil.rmtree() on the whole directory self.save_path / name before receiving folder contents. This was originally done because Gio.File.create() raises G_IO_ERROR_EXISTS if a destination file exists.
Additionally, when an interrupted transfer stopped or aborted prematurely, clean_current_top_dir_file() resolved abs_top_dir = self.save_path.joinpath(relative.parts[0]) and executed self.rm_any(abs_top_dir) with shutil.rmtree(), permanently destroying the entire top-level directory.

These behaviors caused severe, unintentional data loss:

  1. When receiving a folder that already existed on the receiving device, any pre-existing files not present in the incoming batch (e.g. deleted or moved on sender, or transferring an update) were completely wiped out.
  2. If a transfer was interrupted or cancelled mid-transfer, the entire existing receiving directory was deleted.

Solution

  1. Safe Overwriting in receive_data(): Switched from self.current_gfile.create() to self.current_gfile.replace(None, False, Gio.FileCreateFlags.REPLACE_DESTINATION, None). Incoming files now overwrite cleanly without needing directory destruction.
  2. Preserve Directory Trees in clean_existing_files() & rm_any(): Refactored rm_any() and clean_existing_files() to never delete directory trees (shutil.rmtree). If a target entry is a directory, it is kept intact so that existing files are preserved and transfers behave as copy operations rather than destructive overwrites.
  3. Safe Abort Cleanup in clean_current_top_dir_file(): Track self.current_is_new and ensure only newly created partial files are unlinked on abort, rather than nuking the parent directory tree abs_top_dir.

Verification Steps

  • Created comprehensive regression unit tests covering:
    • Preserving pre-existing directories and files when clean_existing_files() runs.
    • Verifying top-level regular files/symlinks are still handled properly.
    • Clean overwriting of individual files during transfers while leaving non-transferred files in the folder intact.
    • Aborting mid-transfer: verifying newly created partial files are removed while existing directory hierarchies and pre-existing files remain untouched.
    • Full end-to-end simulation of Issue Warpinator may delete files on receiver after interrupted transfer #240 (transferring a subset of a previously transferred directory) confirming no data loss occurs on the receiver.
  • Verified all tests pass cleanly.

…int#240)

- In receive_data(), switch from create() to replace() with
  REPLACE_DESTINATION so individual files overwrite cleanly without
  directory destruction.
- In clean_existing_files() and rm_any(), do not delete entire directory
  trees (shutil.rmtree) when receiving folder contents, preserving
  pre-existing files.
- In clean_current_top_dir_file(), ensure only newly created partial
  files are cleaned on abort, rather than nuking existing directory trees.
Copilot AI balanced review requested due to automatic review settings October 15, 2026 17:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

Warpinator may delete files on receiver after interrupted transfer

2 participants