Skip to content

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

Merged
ThomasWaldmann merged 2 commits intoborgbackup:masterfrom
ThomasWaldmann:directory-extraction-master
Feb 11, 2026
Merged

extract: do not delete existing directory if possible, fixes #4233#9288
ThomasWaldmann merged 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.

@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.92%. Comparing base (37fbe3f) to head (b85ad47).
⚠️ Report is 13 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.89%   75.92%   +0.03%     
==========================================
  Files          86       86              
  Lines       14761    14777      +16     
  Branches     2198     2201       +3     
==========================================
+ Hits        11203    11220      +17     
+ Misses       2884     2880       -4     
- Partials      674      677       +3     

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

@ThomasWaldmann ThomasWaldmann force-pushed the directory-extraction-master branch from 8db7b98 to 73a5241 Compare February 9, 2026 21:03
…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 73a5241 to 9a43efa Compare February 9, 2026 21:27
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).
@ThomasWaldmann ThomasWaldmann force-pushed the directory-extraction-master branch from 9a43efa to b85ad47 Compare February 11, 2026 11:11
@ThomasWaldmann ThomasWaldmann merged commit 8da5de3 into borgbackup:master Feb 11, 2026
18 of 19 checks passed
@ThomasWaldmann ThomasWaldmann deleted the directory-extraction-master branch February 11, 2026 12:57
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