Bläddra i källkod

Merge pull request #7595 from nain-F49FF806/1.2-clear-empty-dirs

clear empty directories at end of compact process, fixes #6823
TW 2 år sedan
förälder
incheckning
0bfbd8d8fc
1 ändrade filer med 17 tillägg och 0 borttagningar
  1. 17 0
      src/borg/repository.py

+ 17 - 0
src/borg/repository.py

@@ -879,6 +879,7 @@ class Repository:
             pi.show()
             pi.show()
         pi.finish()
         pi.finish()
         complete_xfer(intermediate=False)
         complete_xfer(intermediate=False)
+        self.io.clear_empty_dirs()
         quota_use_after = self.storage_quota_use
         quota_use_after = self.storage_quota_use
         logger.info('compaction freed about %s repository space.', format_file_size(quota_use_before - quota_use_after))
         logger.info('compaction freed about %s repository space.', format_file_size(quota_use_before - quota_use_after))
         logger.debug('compaction completed.')
         logger.debug('compaction completed.')
@@ -1495,6 +1496,22 @@ class LoggedIO:
         except FileNotFoundError:
         except FileNotFoundError:
             pass
             pass
 
 
+    def clear_empty_dirs(self):
+        """Delete empty segment dirs, i.e those with no segment files.
+        """
+        data_dir = os.path.join(self.path, 'data')
+        segment_dirs = self.get_segment_dirs(data_dir)
+        for segment_dir in segment_dirs:
+            try:
+                # os.rmdir will only delete the directory if it is empty
+                # so we don't need to explicitly check for emptiness first.
+                os.rmdir(segment_dir)
+            except OSError:
+                # OSError is raised by os.rmdir if directory is not empty. This is expected.
+                # It's subclass FileNotFoundError may be raised if the directory already does not exist. Ignorable.
+                pass
+        sync_dir(data_dir)
+
     def segment_exists(self, segment):
     def segment_exists(self, segment):
         filename = self.segment_filename(segment)
         filename = self.segment_filename(segment)
         # When deleting segments, they are first truncated. If truncate(2) and unlink(2) are split
         # When deleting segments, they are first truncated. If truncate(2) and unlink(2) are split