Skip to content

extract: do not delete existing directory if possible, fixes #4233#9288

Open
ThomasWaldmann wants to merge 2 commits intoborgbackup:masterfrom
ThomasWaldmann:directory-extraction-master
Open

extract: do not delete existing directory if possible, fixes #4233#9288
ThomasWaldmann wants to merge 2 commits intoborgbackup:masterfrom
ThomasWaldmann:directory-extraction-master

Conversation

@ThomasWaldmann
Copy link
Member

A pre-existing directory might be a btrfs subvolume that was created by the user ahead of time when restoring several nested subvolumes from a single archive.

If the archive item to be extracted is a directory and there is already a directory at the destination path, do not remove (and recreate) it, but just use it.

That way, btrfs subvolumes (which look like directories) are not deleted.

Fix originally contributed by @intelfx in #7866, but needed more work, so I thought more about the implications and added a test.

Note:

In the past, we first removed (empty) directories, then created a fresh one, then called restore_attrs for that. That produced correct metadata, but only for the case of an EMPTY exisiting directory. If the existing directory was not empty, the simply os.rmdir we tried did not work anyway and did not remove the existing directory.

Usually we extract to an empty base directory, thus encountering this edge case is mostly limited to continuing a previous extraction. In that case, calling restore_attrs again on a directory that already has existing attrs should be harmless, because they are identical.

@ThomasWaldmann
Copy link
Member Author

ThomasWaldmann commented Feb 8, 2026

TODO: Maybe same_item could be extended to consider directories.

That would avoid any potential issues with calling restore_attrs on directories that already have metadata.

Also it would speed up continuing an extraction.

…up#4233

A pre-existing directory might be a btrfs subvolume that was created by
the user ahead of time when restoring several nested subvolumes from a
single archive.

If the archive item to be extracted is a directory and there is already
a directory at the destination path, do not remove (and recreate) it,
but just use it.

That way, btrfs subvolumes (which look like directories) are not deleted.

Fix originally contributed by @intelfx in borgbackup#7866, but needed more work,
so I thought more about the implications and added a test.

Note:

In the past, we first removed (empty) directories, then created a fresh
one, then called restore_attrs for that. That produced correct metadata,
but only for the case of an EMPTY exisiting directory. If the existing
directory was not empty, the simply os.rmdir we tried did not work
anyway and did not remove the existing directory.

Usually we extract to an empty base directory, thus encountering this
edge case is mostly limited to continuing a previous extraction.
In that case, calling restore_attrs again on a directory that already has
existing attrs should be harmless, because they are identical.
@ThomasWaldmann ThomasWaldmann force-pushed the directory-extraction-master branch from 03f0347 to fdfb856 Compare February 8, 2026 08:44
@codecov
Copy link

codecov bot commented Feb 8, 2026

Codecov Report

❌ Patch coverage is 70.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 75.83%. Comparing base (a2b47c7) to head (8db7b98).
⚠️ Report is 5 commits behind head on master.

Files with missing lines Patch % Lines
src/borg/archive.py 70.00% 1 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #9288      +/-   ##
==========================================
- Coverage   75.83%   75.83%   -0.01%     
==========================================
  Files          86       86              
  Lines       14747    14753       +6     
  Branches     2194     2196       +2     
==========================================
+ Hits        11184    11188       +4     
- Misses       2890     2891       +1     
- Partials      673      674       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

if an already existing fs directory has the correct (as archived) mtime,
we have already extracted it in a previous borg extract run and we do not
need and should not call restore_attrs for it again.

if the directory exists, but does not have the correct mtime, restore_attrs
will be called and its attributes will be extracted (and mtime set to
correct value).
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.

1 participant