mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-26 07:53:58 +00:00
Merge pull request #7284 from ThomasWaldmann/prune-in-localtime
fix prune tests, prune in localtime
This commit is contained in:
commit
57e0579cf8
2 changed files with 36 additions and 27 deletions
|
@ -53,10 +53,8 @@ def prune_split(archives, rule, n, kept_because=None):
|
||||||
|
|
||||||
a = None
|
a = None
|
||||||
for a in sorted(archives, key=attrgetter("ts"), reverse=True):
|
for a in sorted(archives, key=attrgetter("ts"), reverse=True):
|
||||||
# we compute the pruning in UTC time zone
|
# we compute the pruning in local time zone
|
||||||
# note: we used to compute the pruning in local timezone (tz=None),
|
period = a.ts.astimezone().strftime(pattern)
|
||||||
# but this is causing test failures in some time zones (like e.g. UTC+12).
|
|
||||||
period = a.ts.astimezone(tz=timezone.utc).strftime(pattern)
|
|
||||||
if period != last:
|
if period != last:
|
||||||
last = period
|
last = period
|
||||||
if a.id not in kept_because:
|
if a.id not in kept_because:
|
||||||
|
@ -216,12 +214,12 @@ def build_parser_prune(self, subparsers, common_parser, mid_common_parser):
|
||||||
up to 7 most recent days with backups (days without backups do not count).
|
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
|
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
|
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
|
starts is used for pruning purposes. Dates and times are interpreted in the local
|
||||||
the local timezone, and weeks go from Monday to Sunday. Specifying a
|
timezone of the system where borg prune runs, and weeks go from Monday to Sunday.
|
||||||
negative number of archives to keep means that there is no limit. As of borg
|
Specifying a negative number of archives to keep means that there is no limit.
|
||||||
1.2.0, borg will retain the oldest archive if any of the secondly, minutely,
|
As of borg 1.2.0, borg will retain the oldest archive if any of the secondly,
|
||||||
hourly, daily, weekly, monthly, or yearly rules was not otherwise able to meet
|
minutely, hourly, daily, weekly, monthly, or yearly rules was not otherwise able to
|
||||||
its retention target. This enables the first chronological archive to continue
|
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.
|
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
|
The ``--keep-last N`` option is doing the same as ``--keep-secondly N`` (and it will
|
||||||
|
|
|
@ -405,6 +405,17 @@ def __repr__(self):
|
||||||
return f"{self.id}: {self.ts.isoformat()}"
|
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(
|
@pytest.mark.parametrize(
|
||||||
"rule,num_to_keep,expected_ids",
|
"rule,num_to_keep,expected_ids",
|
||||||
[
|
[
|
||||||
|
@ -424,23 +435,23 @@ def subset(lst, ids):
|
||||||
|
|
||||||
archives = [
|
archives = [
|
||||||
# years apart
|
# years apart
|
||||||
MockArchive(datetime(2015, 1, 1, 10, 0, 0, tzinfo=timezone.utc), 1),
|
MockArchive(datetime(2015, 1, 1, 10, 0, 0, tzinfo=local_tz), 1),
|
||||||
MockArchive(datetime(2016, 1, 1, 10, 0, 0, tzinfo=timezone.utc), 2),
|
MockArchive(datetime(2016, 1, 1, 10, 0, 0, tzinfo=local_tz), 2),
|
||||||
MockArchive(datetime(2017, 1, 1, 10, 0, 0, tzinfo=timezone.utc), 3),
|
MockArchive(datetime(2017, 1, 1, 10, 0, 0, tzinfo=local_tz), 3),
|
||||||
# months apart
|
# months apart
|
||||||
MockArchive(datetime(2017, 2, 1, 10, 0, 0, tzinfo=timezone.utc), 4),
|
MockArchive(datetime(2017, 2, 1, 10, 0, 0, tzinfo=local_tz), 4),
|
||||||
MockArchive(datetime(2017, 3, 1, 10, 0, 0, tzinfo=timezone.utc), 5),
|
MockArchive(datetime(2017, 3, 1, 10, 0, 0, tzinfo=local_tz), 5),
|
||||||
# days apart
|
# days apart
|
||||||
MockArchive(datetime(2017, 3, 2, 10, 0, 0, tzinfo=timezone.utc), 6),
|
MockArchive(datetime(2017, 3, 2, 10, 0, 0, tzinfo=local_tz), 6),
|
||||||
MockArchive(datetime(2017, 3, 3, 10, 0, 0, tzinfo=timezone.utc), 7),
|
MockArchive(datetime(2017, 3, 3, 10, 0, 0, tzinfo=local_tz), 7),
|
||||||
MockArchive(datetime(2017, 3, 4, 10, 0, 0, tzinfo=timezone.utc), 8),
|
MockArchive(datetime(2017, 3, 4, 10, 0, 0, tzinfo=local_tz), 8),
|
||||||
# minutes apart
|
# minutes apart
|
||||||
MockArchive(datetime(2017, 10, 1, 9, 45, 0, tzinfo=timezone.utc), 9),
|
MockArchive(datetime(2017, 10, 1, 9, 45, 0, tzinfo=local_tz), 9),
|
||||||
MockArchive(datetime(2017, 10, 1, 9, 55, 0, tzinfo=timezone.utc), 10),
|
MockArchive(datetime(2017, 10, 1, 9, 55, 0, tzinfo=local_tz), 10),
|
||||||
# seconds apart
|
# seconds apart
|
||||||
MockArchive(datetime(2017, 10, 1, 10, 0, 1, tzinfo=timezone.utc), 11),
|
MockArchive(datetime(2017, 10, 1, 10, 0, 1, tzinfo=local_tz), 11),
|
||||||
MockArchive(datetime(2017, 10, 1, 10, 0, 3, tzinfo=timezone.utc), 12),
|
MockArchive(datetime(2017, 10, 1, 10, 0, 3, tzinfo=local_tz), 12),
|
||||||
MockArchive(datetime(2017, 10, 1, 10, 0, 5, tzinfo=timezone.utc), 13),
|
MockArchive(datetime(2017, 10, 1, 10, 0, 5, tzinfo=local_tz), 13),
|
||||||
]
|
]
|
||||||
kept_because = {}
|
kept_because = {}
|
||||||
keep = prune_split(archives, rule, num_to_keep, kept_because)
|
keep = prune_split(archives, rule, num_to_keep, kept_because)
|
||||||
|
@ -456,12 +467,12 @@ def subset(lst, ids):
|
||||||
|
|
||||||
archives = [
|
archives = [
|
||||||
# oldest backup, but not last in its year
|
# 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
|
# 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
|
# year end backups
|
||||||
MockArchive(datetime(2018, 12, 31, 10, 0, 0, tzinfo=timezone.utc), 3),
|
MockArchive(datetime(2018, 12, 31, 10, 0, 0, tzinfo=local_tz), 3),
|
||||||
MockArchive(datetime(2019, 12, 31, 10, 0, 0, tzinfo=timezone.utc), 4),
|
MockArchive(datetime(2019, 12, 31, 10, 0, 0, tzinfo=local_tz), 4),
|
||||||
]
|
]
|
||||||
|
|
||||||
# Keep oldest when retention target can't otherwise be met
|
# Keep oldest when retention target can't otherwise be met
|
||||||
|
|
Loading…
Reference in a new issue