Sfoglia il codice sorgente

Merge pull request #7284 from ThomasWaldmann/prune-in-localtime

fix prune tests, prune in localtime
TW 2 anni fa
parent
commit
57e0579cf8
2 ha cambiato i file con 36 aggiunte e 27 eliminazioni
  1. 8 10
      src/borg/archiver/prune_cmd.py
  2. 28 17
      src/borg/testsuite/helpers.py

+ 8 - 10
src/borg/archiver/prune_cmd.py

@@ -53,10 +53,8 @@ def prune_split(archives, rule, n, kept_because=None):
 
     a = None
     for a in sorted(archives, key=attrgetter("ts"), reverse=True):
-        # we compute the pruning in UTC time zone
-        # note: we used to compute the pruning in local timezone (tz=None),
-        # but this is causing test failures in some time zones (like e.g. UTC+12).
-        period = a.ts.astimezone(tz=timezone.utc).strftime(pattern)
+        # we compute the pruning in local time zone
+        period = a.ts.astimezone().strftime(pattern)
         if period != last:
             last = period
             if a.id not in kept_because:
@@ -216,12 +214,12 @@ class PruneMixIn:
         up to 7 most recent days with backups (days without backups do not count).
         The rules are applied from secondly to yearly, and backups selected by previous
         rules do not count towards those of later rules. The time that each backup
-        starts is used for pruning purposes. Dates and times are interpreted in
-        the local timezone, and weeks go from Monday to Sunday. Specifying a
-        negative number of archives to keep means that there is no limit. As of borg
-        1.2.0, borg will retain the oldest archive if any of the secondly, minutely,
-        hourly, daily, weekly, monthly, or yearly rules was not otherwise able to meet
-        its retention target. This enables the first chronological archive to continue
+        starts is used for pruning purposes. Dates and times are interpreted in the local
+        timezone of the system where borg prune runs, and weeks go from Monday to Sunday.
+        Specifying a negative number of archives to keep means that there is no limit.
+        As of borg 1.2.0, borg will retain the oldest archive if any of the secondly,
+        minutely, hourly, daily, weekly, monthly, or yearly rules was not otherwise able to
+        meet its retention target. This enables the first chronological archive to continue
         aging until it is replaced by a newer archive that meets the retention criteria.
 
         The ``--keep-last N`` option is doing the same as ``--keep-secondly N`` (and it will

+ 28 - 17
src/borg/testsuite/helpers.py

@@ -405,6 +405,17 @@ class MockArchive:
         return f"{self.id}: {self.ts.isoformat()}"
 
 
+# This is the local timezone of the system running the tests.
+# We need this e.g. to construct archive timestamps for the prune tests,
+# because borg prune operates in the local timezone (it first converts the
+# archive timestamp to the local timezone). So, if we want the y/m/d/h/m/s
+# values which prune uses to be exactly the ones we give [and NOT shift them
+# by tzoffset], we need to give the timestamps in the same local timezone.
+# Please note that the timestamps in a real borg archive or manifest are
+# stored in UTC timezone.
+local_tz = datetime.now(tz=timezone.utc).astimezone(tz=None).tzinfo
+
+
 @pytest.mark.parametrize(
     "rule,num_to_keep,expected_ids",
     [
@@ -424,23 +435,23 @@ def test_prune_split(rule, num_to_keep, expected_ids):
 
     archives = [
         # years apart
-        MockArchive(datetime(2015, 1, 1, 10, 0, 0, tzinfo=timezone.utc), 1),
-        MockArchive(datetime(2016, 1, 1, 10, 0, 0, tzinfo=timezone.utc), 2),
-        MockArchive(datetime(2017, 1, 1, 10, 0, 0, tzinfo=timezone.utc), 3),
+        MockArchive(datetime(2015, 1, 1, 10, 0, 0, tzinfo=local_tz), 1),
+        MockArchive(datetime(2016, 1, 1, 10, 0, 0, tzinfo=local_tz), 2),
+        MockArchive(datetime(2017, 1, 1, 10, 0, 0, tzinfo=local_tz), 3),
         # months apart
-        MockArchive(datetime(2017, 2, 1, 10, 0, 0, tzinfo=timezone.utc), 4),
-        MockArchive(datetime(2017, 3, 1, 10, 0, 0, tzinfo=timezone.utc), 5),
+        MockArchive(datetime(2017, 2, 1, 10, 0, 0, tzinfo=local_tz), 4),
+        MockArchive(datetime(2017, 3, 1, 10, 0, 0, tzinfo=local_tz), 5),
         # days apart
-        MockArchive(datetime(2017, 3, 2, 10, 0, 0, tzinfo=timezone.utc), 6),
-        MockArchive(datetime(2017, 3, 3, 10, 0, 0, tzinfo=timezone.utc), 7),
-        MockArchive(datetime(2017, 3, 4, 10, 0, 0, tzinfo=timezone.utc), 8),
+        MockArchive(datetime(2017, 3, 2, 10, 0, 0, tzinfo=local_tz), 6),
+        MockArchive(datetime(2017, 3, 3, 10, 0, 0, tzinfo=local_tz), 7),
+        MockArchive(datetime(2017, 3, 4, 10, 0, 0, tzinfo=local_tz), 8),
         # minutes apart
-        MockArchive(datetime(2017, 10, 1, 9, 45, 0, tzinfo=timezone.utc), 9),
-        MockArchive(datetime(2017, 10, 1, 9, 55, 0, tzinfo=timezone.utc), 10),
+        MockArchive(datetime(2017, 10, 1, 9, 45, 0, tzinfo=local_tz), 9),
+        MockArchive(datetime(2017, 10, 1, 9, 55, 0, tzinfo=local_tz), 10),
         # seconds apart
-        MockArchive(datetime(2017, 10, 1, 10, 0, 1, tzinfo=timezone.utc), 11),
-        MockArchive(datetime(2017, 10, 1, 10, 0, 3, tzinfo=timezone.utc), 12),
-        MockArchive(datetime(2017, 10, 1, 10, 0, 5, tzinfo=timezone.utc), 13),
+        MockArchive(datetime(2017, 10, 1, 10, 0, 1, tzinfo=local_tz), 11),
+        MockArchive(datetime(2017, 10, 1, 10, 0, 3, tzinfo=local_tz), 12),
+        MockArchive(datetime(2017, 10, 1, 10, 0, 5, tzinfo=local_tz), 13),
     ]
     kept_because = {}
     keep = prune_split(archives, rule, num_to_keep, kept_because)
@@ -456,12 +467,12 @@ def test_prune_split_keep_oldest():
 
     archives = [
         # oldest backup, but not last in its year
-        MockArchive(datetime(2018, 1, 1, 10, 0, 0, tzinfo=timezone.utc), 1),
+        MockArchive(datetime(2018, 1, 1, 10, 0, 0, tzinfo=local_tz), 1),
         # an interim backup
-        MockArchive(datetime(2018, 12, 30, 10, 0, 0, tzinfo=timezone.utc), 2),
+        MockArchive(datetime(2018, 12, 30, 10, 0, 0, tzinfo=local_tz), 2),
         # year end backups
-        MockArchive(datetime(2018, 12, 31, 10, 0, 0, tzinfo=timezone.utc), 3),
-        MockArchive(datetime(2019, 12, 31, 10, 0, 0, tzinfo=timezone.utc), 4),
+        MockArchive(datetime(2018, 12, 31, 10, 0, 0, tzinfo=local_tz), 3),
+        MockArchive(datetime(2019, 12, 31, 10, 0, 0, tzinfo=local_tz), 4),
     ]
 
     # Keep oldest when retention target can't otherwise be met