mirror of
https://github.com/borgbackup/borg.git
synced 2025-03-03 18:27:01 +00:00
Purge improvements: New options yearly and prefix
This commit is contained in:
parent
e0615df187
commit
9feef66d4e
3 changed files with 35 additions and 10 deletions
|
@ -43,7 +43,9 @@ def load(self, id):
|
|||
except self.store.DoesNotExist:
|
||||
raise self.DoesNotExist
|
||||
self.metadata = msgpack.unpackb(data)
|
||||
assert self.metadata['version'] == 1
|
||||
if self.metadata['version'] != 1:
|
||||
raise Exception('Unknown archive metadata version')
|
||||
self.name = self.metadata['name']
|
||||
|
||||
@property
|
||||
def ts(self):
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
from .key import Key
|
||||
from .helpers import location_validator, format_file_size, format_time,\
|
||||
format_file_mode, IncludePattern, ExcludePattern, exclude_path, to_localtime, \
|
||||
get_cache_dir
|
||||
get_cache_dir, day_of_year
|
||||
from .remote import StoreServer, RemoteStore
|
||||
|
||||
class Archiver(object):
|
||||
|
@ -224,31 +224,39 @@ def do_purge(self, args):
|
|||
num_daily = args.daily
|
||||
num_weekly = args.weekly
|
||||
num_monthly = args.monthly
|
||||
if args.daily + args.weekly + args.monthly == 0:
|
||||
self.print_error('At least one of the "daily", "weekly", "monthly" '
|
||||
num_yearly = args.yearly
|
||||
if args.daily + args.weekly + args.monthly + args.yearly == 0:
|
||||
self.print_error('At least one of the "daily", "weekly", "monthly" or "yearly" '
|
||||
'settings must be specified')
|
||||
return 1
|
||||
t0 = date.today() + timedelta(days=1) # Tomorrow
|
||||
daily = weekly = monthly = 0
|
||||
daily = weekly = monthly = yearly = 0
|
||||
for archive in archives:
|
||||
if args.prefix and not archive.name.startswith(args.prefix):
|
||||
continue
|
||||
t = to_localtime(archive.ts).date()
|
||||
if daily < args.daily and t < t0:
|
||||
daily += 1
|
||||
self.print_verbose('Archive "%s" is daily archive number %d',
|
||||
archive.metadata['name'], daily)
|
||||
archive.name, daily)
|
||||
t0 = t
|
||||
elif weekly < args.weekly and t < t0 and t.weekday() == 1:
|
||||
weekly += 1
|
||||
self.print_verbose('Archive "%s" is weekly archive number %d',
|
||||
archive.metadata['name'], weekly)
|
||||
archive.name, weekly)
|
||||
t0 = t
|
||||
elif monthly < args.monthly and t < t0 and t.day == 1:
|
||||
num_weekly += 1
|
||||
monthly += 1
|
||||
self.print_verbose('Archive "%s" is monthly archive number %d',
|
||||
archive.metadata['name'], monthly)
|
||||
archive.name, monthly)
|
||||
t0 = t
|
||||
elif yearly < args.yearly and t < t0 and day_of_year(t) == 1:
|
||||
yearly += 1
|
||||
self.print_verbose('Archive "%s" is yearly archive number %d',
|
||||
archive.name, yearly)
|
||||
t0 = t
|
||||
else:
|
||||
self.print_verbose('Purging archive %s', archive.metadata['name'])
|
||||
self.print_verbose('Purging archive %s', archive.name)
|
||||
if args.really:
|
||||
archive.delete(cache)
|
||||
else:
|
||||
|
@ -346,6 +354,10 @@ def run(self, args=None):
|
|||
help='Number of daily archives to keep')
|
||||
subparser.add_argument('-m', '--monthly', dest='monthly', type=int, default=0,
|
||||
help='Number of monthly archives to keep')
|
||||
subparser.add_argument('-y', '--yearly', dest='yearly', type=int, default=0,
|
||||
help='Number of yearly archives to keep')
|
||||
subparser.add_argument('-p', '--prefix', dest='prefix', type=str,
|
||||
help='Only consider archive names starting with this prefix')
|
||||
subparser.add_argument('-r', '--really', dest='really',
|
||||
action='store_true', default=False,
|
||||
help='Actually delete archives')
|
||||
|
|
|
@ -12,6 +12,12 @@
|
|||
import time
|
||||
import urllib
|
||||
|
||||
|
||||
def day_of_year(d):
|
||||
"""Calculate the "day of year" from a date object"""
|
||||
return int(d.strftime('%j'))
|
||||
|
||||
|
||||
# OSX filenames are UTF-8 Only so any non-utf8 filenames are url encoded
|
||||
if sys.platform == 'darwin':
|
||||
def encode_filename(name):
|
||||
|
@ -23,6 +29,7 @@ def encode_filename(name):
|
|||
else:
|
||||
encode_filename = str
|
||||
|
||||
|
||||
class Counter(object):
|
||||
|
||||
__slots__ = ('v',)
|
||||
|
@ -48,6 +55,7 @@ def get_keys_dir():
|
|||
return os.environ.get('DARC_KEYS_DIR',
|
||||
os.path.join(os.path.expanduser('~'), '.darc', 'keys'))
|
||||
|
||||
|
||||
def get_cache_dir():
|
||||
"""Determine where to store keys and cache"""
|
||||
return os.environ.get('DARC_CACHE_DIR',
|
||||
|
@ -69,14 +77,17 @@ def wrapper(*args, **kw):
|
|||
return f(*args, **kw)
|
||||
return wrapper
|
||||
|
||||
|
||||
def error_callback(res, error, data):
|
||||
if res:
|
||||
raise res
|
||||
|
||||
|
||||
def to_localtime(ts):
|
||||
"""Convert datetime object from UTC to local time zone"""
|
||||
return ts - timedelta(seconds=time.altzone)
|
||||
|
||||
|
||||
def read_set(path):
|
||||
"""Read set from disk (as int32s)
|
||||
"""
|
||||
|
|
Loading…
Reference in a new issue