mirror of
https://github.com/borgbackup/borg.git
synced 2024-09-19 08:18:10 +03:00
pyupgrade --py38-plus ./**/*.py
This commit is contained in:
parent
d1bcea9e61
commit
cbeef56454
@ -40,7 +40,7 @@
|
|||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = 'Borg - Deduplicating Archiver'
|
project = 'Borg - Deduplicating Archiver'
|
||||||
copyright = u'2010-2014 Jonas Borgström, 2015-2022 The Borg Collective (see AUTHORS file)'
|
copyright = '2010-2014 Jonas Borgström, 2015-2022 The Borg Collective (see AUTHORS file)'
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
@ -35,12 +35,12 @@ def main():
|
|||||||
output = subprocess.check_output(objdump % filename, shell=True,
|
output = subprocess.check_output(objdump % filename, shell=True,
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
output = output.decode()
|
output = output.decode()
|
||||||
versions = set(parse_version(match.group(1))
|
versions = {parse_version(match.group(1))
|
||||||
for match in glibc_re.finditer(output))
|
for match in glibc_re.finditer(output)}
|
||||||
requires_glibc = max(versions)
|
requires_glibc = max(versions)
|
||||||
overall_versions.add(requires_glibc)
|
overall_versions.add(requires_glibc)
|
||||||
if verbose:
|
if verbose:
|
||||||
print("%s %s" % (filename, format_version(requires_glibc)))
|
print(f"{filename} {format_version(requires_glibc)}")
|
||||||
except subprocess.CalledProcessError:
|
except subprocess.CalledProcessError:
|
||||||
if verbose:
|
if verbose:
|
||||||
print("%s errored." % filename)
|
print("%s errored." % filename)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
This script checks compatibility of crypto.blake2b_256 against hashlib.blake2b in CPython 3.6.
|
This script checks compatibility of crypto.blake2b_256 against hashlib.blake2b in CPython 3.6.
|
||||||
"""
|
"""
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
|
|
||||||
def long_desc_from_readme():
|
def long_desc_from_readme():
|
||||||
with open('README.rst', 'r') as fd:
|
with open('README.rst') as fd:
|
||||||
long_description = fd.read()
|
long_description = fd.read()
|
||||||
# remove header, but have one \n before first headline
|
# remove header, but have one \n before first headline
|
||||||
start = long_description.find('What is BorgBackup?')
|
start = long_description.find('What is BorgBackup?')
|
||||||
@ -33,7 +33,7 @@ def format_metavar(option):
|
|||||||
elif option.nargs is None:
|
elif option.nargs is None:
|
||||||
return option.metavar
|
return option.metavar
|
||||||
else:
|
else:
|
||||||
raise ValueError('Can\'t format metavar %s, unknown nargs %s!' % (option.metavar, option.nargs))
|
raise ValueError(f'Can\'t format metavar {option.metavar}, unknown nargs {option.nargs}!')
|
||||||
|
|
||||||
|
|
||||||
class build_usage(Command):
|
class build_usage(Command):
|
||||||
@ -367,7 +367,7 @@ def generate_level(self, prefix, parser, Archiver, extra_choices=None):
|
|||||||
subparsers = [action for action in parser._actions if 'SubParsersAction' in str(action.__class__)][0]
|
subparsers = [action for action in parser._actions if 'SubParsersAction' in str(action.__class__)][0]
|
||||||
for subcommand in subparsers.choices:
|
for subcommand in subparsers.choices:
|
||||||
write('| borg', '[common options]', command, subcommand, '...')
|
write('| borg', '[common options]', command, subcommand, '...')
|
||||||
self.see_also.setdefault(command, []).append('%s-%s' % (command, subcommand))
|
self.see_also.setdefault(command, []).append(f'{command}-{subcommand}')
|
||||||
else:
|
else:
|
||||||
if command == "borgfs":
|
if command == "borgfs":
|
||||||
write(command, end='')
|
write(command, end='')
|
||||||
|
@ -198,7 +198,7 @@ def __init__(self, op, os_error):
|
|||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
if self.op:
|
if self.op:
|
||||||
return '%s: %s' % (self.op, self.os_error)
|
return f'{self.op}: {self.os_error}'
|
||||||
else:
|
else:
|
||||||
return str(self.os_error)
|
return str(self.os_error)
|
||||||
|
|
||||||
@ -464,7 +464,7 @@ def __init__(self, repository, key, manifest, name, cache=None, create=False,
|
|||||||
raise self.AlreadyExists(name)
|
raise self.AlreadyExists(name)
|
||||||
i = 0
|
i = 0
|
||||||
while True:
|
while True:
|
||||||
self.checkpoint_name = '%s.checkpoint%s' % (name, i and ('.%d' % i) or '')
|
self.checkpoint_name = '{}.checkpoint{}'.format(name, i and ('.%d' % i) or '')
|
||||||
if self.checkpoint_name not in manifest.archives:
|
if self.checkpoint_name not in manifest.archives:
|
||||||
break
|
break
|
||||||
i += 1
|
i += 1
|
||||||
@ -1823,7 +1823,7 @@ def replacement_chunk(size):
|
|||||||
chunks_healthy = item.chunks_healthy if has_chunks_healthy else chunks_current
|
chunks_healthy = item.chunks_healthy if has_chunks_healthy else chunks_current
|
||||||
if has_chunks_healthy and len(chunks_current) != len(chunks_healthy):
|
if has_chunks_healthy and len(chunks_current) != len(chunks_healthy):
|
||||||
# should never happen, but there was issue #3218.
|
# should never happen, but there was issue #3218.
|
||||||
logger.warning('{}: {}: Invalid chunks_healthy metadata removed!'.format(archive_name, item.path))
|
logger.warning(f'{archive_name}: {item.path}: Invalid chunks_healthy metadata removed!')
|
||||||
del item.chunks_healthy
|
del item.chunks_healthy
|
||||||
has_chunks_healthy = False
|
has_chunks_healthy = False
|
||||||
chunks_healthy = chunks_current
|
chunks_healthy = chunks_current
|
||||||
@ -1867,7 +1867,7 @@ def replacement_chunk(size):
|
|||||||
# if this is first repair, remember the correct chunk IDs, so we can maybe heal the file later
|
# if this is first repair, remember the correct chunk IDs, so we can maybe heal the file later
|
||||||
item.chunks_healthy = item.chunks
|
item.chunks_healthy = item.chunks
|
||||||
if has_chunks_healthy and chunk_list == chunks_healthy:
|
if has_chunks_healthy and chunk_list == chunks_healthy:
|
||||||
logger.info('{}: {}: Completely healed previously damaged file!'.format(archive_name, item.path))
|
logger.info(f'{archive_name}: {item.path}: Completely healed previously damaged file!')
|
||||||
del item.chunks_healthy
|
del item.chunks_healthy
|
||||||
item.chunks = chunk_list
|
item.chunks = chunk_list
|
||||||
if 'size' in item:
|
if 'size' in item:
|
||||||
@ -1902,7 +1902,7 @@ def report(msg, chunk_id, chunk_no):
|
|||||||
logger.error(msg)
|
logger.error(msg)
|
||||||
|
|
||||||
def list_keys_safe(keys):
|
def list_keys_safe(keys):
|
||||||
return ', '.join((k.decode(errors='replace') if isinstance(k, bytes) else str(k) for k in keys))
|
return ', '.join(k.decode(errors='replace') if isinstance(k, bytes) else str(k) for k in keys)
|
||||||
|
|
||||||
def valid_item(obj):
|
def valid_item(obj):
|
||||||
if not isinstance(obj, StableDict):
|
if not isinstance(obj, StableDict):
|
||||||
@ -1972,7 +1972,7 @@ def valid_item(obj):
|
|||||||
with cache_if_remote(self.repository) as repository:
|
with cache_if_remote(self.repository) as repository:
|
||||||
for i, info in enumerate(archive_infos):
|
for i, info in enumerate(archive_infos):
|
||||||
pi.show(i)
|
pi.show(i)
|
||||||
logger.info('Analyzing archive {} ({}/{})'.format(info.name, i + 1, num_archives))
|
logger.info(f'Analyzing archive {info.name} ({i + 1}/{num_archives})')
|
||||||
archive_id = info.id
|
archive_id = info.id
|
||||||
if archive_id not in self.chunks:
|
if archive_id not in self.chunks:
|
||||||
logger.error('Archive metadata block is missing!')
|
logger.error('Archive metadata block is missing!')
|
||||||
@ -2008,7 +2008,7 @@ def orphan_chunks_check(self):
|
|||||||
unused = {id_ for id_, entry in self.chunks.iteritems() if entry.refcount == 0}
|
unused = {id_ for id_, entry in self.chunks.iteritems() if entry.refcount == 0}
|
||||||
orphaned = unused - self.possibly_superseded
|
orphaned = unused - self.possibly_superseded
|
||||||
if orphaned:
|
if orphaned:
|
||||||
logger.error('{} orphaned objects found!'.format(len(orphaned)))
|
logger.error(f'{len(orphaned)} orphaned objects found!')
|
||||||
self.error_found = True
|
self.error_found = True
|
||||||
if self.repair and unused:
|
if self.repair and unused:
|
||||||
logger.info('Deleting %d orphaned and %d superseded objects...' % (
|
logger.info('Deleting %d orphaned and %d superseded objects...' % (
|
||||||
|
@ -377,7 +377,7 @@ def do_key_export(self, args, repository):
|
|||||||
else:
|
else:
|
||||||
manager.export(args.path)
|
manager.export(args.path)
|
||||||
except IsADirectoryError:
|
except IsADirectoryError:
|
||||||
self.print_error("'{}' must be a file, not a directory".format(args.path))
|
self.print_error(f"'{args.path}' must be a file, not a directory")
|
||||||
return EXIT_ERROR
|
return EXIT_ERROR
|
||||||
return EXIT_SUCCESS
|
return EXIT_SUCCESS
|
||||||
|
|
||||||
@ -1191,7 +1191,7 @@ def _delete_archives(self, args, repository):
|
|||||||
current_archive = manifest.archives.pop(archive_name)
|
current_archive = manifest.archives.pop(archive_name)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.exit_code = EXIT_WARNING
|
self.exit_code = EXIT_WARNING
|
||||||
logger.warning('Archive {} not found ({}/{}).'.format(archive_name, i, len(archive_names)))
|
logger.warning(f'Archive {archive_name} not found ({i}/{len(archive_names)}).')
|
||||||
else:
|
else:
|
||||||
deleted = True
|
deleted = True
|
||||||
if self.output_list:
|
if self.output_list:
|
||||||
@ -1851,12 +1851,12 @@ def list_config(config):
|
|||||||
value = default_values.get(key)
|
value = default_values.get(key)
|
||||||
if value is None:
|
if value is None:
|
||||||
raise Error('The repository config is missing the %s key which has no default value' % key)
|
raise Error('The repository config is missing the %s key which has no default value' % key)
|
||||||
print('%s = %s' % (key, value))
|
print(f'{key} = {value}')
|
||||||
for key in ['last_segment_checked', ]:
|
for key in ['last_segment_checked', ]:
|
||||||
value = config.get('repository', key, fallback=None)
|
value = config.get('repository', key, fallback=None)
|
||||||
if value is None:
|
if value is None:
|
||||||
continue
|
continue
|
||||||
print('%s = %s' % (key, value))
|
print(f'{key} = {value}')
|
||||||
|
|
||||||
if not args.list:
|
if not args.list:
|
||||||
if args.name is None:
|
if args.name is None:
|
||||||
@ -2059,7 +2059,7 @@ def do_debug_search_repo_objs(self, args, repository):
|
|||||||
def print_finding(info, wanted, data, offset):
|
def print_finding(info, wanted, data, offset):
|
||||||
before = data[offset - context:offset]
|
before = data[offset - context:offset]
|
||||||
after = data[offset + len(wanted):offset + len(wanted) + context]
|
after = data[offset + len(wanted):offset + len(wanted) + context]
|
||||||
print('%s: %s %s %s == %r %r %r' % (info, before.hex(), wanted.hex(), after.hex(),
|
print('{}: {} {} {} == {!r} {!r} {!r}'.format(info, before.hex(), wanted.hex(), after.hex(),
|
||||||
before, wanted, after))
|
before, wanted, after))
|
||||||
|
|
||||||
wanted = args.wanted
|
wanted = args.wanted
|
||||||
@ -5032,7 +5032,7 @@ def sig_info_handler(sig_no, stack): # pragma: no cover
|
|||||||
total = loc['st'].st_size
|
total = loc['st'].st_size
|
||||||
except Exception:
|
except Exception:
|
||||||
pos, total = 0, 0
|
pos, total = 0, 0
|
||||||
logger.info("{0} {1}/{2}".format(path, format_file_size(pos), format_file_size(total)))
|
logger.info(f"{path} {format_file_size(pos)}/{format_file_size(total)}")
|
||||||
break
|
break
|
||||||
if func in ('extract_item', ): # extract op
|
if func in ('extract_item', ): # extract op
|
||||||
path = loc['item'].path
|
path = loc['item'].path
|
||||||
@ -5040,7 +5040,7 @@ def sig_info_handler(sig_no, stack): # pragma: no cover
|
|||||||
pos = loc['fd'].tell()
|
pos = loc['fd'].tell()
|
||||||
except Exception:
|
except Exception:
|
||||||
pos = 0
|
pos = 0
|
||||||
logger.info("{0} {1}/???".format(path, format_file_size(pos)))
|
logger.info(f"{path} {format_file_size(pos)}/???")
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
@ -5078,7 +5078,7 @@ def main(): # pragma: no cover
|
|||||||
except Error as e:
|
except Error as e:
|
||||||
msg = e.get_message()
|
msg = e.get_message()
|
||||||
tb_log_level = logging.ERROR if e.traceback else logging.DEBUG
|
tb_log_level = logging.ERROR if e.traceback else logging.DEBUG
|
||||||
tb = '%s\n%s' % (traceback.format_exc(), sysinfo())
|
tb = f'{traceback.format_exc()}\n{sysinfo()}'
|
||||||
# we might not have logging setup yet, so get out quickly
|
# we might not have logging setup yet, so get out quickly
|
||||||
print(msg, file=sys.stderr)
|
print(msg, file=sys.stderr)
|
||||||
if tb_log_level == logging.ERROR:
|
if tb_log_level == logging.ERROR:
|
||||||
@ -5091,7 +5091,7 @@ def main(): # pragma: no cover
|
|||||||
msg = e.get_message()
|
msg = e.get_message()
|
||||||
msgid = type(e).__qualname__
|
msgid = type(e).__qualname__
|
||||||
tb_log_level = logging.ERROR if e.traceback else logging.DEBUG
|
tb_log_level = logging.ERROR if e.traceback else logging.DEBUG
|
||||||
tb = "%s\n%s" % (traceback.format_exc(), sysinfo())
|
tb = f"{traceback.format_exc()}\n{sysinfo()}"
|
||||||
exit_code = e.exit_code
|
exit_code = e.exit_code
|
||||||
except RemoteRepository.RPCError as e:
|
except RemoteRepository.RPCError as e:
|
||||||
important = e.exception_class not in ('LockTimeout', ) and e.traceback
|
important = e.exception_class not in ('LockTimeout', ) and e.traceback
|
||||||
@ -5108,18 +5108,18 @@ def main(): # pragma: no cover
|
|||||||
msg = 'Local Exception'
|
msg = 'Local Exception'
|
||||||
msgid = 'Exception'
|
msgid = 'Exception'
|
||||||
tb_log_level = logging.ERROR
|
tb_log_level = logging.ERROR
|
||||||
tb = '%s\n%s' % (traceback.format_exc(), sysinfo())
|
tb = f'{traceback.format_exc()}\n{sysinfo()}'
|
||||||
exit_code = EXIT_ERROR
|
exit_code = EXIT_ERROR
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
msg = 'Keyboard interrupt'
|
msg = 'Keyboard interrupt'
|
||||||
tb_log_level = logging.DEBUG
|
tb_log_level = logging.DEBUG
|
||||||
tb = '%s\n%s' % (traceback.format_exc(), sysinfo())
|
tb = f'{traceback.format_exc()}\n{sysinfo()}'
|
||||||
exit_code = EXIT_SIGNAL_BASE + 2
|
exit_code = EXIT_SIGNAL_BASE + 2
|
||||||
except SigTerm:
|
except SigTerm:
|
||||||
msg = 'Received SIGTERM'
|
msg = 'Received SIGTERM'
|
||||||
msgid = 'Signal.SIGTERM'
|
msgid = 'Signal.SIGTERM'
|
||||||
tb_log_level = logging.DEBUG
|
tb_log_level = logging.DEBUG
|
||||||
tb = '%s\n%s' % (traceback.format_exc(), sysinfo())
|
tb = f'{traceback.format_exc()}\n{sysinfo()}'
|
||||||
exit_code = EXIT_SIGNAL_BASE + 15
|
exit_code = EXIT_SIGNAL_BASE + 15
|
||||||
except SigHup:
|
except SigHup:
|
||||||
msg = 'Received SIGHUP.'
|
msg = 'Received SIGHUP.'
|
||||||
|
@ -83,7 +83,7 @@ def key_matches(self, key):
|
|||||||
if not self.known():
|
if not self.known():
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
with open(self.key_type_file, 'r') as fd:
|
with open(self.key_type_file) as fd:
|
||||||
type = fd.read()
|
type = fd.read()
|
||||||
return type == str(key.TYPE)
|
return type == str(key.TYPE)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
@ -687,13 +687,13 @@ def cached_archives():
|
|||||||
fns = os.listdir(archive_path)
|
fns = os.listdir(archive_path)
|
||||||
# filenames with 64 hex digits == 256bit,
|
# filenames with 64 hex digits == 256bit,
|
||||||
# or compact indices which are 64 hex digits + ".compact"
|
# or compact indices which are 64 hex digits + ".compact"
|
||||||
return set(unhexlify(fn) for fn in fns if len(fn) == 64) | \
|
return {unhexlify(fn) for fn in fns if len(fn) == 64} | \
|
||||||
set(unhexlify(fn[:64]) for fn in fns if len(fn) == 72 and fn.endswith('.compact'))
|
{unhexlify(fn[:64]) for fn in fns if len(fn) == 72 and fn.endswith('.compact')}
|
||||||
else:
|
else:
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
def repo_archives():
|
def repo_archives():
|
||||||
return set(info.id for info in self.manifest.archives.list())
|
return {info.id for info in self.manifest.archives.list()}
|
||||||
|
|
||||||
def cleanup_outdated(ids):
|
def cleanup_outdated(ids):
|
||||||
for id in ids:
|
for id in ids:
|
||||||
|
@ -224,7 +224,7 @@ def integrity_file_path(path):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def read_integrity_file(cls, path):
|
def read_integrity_file(cls, path):
|
||||||
try:
|
try:
|
||||||
with open(cls.integrity_file_path(path), 'r') as fd:
|
with open(cls.integrity_file_path(path)) as fd:
|
||||||
return cls.parse_integrity_data(path, fd.read())
|
return cls.parse_integrity_data(path, fd.read())
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
logger.info('No integrity file found for %s', path)
|
logger.info('No integrity file found for %s', path)
|
||||||
|
@ -379,7 +379,7 @@ def decrypt(self, id, data, decompress=True):
|
|||||||
try:
|
try:
|
||||||
payload = self.cipher.decrypt(data)
|
payload = self.cipher.decrypt(data)
|
||||||
except IntegrityError as e:
|
except IntegrityError as e:
|
||||||
raise IntegrityError("Chunk %s: Could not decrypt [%s]" % (bin_to_hex(id), str(e)))
|
raise IntegrityError(f"Chunk {bin_to_hex(id)}: Could not decrypt [{str(e)}]")
|
||||||
if not decompress:
|
if not decompress:
|
||||||
return payload
|
return payload
|
||||||
data = self.decompress(payload)
|
data = self.decompress(payload)
|
||||||
@ -469,7 +469,7 @@ def getpass(cls, prompt):
|
|||||||
msg = []
|
msg = []
|
||||||
for env_var in 'BORG_PASSPHRASE', 'BORG_PASSCOMMAND':
|
for env_var in 'BORG_PASSPHRASE', 'BORG_PASSCOMMAND':
|
||||||
env_var_set = os.environ.get(env_var) is not None
|
env_var_set = os.environ.get(env_var) is not None
|
||||||
msg.append('%s is %s.' % (env_var, 'set' if env_var_set else 'not set'))
|
msg.append('{} is {}.'.format(env_var, 'set' if env_var_set else 'not set'))
|
||||||
msg.append('Interactive password query failed.')
|
msg.append('Interactive password query failed.')
|
||||||
raise NoPassphraseFailure(' '.join(msg)) from None
|
raise NoPassphraseFailure(' '.join(msg)) from None
|
||||||
else:
|
else:
|
||||||
@ -760,7 +760,7 @@ def _get_new_target_in_keys_dir(self, args):
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
def load(self, target, passphrase):
|
def load(self, target, passphrase):
|
||||||
with open(target, 'r') as fd:
|
with open(target) as fd:
|
||||||
key_data = ''.join(fd.readlines()[1:])
|
key_data = ''.join(fd.readlines()[1:])
|
||||||
success = self._load(key_data, passphrase)
|
success = self._load(key_data, passphrase)
|
||||||
if success:
|
if success:
|
||||||
@ -775,7 +775,7 @@ def save(self, target, passphrase, create=False):
|
|||||||
raise Error('Aborting because key in "%s" already exists.' % target)
|
raise Error('Aborting because key in "%s" already exists.' % target)
|
||||||
key_data = self._save(passphrase)
|
key_data = self._save(passphrase)
|
||||||
with SaveFile(target) as fd:
|
with SaveFile(target) as fd:
|
||||||
fd.write('%s %s\n' % (self.FILE_ID, bin_to_hex(self.repository_id)))
|
fd.write(f'{self.FILE_ID} {bin_to_hex(self.repository_id)}\n')
|
||||||
fd.write(key_data)
|
fd.write(key_data)
|
||||||
fd.write('\n')
|
fd.write('\n')
|
||||||
self.target = target
|
self.target = target
|
||||||
|
@ -52,7 +52,7 @@ def load_keyblob(self):
|
|||||||
if self.keyblob_storage == KeyBlobStorage.KEYFILE:
|
if self.keyblob_storage == KeyBlobStorage.KEYFILE:
|
||||||
k = KeyfileKey(self.repository)
|
k = KeyfileKey(self.repository)
|
||||||
target = k.find_key()
|
target = k.find_key()
|
||||||
with open(target, 'r') as fd:
|
with open(target) as fd:
|
||||||
self.keyblob = ''.join(fd.readlines()[1:])
|
self.keyblob = ''.join(fd.readlines()[1:])
|
||||||
|
|
||||||
elif self.keyblob_storage == KeyBlobStorage.REPO:
|
elif self.keyblob_storage == KeyBlobStorage.REPO:
|
||||||
@ -68,7 +68,7 @@ def store_keyblob(self, args):
|
|||||||
self.repository.save_key(self.keyblob.encode('utf-8'))
|
self.repository.save_key(self.keyblob.encode('utf-8'))
|
||||||
|
|
||||||
def get_keyfile_data(self):
|
def get_keyfile_data(self):
|
||||||
data = '%s %s\n' % (KeyfileKey.FILE_ID, bin_to_hex(self.repository.id))
|
data = f'{KeyfileKey.FILE_ID} {bin_to_hex(self.repository.id)}\n'
|
||||||
data += self.keyblob
|
data += self.keyblob
|
||||||
if not self.keyblob.endswith('\n'):
|
if not self.keyblob.endswith('\n'):
|
||||||
data += '\n'
|
data += '\n'
|
||||||
@ -115,7 +115,7 @@ def grouped(s):
|
|||||||
lines = (len(binary) + 17) // 18
|
lines = (len(binary) + 17) // 18
|
||||||
repoid = bin_to_hex(self.repository.id)[:18]
|
repoid = bin_to_hex(self.repository.id)[:18]
|
||||||
complete_checksum = sha256_truncated(binary, 12)
|
complete_checksum = sha256_truncated(binary, 12)
|
||||||
export += 'id: {0:d} / {1} / {2} - {3}\n'.format(lines,
|
export += 'id: {:d} / {} / {} - {}\n'.format(lines,
|
||||||
grouped(repoid),
|
grouped(repoid),
|
||||||
grouped(complete_checksum),
|
grouped(complete_checksum),
|
||||||
sha256_truncated((str(lines) + '/' + repoid + '/' + complete_checksum).encode('ascii'), 2))
|
sha256_truncated((str(lines) + '/' + repoid + '/' + complete_checksum).encode('ascii'), 2))
|
||||||
@ -124,7 +124,7 @@ def grouped(s):
|
|||||||
idx += 1
|
idx += 1
|
||||||
binline = binary[:18]
|
binline = binary[:18]
|
||||||
checksum = sha256_truncated(idx.to_bytes(2, byteorder='big') + binline, 2)
|
checksum = sha256_truncated(idx.to_bytes(2, byteorder='big') + binline, 2)
|
||||||
export += '{0:2d}: {1} - {2}\n'.format(idx, grouped(bin_to_hex(binline)), checksum)
|
export += f'{idx:2d}: {grouped(bin_to_hex(binline))} - {checksum}\n'
|
||||||
binary = binary[18:]
|
binary = binary[18:]
|
||||||
|
|
||||||
with dash_open(path, 'w') as fd:
|
with dash_open(path, 'w') as fd:
|
||||||
@ -188,7 +188,7 @@ def import_paperkey(self, args):
|
|||||||
idx = 1
|
idx = 1
|
||||||
# body line input
|
# body line input
|
||||||
while True:
|
while True:
|
||||||
inline = input('{0:2d}: '.format(idx))
|
inline = input(f'{idx:2d}: ')
|
||||||
inline = inline.replace(' ', '')
|
inline = inline.replace(' ', '')
|
||||||
if inline == '':
|
if inline == '':
|
||||||
if yes('Abort import? [yN]:'):
|
if yes('Abort import? [yN]:'):
|
||||||
@ -204,7 +204,7 @@ def import_paperkey(self, args):
|
|||||||
print("only characters 0-9 and a-f and '-' are valid, try again")
|
print("only characters 0-9 and a-f and '-' are valid, try again")
|
||||||
continue
|
continue
|
||||||
if sha256_truncated(idx.to_bytes(2, byteorder='big') + part, 2) != checksum:
|
if sha256_truncated(idx.to_bytes(2, byteorder='big') + part, 2) != checksum:
|
||||||
print('line checksum did not match, try line {0} again'.format(idx))
|
print(f'line checksum did not match, try line {idx} again')
|
||||||
continue
|
continue
|
||||||
result += part
|
result += part
|
||||||
if idx == lines:
|
if idx == lines:
|
||||||
|
@ -22,7 +22,7 @@ def __init__(self, repository, manifest_nonce):
|
|||||||
|
|
||||||
def get_local_free_nonce(self):
|
def get_local_free_nonce(self):
|
||||||
try:
|
try:
|
||||||
with open(self.nonce_file, 'r') as fd:
|
with open(self.nonce_file) as fd:
|
||||||
return bytes_to_long(unhexlify(fd.read()))
|
return bytes_to_long(unhexlify(fd.read()))
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return None
|
return None
|
||||||
|
@ -234,7 +234,7 @@ def iter_archive_items(self, archive_item_ids, filter=None, consider_part_files=
|
|||||||
self.write_offset = write_offset
|
self.write_offset = write_offset
|
||||||
|
|
||||||
|
|
||||||
class FuseBackend(object):
|
class FuseBackend:
|
||||||
"""Virtual filesystem based on archive(s) to provide information to fuse
|
"""Virtual filesystem based on archive(s) to provide information to fuse
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ def get_all_mandatory_features(self):
|
|||||||
|
|
||||||
for operation, requirements in feature_flags.items():
|
for operation, requirements in feature_flags.items():
|
||||||
if b'mandatory' in requirements:
|
if b'mandatory' in requirements:
|
||||||
result[operation.decode()] = set([feature.decode() for feature in requirements[b'mandatory']])
|
result[operation.decode()] = {feature.decode() for feature in requirements[b'mandatory']}
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def write(self):
|
def write(self):
|
||||||
|
@ -91,13 +91,13 @@ def sysinfo():
|
|||||||
from ..fuse_impl import llfuse, BORG_FUSE_IMPL
|
from ..fuse_impl import llfuse, BORG_FUSE_IMPL
|
||||||
llfuse_name = llfuse.__name__ if llfuse else 'None'
|
llfuse_name = llfuse.__name__ if llfuse else 'None'
|
||||||
llfuse_version = (' %s' % llfuse.__version__) if llfuse else ''
|
llfuse_version = (' %s' % llfuse.__version__) if llfuse else ''
|
||||||
llfuse_info = '%s%s [%s]' % (llfuse_name, llfuse_version, BORG_FUSE_IMPL)
|
llfuse_info = f'{llfuse_name}{llfuse_version} [{BORG_FUSE_IMPL}]'
|
||||||
info = []
|
info = []
|
||||||
if uname is not None:
|
if uname is not None:
|
||||||
info.append('Platform: %s' % (' '.join(uname), ))
|
info.append('Platform: {}'.format(' '.join(uname)))
|
||||||
if linux_distribution is not None:
|
if linux_distribution is not None:
|
||||||
info.append('Linux: %s %s %s' % linux_distribution)
|
info.append('Linux: %s %s %s' % linux_distribution)
|
||||||
info.append('Borg: %s Python: %s %s msgpack: %s fuse: %s' % (
|
info.append('Borg: {} Python: {} {} msgpack: {} fuse: {}'.format(
|
||||||
borg_version, python_implementation, python_version, msgpack_version, llfuse_info))
|
borg_version, python_implementation, python_version, msgpack_version, llfuse_info))
|
||||||
info.append('PID: %d CWD: %s' % (os.getpid(), os.getcwd()))
|
info.append('PID: %d CWD: %s' % (os.getpid(), os.getcwd()))
|
||||||
info.append('sys.argv: %r' % sys.argv)
|
info.append('sys.argv: %r' % sys.argv)
|
||||||
|
@ -80,7 +80,7 @@ def interval(s):
|
|||||||
# range suffixes in ascending multiplier order
|
# range suffixes in ascending multiplier order
|
||||||
ranges = [k for k, v in sorted(multiplier.items(), key=lambda t: t[1])]
|
ranges = [k for k, v in sorted(multiplier.items(), key=lambda t: t[1])]
|
||||||
raise argparse.ArgumentTypeError(
|
raise argparse.ArgumentTypeError(
|
||||||
'Unexpected interval time unit "%s": expected one of %r' % (s[-1], ranges))
|
f'Unexpected interval time unit "{s[-1]}": expected one of {ranges!r}')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hours = int(number) * multiplier[suffix]
|
hours = int(number) * multiplier[suffix]
|
||||||
@ -117,7 +117,7 @@ def ChunkerParams(s):
|
|||||||
return CHUNKER_PARAMS
|
return CHUNKER_PARAMS
|
||||||
# this must stay last as it deals with old-style compat mode (no algorithm, 4 params, buzhash):
|
# this must stay last as it deals with old-style compat mode (no algorithm, 4 params, buzhash):
|
||||||
if algo == CH_BUZHASH and count == 5 or count == 4: # [buzhash, ]chunk_min, chunk_max, chunk_mask, window_size
|
if algo == CH_BUZHASH and count == 5 or count == 4: # [buzhash, ]chunk_min, chunk_max, chunk_mask, window_size
|
||||||
chunk_min, chunk_max, chunk_mask, window_size = [int(p) for p in params[count - 4:]]
|
chunk_min, chunk_max, chunk_mask, window_size = (int(p) for p in params[count - 4:])
|
||||||
if not (chunk_min <= chunk_mask <= chunk_max):
|
if not (chunk_min <= chunk_mask <= chunk_max):
|
||||||
raise ValueError('required: chunk_min <= chunk_mask <= chunk_max')
|
raise ValueError('required: chunk_min <= chunk_mask <= chunk_max')
|
||||||
if chunk_min < 6:
|
if chunk_min < 6:
|
||||||
@ -150,7 +150,7 @@ def partial_format(format, mapping):
|
|||||||
"""
|
"""
|
||||||
for key, value in mapping.items():
|
for key, value in mapping.items():
|
||||||
key = re.escape(key)
|
key = re.escape(key)
|
||||||
format = re.sub(r'(?<!\{)((\{%s\})|(\{%s:[^\}]*\}))' % (key, key),
|
format = re.sub(fr'(?<!\{{)((\{{{key}\}})|(\{{{key}:[^\}}]*\}}))',
|
||||||
lambda match: match.group(1).format_map(mapping),
|
lambda match: match.group(1).format_map(mapping),
|
||||||
format)
|
format)
|
||||||
return format
|
return format
|
||||||
@ -397,7 +397,7 @@ def parse(self, text, overrides={}):
|
|||||||
valid = self._parse(repo)
|
valid = self._parse(repo)
|
||||||
self.archive = m.group('archive')
|
self.archive = m.group('archive')
|
||||||
self.raw = repo_raw if not self.archive else repo_raw + self.raw
|
self.raw = repo_raw if not self.archive else repo_raw + self.raw
|
||||||
self.processed = repo if not self.archive else '%s::%s' % (repo, self.archive)
|
self.processed = repo if not self.archive else f'{repo}::{self.archive}'
|
||||||
return valid
|
return valid
|
||||||
|
|
||||||
def _parse(self, text):
|
def _parse(self, text):
|
||||||
@ -484,9 +484,9 @@ def canonical_path(self):
|
|||||||
path = '/./' + self.path # /./x = path x relative to cwd
|
path = '/./' + self.path # /./x = path x relative to cwd
|
||||||
else:
|
else:
|
||||||
path = self.path
|
path = self.path
|
||||||
return 'ssh://{}{}{}{}'.format('{}@'.format(self.user) if self.user else '',
|
return 'ssh://{}{}{}{}'.format(f'{self.user}@' if self.user else '',
|
||||||
self._host, # needed for ipv6 addrs
|
self._host, # needed for ipv6 addrs
|
||||||
':{}'.format(self.port) if self.port else '',
|
f':{self.port}' if self.port else '',
|
||||||
path)
|
path)
|
||||||
|
|
||||||
def with_timestamp(self, timestamp):
|
def with_timestamp(self, timestamp):
|
||||||
@ -947,7 +947,7 @@ def ellipsis_truncate(msg, space):
|
|||||||
# if there is very little space, just show ...
|
# if there is very little space, just show ...
|
||||||
return '...' + ' ' * (space - ellipsis_width)
|
return '...' + ' ' * (space - ellipsis_width)
|
||||||
if space < ellipsis_width + msg_width:
|
if space < ellipsis_width + msg_width:
|
||||||
return '%s...%s' % (swidth_slice(msg, space // 2 - ellipsis_width),
|
return '{}...{}'.format(swidth_slice(msg, space // 2 - ellipsis_width),
|
||||||
swidth_slice(msg, -space // 2))
|
swidth_slice(msg, -space // 2))
|
||||||
return msg + ' ' * (space - msg_width)
|
return msg + ' ' * (space - msg_width)
|
||||||
|
|
||||||
|
@ -320,7 +320,7 @@ def create_filter_process(cmd, stream, stream_close, inbound=True):
|
|||||||
proc = popen_with_error_handling(cmd, stdin=subprocess.PIPE, stdout=filter_stream,
|
proc = popen_with_error_handling(cmd, stdin=subprocess.PIPE, stdout=filter_stream,
|
||||||
log_prefix='filter-process: ', env=env)
|
log_prefix='filter-process: ', env=env)
|
||||||
if not proc:
|
if not proc:
|
||||||
raise Error('filter %s: process creation failed' % (cmd, ))
|
raise Error(f'filter {cmd}: process creation failed')
|
||||||
stream = proc.stdout if inbound else proc.stdin
|
stream = proc.stdout if inbound else proc.stdin
|
||||||
# inbound: do not close the pipe (this is the task of the filter process [== writer])
|
# inbound: do not close the pipe (this is the task of the filter process [== writer])
|
||||||
# outbound: close the pipe, otherwise the filter process would not notice when we are done.
|
# outbound: close the pipe, otherwise the filter process would not notice when we are done.
|
||||||
|
@ -131,7 +131,7 @@ def __format__(self, format_spec):
|
|||||||
return format_time(self.ts, format_spec=format_spec)
|
return format_time(self.ts, format_spec=format_spec)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}'.format(self)
|
return f'{self}'
|
||||||
|
|
||||||
def isoformat(self):
|
def isoformat(self):
|
||||||
return isoformat_time(self.ts)
|
return isoformat_time(self.ts)
|
||||||
|
@ -42,7 +42,7 @@ def __init__(self, timeout=None, sleep=None):
|
|||||||
self.end_time = None
|
self.end_time = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s: start=%r end=%r timeout=%r sleep=%r>" % (
|
return "<{}: start={!r} end={!r} timeout={!r} sleep={!r}>".format(
|
||||||
self.__class__.__name__, self.start_time, self.end_time,
|
self.__class__.__name__, self.start_time, self.end_time,
|
||||||
self.timeout_interval, self.sleep_interval)
|
self.timeout_interval, self.sleep_interval)
|
||||||
|
|
||||||
@ -118,7 +118,7 @@ def __exit__(self, *exc):
|
|||||||
self.release()
|
self.release()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s: %r>" % (self.__class__.__name__, self.unique_name)
|
return f"<{self.__class__.__name__}: {self.unique_name!r}>"
|
||||||
|
|
||||||
def acquire(self, timeout=None, sleep=None):
|
def acquire(self, timeout=None, sleep=None):
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
@ -299,7 +299,7 @@ def remove(self):
|
|||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
roster = self.load()
|
roster = self.load()
|
||||||
return set(tuple(e) for e in roster.get(key, []))
|
return {tuple(e) for e in roster.get(key, [])}
|
||||||
|
|
||||||
def empty(self, *keys):
|
def empty(self, *keys):
|
||||||
return all(not self.get(key) for key in keys)
|
return all(not self.get(key) for key in keys)
|
||||||
@ -307,7 +307,7 @@ def empty(self, *keys):
|
|||||||
def modify(self, key, op):
|
def modify(self, key, op):
|
||||||
roster = self.load()
|
roster = self.load()
|
||||||
try:
|
try:
|
||||||
elements = set(tuple(e) for e in roster[key])
|
elements = {tuple(e) for e in roster[key]}
|
||||||
except KeyError:
|
except KeyError:
|
||||||
elements = set()
|
elements = set()
|
||||||
if op == ADD:
|
if op == ADD:
|
||||||
@ -374,7 +374,7 @@ def __exit__(self, *exc):
|
|||||||
self.release()
|
self.release()
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s: %r>" % (self.__class__.__name__, self.id)
|
return f"<{self.__class__.__name__}: {self.id!r}>"
|
||||||
|
|
||||||
def acquire(self, exclusive=None, remove=None, sleep=None):
|
def acquire(self, exclusive=None, remove=None, sleep=None):
|
||||||
if exclusive is None:
|
if exclusive is None:
|
||||||
|
@ -46,7 +46,7 @@
|
|||||||
|
|
||||||
def _log_warning(message, category, filename, lineno, file=None, line=None):
|
def _log_warning(message, category, filename, lineno, file=None, line=None):
|
||||||
# for warnings, we just want to use the logging system, not stderr or other files
|
# for warnings, we just want to use the logging system, not stderr or other files
|
||||||
msg = "{0}:{1}: {2}: {3}".format(filename, lineno, category.__name__, message)
|
msg = f"{filename}:{lineno}: {category.__name__}: {message}"
|
||||||
logger = create_logger(__name__)
|
logger = create_logger(__name__)
|
||||||
# Note: the warning will look like coming from here,
|
# Note: the warning will look like coming from here,
|
||||||
# but msg contains info about where it really comes from
|
# but msg contains info about where it really comes from
|
||||||
@ -82,7 +82,7 @@ def setup_logging(stream=None, conf_fname=None, env_var='BORG_LOGGING_CONF', lev
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
borg_logger = logging.getLogger('borg')
|
borg_logger = logging.getLogger('borg')
|
||||||
borg_logger.json = json
|
borg_logger.json = json
|
||||||
logger.debug('using logging configuration read from "{0}"'.format(conf_fname))
|
logger.debug(f'using logging configuration read from "{conf_fname}"')
|
||||||
warnings.showwarning = _log_warning
|
warnings.showwarning = _log_warning
|
||||||
return None
|
return None
|
||||||
except Exception as err: # XXX be more precise
|
except Exception as err: # XXX be more precise
|
||||||
@ -110,7 +110,7 @@ def setup_logging(stream=None, conf_fname=None, env_var='BORG_LOGGING_CONF', lev
|
|||||||
configured = True
|
configured = True
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
if err_msg:
|
if err_msg:
|
||||||
logger.warning('setup_logging for "{0}" failed with "{1}".'.format(conf_fname, err_msg))
|
logger.warning(f'setup_logging for "{conf_fname}" failed with "{err_msg}".')
|
||||||
logger.debug('using builtin fallback logging configuration')
|
logger.debug('using builtin fallback logging configuration')
|
||||||
warnings.showwarning = _log_warning
|
warnings.showwarning = _log_warning
|
||||||
return handler
|
return handler
|
||||||
|
@ -201,7 +201,7 @@ def match(self, path, normalize=True):
|
|||||||
return matches
|
return matches
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '%s(%s)' % (type(self), self.pattern)
|
return f'{type(self)}({self.pattern})'
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.pattern_orig
|
return self.pattern_orig
|
||||||
@ -315,7 +315,7 @@ def _match(self, path):
|
|||||||
ShellPattern,
|
ShellPattern,
|
||||||
}
|
}
|
||||||
|
|
||||||
_PATTERN_CLASS_BY_PREFIX = dict((i.PREFIX, i) for i in _PATTERN_CLASSES)
|
_PATTERN_CLASS_BY_PREFIX = {i.PREFIX: i for i in _PATTERN_CLASSES}
|
||||||
|
|
||||||
CmdTuple = namedtuple('CmdTuple', 'val cmd')
|
CmdTuple = namedtuple('CmdTuple', 'val cmd')
|
||||||
|
|
||||||
@ -339,7 +339,7 @@ def get_pattern_class(prefix):
|
|||||||
try:
|
try:
|
||||||
return _PATTERN_CLASS_BY_PREFIX[prefix]
|
return _PATTERN_CLASS_BY_PREFIX[prefix]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise ValueError("Unknown pattern style: {}".format(prefix)) from None
|
raise ValueError(f"Unknown pattern style: {prefix}") from None
|
||||||
|
|
||||||
|
|
||||||
def parse_pattern(pattern, fallback=FnmatchPattern, recurse_dir=True):
|
def parse_pattern(pattern, fallback=FnmatchPattern, recurse_dir=True):
|
||||||
@ -394,7 +394,7 @@ def parse_inclexcl_command(cmd_line_str, fallback=ShellPattern):
|
|||||||
try:
|
try:
|
||||||
val = get_pattern_class(remainder_str)
|
val = get_pattern_class(remainder_str)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise argparse.ArgumentTypeError("Invalid pattern style: {}".format(remainder_str))
|
raise argparse.ArgumentTypeError(f"Invalid pattern style: {remainder_str}")
|
||||||
else:
|
else:
|
||||||
# determine recurse_dir based on command type
|
# determine recurse_dir based on command type
|
||||||
recurse_dir = command_recurses_dir(cmd)
|
recurse_dir = command_recurses_dir(cmd)
|
||||||
|
@ -265,7 +265,7 @@ def getfqdn(name=''):
|
|||||||
name = socket.gethostname()
|
name = socket.gethostname()
|
||||||
try:
|
try:
|
||||||
addrs = socket.getaddrinfo(name, None, 0, socket.SOCK_DGRAM, 0, socket.AI_CANONNAME)
|
addrs = socket.getaddrinfo(name, None, 0, socket.SOCK_DGRAM, 0, socket.AI_CANONNAME)
|
||||||
except socket.error:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
for addr in addrs:
|
for addr in addrs:
|
||||||
@ -288,7 +288,7 @@ def getfqdn(name=''):
|
|||||||
# thus, we offer BORG_HOST_ID where a user can set an own, unique id for each of his hosts.
|
# thus, we offer BORG_HOST_ID where a user can set an own, unique id for each of his hosts.
|
||||||
hostid = os.environ.get('BORG_HOST_ID')
|
hostid = os.environ.get('BORG_HOST_ID')
|
||||||
if not hostid:
|
if not hostid:
|
||||||
hostid = '%s@%s' % (fqdn, uuid.getnode())
|
hostid = f'{fqdn}@{uuid.getnode()}'
|
||||||
|
|
||||||
|
|
||||||
def get_process_id():
|
def get_process_id():
|
||||||
|
@ -286,7 +286,7 @@ def serve(self):
|
|||||||
else:
|
else:
|
||||||
tb_log_level = logging.ERROR
|
tb_log_level = logging.ERROR
|
||||||
msg = '%s Exception in RPC call' % e.__class__.__name__
|
msg = '%s Exception in RPC call' % e.__class__.__name__
|
||||||
tb = '%s\n%s' % (traceback.format_exc(), sysinfo())
|
tb = f'{traceback.format_exc()}\n{sysinfo()}'
|
||||||
logging.error(msg)
|
logging.error(msg)
|
||||||
logging.log(tb_log_level, tb)
|
logging.log(tb_log_level, tb)
|
||||||
exc = 'Remote Exception (see remote log for the traceback)'
|
exc = 'Remote Exception (see remote log for the traceback)'
|
||||||
@ -470,7 +470,7 @@ def do_rpc(self, *args, **kwargs):
|
|||||||
if restriction.get('dontcare', False):
|
if restriction.get('dontcare', False):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
raise self.RPCServerOutdated("{0} {1}={2!s}".format(f.__name__, name, named[name]),
|
raise self.RPCServerOutdated(f"{f.__name__} {name}={named[name]!s}",
|
||||||
format_version(restriction['since']))
|
format_version(restriction['since']))
|
||||||
|
|
||||||
return self.call(f.__name__, named, **extra)
|
return self.call(f.__name__, named, **extra)
|
||||||
@ -622,7 +622,7 @@ def __del__(self):
|
|||||||
assert False, 'cleanup happened in Repository.__del__'
|
assert False, 'cleanup happened in Repository.__del__'
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s %s>' % (self.__class__.__name__, self.location.canonical_path())
|
return f'<{self.__class__.__name__} {self.location.canonical_path()}>'
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
@ -697,7 +697,7 @@ def ssh_cmd(self, location):
|
|||||||
if location.port:
|
if location.port:
|
||||||
args += ['-p', str(location.port)]
|
args += ['-p', str(location.port)]
|
||||||
if location.user:
|
if location.user:
|
||||||
args.append('%s@%s' % (location.user, location.host))
|
args.append(f'{location.user}@{location.host}')
|
||||||
else:
|
else:
|
||||||
args.append('%s' % location.host)
|
args.append('%s' % location.host)
|
||||||
return args
|
return args
|
||||||
@ -941,8 +941,7 @@ def get(self, id):
|
|||||||
return resp
|
return resp
|
||||||
|
|
||||||
def get_many(self, ids, is_preloaded=False):
|
def get_many(self, ids, is_preloaded=False):
|
||||||
for resp in self.call_many('get', [{'id': id} for id in ids], is_preloaded=is_preloaded):
|
yield from self.call_many('get', [{'id': id} for id in ids], is_preloaded=is_preloaded)
|
||||||
yield resp
|
|
||||||
|
|
||||||
@api(since=parse_version('1.0.0'))
|
@api(since=parse_version('1.0.0'))
|
||||||
def put(self, id, data, wait=True):
|
def put(self, id, data, wait=True):
|
||||||
|
@ -190,7 +190,7 @@ def __del__(self):
|
|||||||
assert False, "cleanup happened in Repository.__del__"
|
assert False, "cleanup happened in Repository.__del__"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return '<%s %s>' % (self.__class__.__name__, self.path)
|
return f'<{self.__class__.__name__} {self.path}>'
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
if self.do_create:
|
if self.do_create:
|
||||||
@ -347,7 +347,7 @@ def get_free_nonce(self):
|
|||||||
|
|
||||||
nonce_path = os.path.join(self.path, 'nonce')
|
nonce_path = os.path.join(self.path, 'nonce')
|
||||||
try:
|
try:
|
||||||
with open(nonce_path, 'r') as fd:
|
with open(nonce_path) as fd:
|
||||||
return int.from_bytes(unhexlify(fd.read()), byteorder='big')
|
return int.from_bytes(unhexlify(fd.read()), byteorder='big')
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
return None
|
return None
|
||||||
@ -716,7 +716,7 @@ def check_free_space(self):
|
|||||||
except OSError as os_error:
|
except OSError as os_error:
|
||||||
logger.warning('Failed to check free space before committing: ' + str(os_error))
|
logger.warning('Failed to check free space before committing: ' + str(os_error))
|
||||||
return
|
return
|
||||||
logger.debug('check_free_space: required bytes {}, free bytes {}'.format(required_free_space, free_space))
|
logger.debug(f'check_free_space: required bytes {required_free_space}, free bytes {free_space}')
|
||||||
if free_space < required_free_space:
|
if free_space < required_free_space:
|
||||||
if self.created:
|
if self.created:
|
||||||
logger.error('Not enough free space to initialize repository at this location.')
|
logger.error('Not enough free space to initialize repository at this location.')
|
||||||
@ -924,7 +924,7 @@ def _update_index(self, segment, objects, report=None):
|
|||||||
elif tag == TAG_COMMIT:
|
elif tag == TAG_COMMIT:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
msg = 'Unexpected tag {} in segment {}'.format(tag, segment)
|
msg = f'Unexpected tag {tag} in segment {segment}'
|
||||||
if report is None:
|
if report is None:
|
||||||
raise self.CheckNeeded(msg)
|
raise self.CheckNeeded(msg)
|
||||||
else:
|
else:
|
||||||
@ -1045,7 +1045,7 @@ def report_error(msg):
|
|||||||
# self.index, self.segments, self.compact now reflect the state of the segment files up to <transaction_id>
|
# self.index, self.segments, self.compact now reflect the state of the segment files up to <transaction_id>
|
||||||
# We might need to add a commit tag if no committed segment is found
|
# We might need to add a commit tag if no committed segment is found
|
||||||
if repair and segments_transaction_id is None:
|
if repair and segments_transaction_id is None:
|
||||||
report_error('Adding commit tag to segment {}'.format(transaction_id))
|
report_error(f'Adding commit tag to segment {transaction_id}')
|
||||||
self.io.segment = transaction_id + 1
|
self.io.segment = transaction_id + 1
|
||||||
self.io.write_commit()
|
self.io.write_commit()
|
||||||
if not partial:
|
if not partial:
|
||||||
@ -1484,7 +1484,7 @@ def iter_objects(self, segment, offset=0, include_data=False, read_data=True):
|
|||||||
# Repository.scan() calls us with segment > 0 when it continues an ongoing iteration
|
# Repository.scan() calls us with segment > 0 when it continues an ongoing iteration
|
||||||
# from a marker position - but then we have checked the magic before already.
|
# from a marker position - but then we have checked the magic before already.
|
||||||
if fd.read(MAGIC_LEN) != MAGIC:
|
if fd.read(MAGIC_LEN) != MAGIC:
|
||||||
raise IntegrityError('Invalid segment magic [segment {}, offset {}]'.format(segment, 0))
|
raise IntegrityError(f'Invalid segment magic [segment {segment}, offset {0}]')
|
||||||
offset = MAGIC_LEN
|
offset = MAGIC_LEN
|
||||||
header = fd.read(self.header_fmt.size)
|
header = fd.read(self.header_fmt.size)
|
||||||
while header:
|
while header:
|
||||||
@ -1613,7 +1613,7 @@ def write_put(self, id, data, raise_full=False):
|
|||||||
data_size = len(data)
|
data_size = len(data)
|
||||||
if data_size > MAX_DATA_SIZE:
|
if data_size > MAX_DATA_SIZE:
|
||||||
# this would push the segment entry size beyond MAX_OBJECT_SIZE.
|
# this would push the segment entry size beyond MAX_OBJECT_SIZE.
|
||||||
raise IntegrityError('More than allowed put data [{} > {}]'.format(data_size, MAX_DATA_SIZE))
|
raise IntegrityError(f'More than allowed put data [{data_size} > {MAX_DATA_SIZE}]')
|
||||||
fd = self.get_write_fd(want_new=(id == Manifest.MANIFEST_ID), raise_full=raise_full)
|
fd = self.get_write_fd(want_new=(id == Manifest.MANIFEST_ID), raise_full=raise_full)
|
||||||
size = data_size + self.put_header_fmt.size
|
size = data_size + self.put_header_fmt.size
|
||||||
offset = self.offset
|
offset = self.offset
|
||||||
|
@ -33,7 +33,7 @@ def translate(pat, match_end=r"\Z"):
|
|||||||
if i + 1 < n and pat[i] == "*" and pat[i + 1] == sep:
|
if i + 1 < n and pat[i] == "*" and pat[i + 1] == sep:
|
||||||
# **/ == wildcard for 0+ full (relative) directory names with trailing slashes; the forward slash stands
|
# **/ == wildcard for 0+ full (relative) directory names with trailing slashes; the forward slash stands
|
||||||
# for the platform-specific path separator
|
# for the platform-specific path separator
|
||||||
res += r"(?:[^\%s]*\%s)*" % (sep, sep)
|
res += fr"(?:[^\{sep}]*\{sep})*"
|
||||||
i += 2
|
i += 2
|
||||||
else:
|
else:
|
||||||
# * == wildcard for name parts (does not cross path separator)
|
# * == wildcard for name parts (does not cross path separator)
|
||||||
|
@ -58,7 +58,7 @@ def unopened_tempfile():
|
|||||||
yield os.path.join(tempdir, "file")
|
yield os.path.join(tempdir, "file")
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache
|
||||||
def are_symlinks_supported():
|
def are_symlinks_supported():
|
||||||
with unopened_tempfile() as filepath:
|
with unopened_tempfile() as filepath:
|
||||||
try:
|
try:
|
||||||
@ -70,7 +70,7 @@ def are_symlinks_supported():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache
|
||||||
def are_hardlinks_supported():
|
def are_hardlinks_supported():
|
||||||
if not hasattr(os, 'link'):
|
if not hasattr(os, 'link'):
|
||||||
# some pythons do not have os.link
|
# some pythons do not have os.link
|
||||||
@ -89,7 +89,7 @@ def are_hardlinks_supported():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache
|
||||||
def are_fifos_supported():
|
def are_fifos_supported():
|
||||||
with unopened_tempfile() as filepath:
|
with unopened_tempfile() as filepath:
|
||||||
try:
|
try:
|
||||||
@ -104,7 +104,7 @@ def are_fifos_supported():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache
|
||||||
def is_utime_fully_supported():
|
def is_utime_fully_supported():
|
||||||
with unopened_tempfile() as filepath:
|
with unopened_tempfile() as filepath:
|
||||||
# Some filesystems (such as SSHFS) don't support utime on symlinks
|
# Some filesystems (such as SSHFS) don't support utime on symlinks
|
||||||
@ -124,7 +124,7 @@ def is_utime_fully_supported():
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache
|
||||||
def is_birthtime_fully_supported():
|
def is_birthtime_fully_supported():
|
||||||
if not hasattr(os.stat_result, 'st_birthtime'):
|
if not hasattr(os.stat_result, 'st_birthtime'):
|
||||||
return False
|
return False
|
||||||
@ -172,9 +172,9 @@ class BaseTestCase(unittest.TestCase):
|
|||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def assert_creates_file(self, path):
|
def assert_creates_file(self, path):
|
||||||
assert not os.path.exists(path), '{} should not exist'.format(path)
|
assert not os.path.exists(path), f'{path} should not exist'
|
||||||
yield
|
yield
|
||||||
assert os.path.exists(path), '{} should exist'.format(path)
|
assert os.path.exists(path), f'{path} should exist'
|
||||||
|
|
||||||
def assert_dirs_equal(self, dir1, dir2, **kwargs):
|
def assert_dirs_equal(self, dir1, dir2, **kwargs):
|
||||||
diff = filecmp.dircmp(dir1, dir2)
|
diff = filecmp.dircmp(dir1, dir2)
|
||||||
@ -293,7 +293,7 @@ def wait_for_mountstate(self, mountpoint, *, mounted, timeout=5):
|
|||||||
if os.path.ismount(mountpoint) == mounted:
|
if os.path.ismount(mountpoint) == mounted:
|
||||||
return
|
return
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
message = 'Waiting for %s of %s' % ('mount' if mounted else 'umount', mountpoint)
|
message = 'Waiting for {} of {}'.format('mount' if mounted else 'umount', mountpoint)
|
||||||
raise TimeoutError(message)
|
raise TimeoutError(message)
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
|
@ -55,10 +55,10 @@ def tests_stats_progress(stats, monkeypatch, columns=80):
|
|||||||
def test_stats_format(stats):
|
def test_stats_format(stats):
|
||||||
assert str(stats) == """\
|
assert str(stats) == """\
|
||||||
This archive: 20 B 10 B 10 B"""
|
This archive: 20 B 10 B 10 B"""
|
||||||
s = "{0.osize_fmt}".format(stats)
|
s = f"{stats.osize_fmt}"
|
||||||
assert s == "20 B"
|
assert s == "20 B"
|
||||||
# kind of redundant, but id is variable so we can't match reliably
|
# kind of redundant, but id is variable so we can't match reliably
|
||||||
assert repr(stats) == '<Statistics object at {:#x} (20, 10, 10)>'.format(id(stats))
|
assert repr(stats) == f'<Statistics object at {id(stats):#x} (20, 10, 10)>'
|
||||||
|
|
||||||
|
|
||||||
class MockCache:
|
class MockCache:
|
||||||
|
@ -1867,7 +1867,7 @@ def test_unknown_mandatory_feature_in_cache(self):
|
|||||||
manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
|
manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
|
||||||
with Cache(repository, key, manifest) as cache:
|
with Cache(repository, key, manifest) as cache:
|
||||||
cache.begin_txn()
|
cache.begin_txn()
|
||||||
cache.cache_config.mandatory_features = set(['unknown-feature'])
|
cache.cache_config.mandatory_features = {'unknown-feature'}
|
||||||
cache.commit()
|
cache.commit()
|
||||||
|
|
||||||
if self.FORK_DEFAULT:
|
if self.FORK_DEFAULT:
|
||||||
@ -1891,7 +1891,7 @@ def wipe_wrapper(*args):
|
|||||||
repository._location = Location(self.repository_location)
|
repository._location = Location(self.repository_location)
|
||||||
manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
|
manifest, key = Manifest.load(repository, Manifest.NO_OPERATION_CHECK)
|
||||||
with Cache(repository, key, manifest) as cache:
|
with Cache(repository, key, manifest) as cache:
|
||||||
assert cache.cache_config.mandatory_features == set([])
|
assert cache.cache_config.mandatory_features == set()
|
||||||
|
|
||||||
def test_progress_on(self):
|
def test_progress_on(self):
|
||||||
self.create_regular_file('file1', size=1024 * 80)
|
self.create_regular_file('file1', size=1024 * 80)
|
||||||
@ -2748,7 +2748,7 @@ def wrapper(self, old_id, new_id):
|
|||||||
pass
|
pass
|
||||||
with open(assert_data_file, 'rb') as _in:
|
with open(assert_data_file, 'rb') as _in:
|
||||||
assert_data = pickle.load(_in)
|
assert_data = pickle.load(_in)
|
||||||
print('\nLock.migrate_lock(): assert_data = %r.' % (assert_data, ), file=sys.stderr, flush=True)
|
print(f'\nLock.migrate_lock(): assert_data = {assert_data!r}.', file=sys.stderr, flush=True)
|
||||||
exception = assert_data['exception']
|
exception = assert_data['exception']
|
||||||
if exception is not None:
|
if exception is not None:
|
||||||
extracted_tb = assert_data['exception.extr_tb']
|
extracted_tb = assert_data['exception.extr_tb']
|
||||||
@ -3089,14 +3089,14 @@ def test_key_export_keyfile(self):
|
|||||||
repo_id = self._extract_repository_id(self.repository_path)
|
repo_id = self._extract_repository_id(self.repository_path)
|
||||||
self.cmd('key', 'export', self.repository_location, export_file)
|
self.cmd('key', 'export', self.repository_location, export_file)
|
||||||
|
|
||||||
with open(export_file, 'r') as fd:
|
with open(export_file) as fd:
|
||||||
export_contents = fd.read()
|
export_contents = fd.read()
|
||||||
|
|
||||||
assert export_contents.startswith('BORG_KEY ' + bin_to_hex(repo_id) + '\n')
|
assert export_contents.startswith('BORG_KEY ' + bin_to_hex(repo_id) + '\n')
|
||||||
|
|
||||||
key_file = self.keys_path + '/' + os.listdir(self.keys_path)[0]
|
key_file = self.keys_path + '/' + os.listdir(self.keys_path)[0]
|
||||||
|
|
||||||
with open(key_file, 'r') as fd:
|
with open(key_file) as fd:
|
||||||
key_contents = fd.read()
|
key_contents = fd.read()
|
||||||
|
|
||||||
assert key_contents == export_contents
|
assert key_contents == export_contents
|
||||||
@ -3105,7 +3105,7 @@ def test_key_export_keyfile(self):
|
|||||||
|
|
||||||
self.cmd('key', 'import', self.repository_location, export_file)
|
self.cmd('key', 'import', self.repository_location, export_file)
|
||||||
|
|
||||||
with open(key_file, 'r') as fd:
|
with open(key_file) as fd:
|
||||||
key_contents2 = fd.read()
|
key_contents2 = fd.read()
|
||||||
|
|
||||||
assert key_contents2 == key_contents
|
assert key_contents2 == key_contents
|
||||||
@ -3117,7 +3117,7 @@ def test_key_import_keyfile_with_borg_key_file(self):
|
|||||||
self.cmd('key', 'export', self.repository_location, exported_key_file)
|
self.cmd('key', 'export', self.repository_location, exported_key_file)
|
||||||
|
|
||||||
key_file = os.path.join(self.keys_path, os.listdir(self.keys_path)[0])
|
key_file = os.path.join(self.keys_path, os.listdir(self.keys_path)[0])
|
||||||
with open(key_file, 'r') as fd:
|
with open(key_file) as fd:
|
||||||
key_contents = fd.read()
|
key_contents = fd.read()
|
||||||
os.unlink(key_file)
|
os.unlink(key_file)
|
||||||
|
|
||||||
@ -3126,7 +3126,7 @@ def test_key_import_keyfile_with_borg_key_file(self):
|
|||||||
self.cmd('key', 'import', self.repository_location, exported_key_file)
|
self.cmd('key', 'import', self.repository_location, exported_key_file)
|
||||||
assert not os.path.isfile(key_file), '"borg key import" should respect BORG_KEY_FILE'
|
assert not os.path.isfile(key_file), '"borg key import" should respect BORG_KEY_FILE'
|
||||||
|
|
||||||
with open(imported_key_file, 'r') as fd:
|
with open(imported_key_file) as fd:
|
||||||
imported_key_contents = fd.read()
|
imported_key_contents = fd.read()
|
||||||
assert imported_key_contents == key_contents
|
assert imported_key_contents == key_contents
|
||||||
|
|
||||||
@ -3136,7 +3136,7 @@ def test_key_export_repokey(self):
|
|||||||
repo_id = self._extract_repository_id(self.repository_path)
|
repo_id = self._extract_repository_id(self.repository_path)
|
||||||
self.cmd('key', 'export', self.repository_location, export_file)
|
self.cmd('key', 'export', self.repository_location, export_file)
|
||||||
|
|
||||||
with open(export_file, 'r') as fd:
|
with open(export_file) as fd:
|
||||||
export_contents = fd.read()
|
export_contents = fd.read()
|
||||||
|
|
||||||
assert export_contents.startswith('BORG_KEY ' + bin_to_hex(repo_id) + '\n')
|
assert export_contents.startswith('BORG_KEY ' + bin_to_hex(repo_id) + '\n')
|
||||||
@ -3167,7 +3167,7 @@ def test_key_export_qr(self):
|
|||||||
repo_id = self._extract_repository_id(self.repository_path)
|
repo_id = self._extract_repository_id(self.repository_path)
|
||||||
self.cmd('key', 'export', '--qr-html', self.repository_location, export_file)
|
self.cmd('key', 'export', '--qr-html', self.repository_location, export_file)
|
||||||
|
|
||||||
with open(export_file, 'r', encoding='utf-8') as fd:
|
with open(export_file, encoding='utf-8') as fd:
|
||||||
export_contents = fd.read()
|
export_contents = fd.read()
|
||||||
|
|
||||||
assert bin_to_hex(repo_id) in export_contents
|
assert bin_to_hex(repo_id) in export_contents
|
||||||
@ -3221,7 +3221,7 @@ def test_key_export_paperkey(self):
|
|||||||
|
|
||||||
self.cmd('key', 'export', '--paper', self.repository_location, export_file)
|
self.cmd('key', 'export', '--paper', self.repository_location, export_file)
|
||||||
|
|
||||||
with open(export_file, 'r') as fd:
|
with open(export_file) as fd:
|
||||||
export_contents = fd.read()
|
export_contents = fd.read()
|
||||||
|
|
||||||
assert export_contents == """To restore key use borg key import --paper /path/to/repo
|
assert export_contents == """To restore key use borg key import --paper /path/to/repo
|
||||||
@ -3284,7 +3284,7 @@ def test_debug_dump_manifest(self):
|
|||||||
dump_file = self.output_path + '/dump'
|
dump_file = self.output_path + '/dump'
|
||||||
output = self.cmd('debug', 'dump-manifest', self.repository_location, dump_file)
|
output = self.cmd('debug', 'dump-manifest', self.repository_location, dump_file)
|
||||||
assert output == ""
|
assert output == ""
|
||||||
with open(dump_file, "r") as f:
|
with open(dump_file) as f:
|
||||||
result = json.load(f)
|
result = json.load(f)
|
||||||
assert 'archives' in result
|
assert 'archives' in result
|
||||||
assert 'config' in result
|
assert 'config' in result
|
||||||
@ -3299,7 +3299,7 @@ def test_debug_dump_archive(self):
|
|||||||
dump_file = self.output_path + '/dump'
|
dump_file = self.output_path + '/dump'
|
||||||
output = self.cmd('debug', 'dump-archive', self.repository_location + "::test", dump_file)
|
output = self.cmd('debug', 'dump-archive', self.repository_location + "::test", dump_file)
|
||||||
assert output == ""
|
assert output == ""
|
||||||
with open(dump_file, "r") as f:
|
with open(dump_file) as f:
|
||||||
result = json.load(f)
|
result = json.load(f)
|
||||||
assert '_name' in result
|
assert '_name' in result
|
||||||
assert '_manifest_entry' in result
|
assert '_manifest_entry' in result
|
||||||
@ -4144,7 +4144,7 @@ def do_asserts(output, can_compare_ids):
|
|||||||
# File contents changed (deleted and replaced with a new file)
|
# File contents changed (deleted and replaced with a new file)
|
||||||
change = 'B' if can_compare_ids else '{:<19}'.format('modified')
|
change = 'B' if can_compare_ids else '{:<19}'.format('modified')
|
||||||
assert 'file_replaced' in output # added to debug #3494
|
assert 'file_replaced' in output # added to debug #3494
|
||||||
assert '{} input/file_replaced'.format(change) in output
|
assert f'{change} input/file_replaced' in output
|
||||||
|
|
||||||
# File unchanged
|
# File unchanged
|
||||||
assert 'input/file_unchanged' not in output
|
assert 'input/file_unchanged' not in output
|
||||||
@ -4174,9 +4174,9 @@ def do_asserts(output, can_compare_ids):
|
|||||||
# should notice the changes in both links. However, the symlink
|
# should notice the changes in both links. However, the symlink
|
||||||
# pointing to the file is not changed.
|
# pointing to the file is not changed.
|
||||||
change = '0 B' if can_compare_ids else '{:<19}'.format('modified')
|
change = '0 B' if can_compare_ids else '{:<19}'.format('modified')
|
||||||
assert '{} input/empty'.format(change) in output
|
assert f'{change} input/empty' in output
|
||||||
if are_hardlinks_supported():
|
if are_hardlinks_supported():
|
||||||
assert '{} input/hardlink_contents_changed'.format(change) in output
|
assert f'{change} input/hardlink_contents_changed' in output
|
||||||
if are_symlinks_supported():
|
if are_symlinks_supported():
|
||||||
assert 'input/link_target_contents_changed' not in output
|
assert 'input/link_target_contents_changed' not in output
|
||||||
|
|
||||||
|
@ -147,7 +147,7 @@ def test_obfuscate():
|
|||||||
# 2 id bytes compression, 2 id bytes obfuscator. 4 length bytes
|
# 2 id bytes compression, 2 id bytes obfuscator. 4 length bytes
|
||||||
assert len(data) + 8 <= len(compressed) <= len(data) * 101 + 8
|
assert len(data) + 8 <= len(compressed) <= len(data) * 101 + 8
|
||||||
# compressing 100 times the same data should give at least 50 different result sizes
|
# compressing 100 times the same data should give at least 50 different result sizes
|
||||||
assert len(set(len(compressor.compress(data)) for i in range(100))) > 50
|
assert len({len(compressor.compress(data)) for i in range(100)}) > 50
|
||||||
|
|
||||||
cs = CompressionSpec('obfuscate,2,lz4')
|
cs = CompressionSpec('obfuscate,2,lz4')
|
||||||
assert isinstance(cs.inner.compressor, LZ4)
|
assert isinstance(cs.inner.compressor, LZ4)
|
||||||
@ -158,7 +158,7 @@ def test_obfuscate():
|
|||||||
min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries
|
min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries
|
||||||
assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 1001 + 8
|
assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 1001 + 8
|
||||||
# compressing 100 times the same data should give multiple different result sizes
|
# compressing 100 times the same data should give multiple different result sizes
|
||||||
assert len(set(len(compressor.compress(data)) for i in range(100))) > 10
|
assert len({len(compressor.compress(data)) for i in range(100)}) > 10
|
||||||
|
|
||||||
cs = CompressionSpec('obfuscate,6,zstd,3')
|
cs = CompressionSpec('obfuscate,6,zstd,3')
|
||||||
assert isinstance(cs.inner.compressor, ZSTD)
|
assert isinstance(cs.inner.compressor, ZSTD)
|
||||||
@ -169,7 +169,7 @@ def test_obfuscate():
|
|||||||
min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries
|
min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries
|
||||||
assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 10000001 + 8
|
assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 10000001 + 8
|
||||||
# compressing 100 times the same data should give multiple different result sizes
|
# compressing 100 times the same data should give multiple different result sizes
|
||||||
assert len(set(len(compressor.compress(data)) for i in range(100))) > 90
|
assert len({len(compressor.compress(data)) for i in range(100)}) > 90
|
||||||
|
|
||||||
cs = CompressionSpec('obfuscate,2,auto,zstd,10')
|
cs = CompressionSpec('obfuscate,2,auto,zstd,10')
|
||||||
assert isinstance(cs.inner.compressor, Auto)
|
assert isinstance(cs.inner.compressor, Auto)
|
||||||
@ -180,7 +180,7 @@ def test_obfuscate():
|
|||||||
min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries
|
min_compress, max_compress = 0.2, 0.001 # estimate compression factor outer boundaries
|
||||||
assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 1001 + 8
|
assert max_compress * len(data) + 8 <= len(compressed) <= min_compress * len(data) * 1001 + 8
|
||||||
# compressing 100 times the same data should give multiple different result sizes
|
# compressing 100 times the same data should give multiple different result sizes
|
||||||
assert len(set(len(compressor.compress(data)) for i in range(100))) > 10
|
assert len({len(compressor.compress(data)) for i in range(100)}) > 10
|
||||||
|
|
||||||
cs = CompressionSpec('obfuscate,110,none')
|
cs = CompressionSpec('obfuscate,110,none')
|
||||||
assert isinstance(cs.inner.compressor, CNONE)
|
assert isinstance(cs.inner.compressor, CNONE)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ..crypto.file_integrity import IntegrityCheckedFile, DetachedIntegrityCheckedFile, FileIntegrityError
|
from ..crypto.file_integrity import IntegrityCheckedFile, DetachedIntegrityCheckedFile, FileIntegrityError
|
||||||
|
@ -225,7 +225,7 @@ def test_format_path(self, monkeypatch):
|
|||||||
monkeypatch.delenv('BORG_REPO', raising=False)
|
monkeypatch.delenv('BORG_REPO', raising=False)
|
||||||
test_pid = os.getpid()
|
test_pid = os.getpid()
|
||||||
assert repr(Location('/some/path::archive{pid}')) == \
|
assert repr(Location('/some/path::archive{pid}')) == \
|
||||||
"Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive{}')".format(test_pid)
|
f"Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive{test_pid}')"
|
||||||
location_time1 = Location('/some/path::archive{now:%s}')
|
location_time1 = Location('/some/path::archive{now:%s}')
|
||||||
sleep(1.1)
|
sleep(1.1)
|
||||||
location_time2 = Location('/some/path::archive{now:%s}')
|
location_time2 = Location('/some/path::archive{now:%s}')
|
||||||
@ -259,11 +259,11 @@ def test_ssh_placeholder(self, monkeypatch):
|
|||||||
from borg.platform import hostname
|
from borg.platform import hostname
|
||||||
monkeypatch.setenv('BORG_REPO', 'ssh://user@host:1234/{hostname}')
|
monkeypatch.setenv('BORG_REPO', 'ssh://user@host:1234/{hostname}')
|
||||||
assert repr(Location('::archive')) == \
|
assert repr(Location('::archive')) == \
|
||||||
"Location(proto='ssh', user='user', host='host', port=1234, path='/{}', archive='archive')".format(hostname)
|
f"Location(proto='ssh', user='user', host='host', port=1234, path='/{hostname}', archive='archive')"
|
||||||
assert repr(Location('::')) == \
|
assert repr(Location('::')) == \
|
||||||
"Location(proto='ssh', user='user', host='host', port=1234, path='/{}', archive=None)".format(hostname)
|
f"Location(proto='ssh', user='user', host='host', port=1234, path='/{hostname}', archive=None)"
|
||||||
assert repr(Location()) == \
|
assert repr(Location()) == \
|
||||||
"Location(proto='ssh', user='user', host='host', port=1234, path='/{}', archive=None)".format(hostname)
|
f"Location(proto='ssh', user='user', host='host', port=1234, path='/{hostname}', archive=None)"
|
||||||
|
|
||||||
def test_file(self, monkeypatch):
|
def test_file(self, monkeypatch):
|
||||||
monkeypatch.setenv('BORG_REPO', 'file:///some/path')
|
monkeypatch.setenv('BORG_REPO', 'file:///some/path')
|
||||||
@ -380,7 +380,7 @@ def __init__(self, ts, id):
|
|||||||
self.id = id
|
self.id = id
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "{0}: {1}".format(self.id, self.ts.isoformat())
|
return f"{self.id}: {self.ts.isoformat()}"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
|
@ -14,7 +14,7 @@ def test_lrucache(self):
|
|||||||
for i, x in enumerate('abc'):
|
for i, x in enumerate('abc'):
|
||||||
c[x] = i
|
c[x] = i
|
||||||
assert len(c) == 2
|
assert len(c) == 2
|
||||||
assert c.items() == set([('b', 1), ('c', 2)])
|
assert c.items() == {('b', 1), ('c', 2)}
|
||||||
assert 'a' not in c
|
assert 'a' not in c
|
||||||
assert 'b' in c
|
assert 'b' in c
|
||||||
with pytest.raises(KeyError):
|
with pytest.raises(KeyError):
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ..nanorst import rst_to_text
|
from ..nanorst import rst_to_text
|
||||||
|
@ -37,7 +37,7 @@ def setUp(self):
|
|||||||
self.repository = None
|
self.repository = None
|
||||||
|
|
||||||
def cache_nonce(self):
|
def cache_nonce(self):
|
||||||
with open(os.path.join(get_security_dir(self.repository.id_str), 'nonce'), "r") as fd:
|
with open(os.path.join(get_security_dir(self.repository.id_str), 'nonce')) as fd:
|
||||||
return fd.read()
|
return fd.read()
|
||||||
|
|
||||||
def set_cache_nonce(self, nonce):
|
def set_cache_nonce(self, nonce):
|
||||||
|
@ -204,7 +204,7 @@ def use_normalized_unicode():
|
|||||||
def _make_test_patterns(pattern):
|
def _make_test_patterns(pattern):
|
||||||
return [PathPrefixPattern(pattern),
|
return [PathPrefixPattern(pattern),
|
||||||
FnmatchPattern(pattern),
|
FnmatchPattern(pattern),
|
||||||
RegexPattern("^{}/foo$".format(pattern)),
|
RegexPattern(f"^{pattern}/foo$"),
|
||||||
ShellPattern(pattern),
|
ShellPattern(pattern),
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -275,7 +275,7 @@ def test_exclude_patterns_from_file(tmpdir, lines, expected):
|
|||||||
|
|
||||||
def evaluate(filename):
|
def evaluate(filename):
|
||||||
patterns = []
|
patterns = []
|
||||||
load_exclude_file(open(filename, "rt"), patterns)
|
load_exclude_file(open(filename), patterns)
|
||||||
matcher = PatternMatcher(fallback=True)
|
matcher = PatternMatcher(fallback=True)
|
||||||
matcher.add_inclexcl(patterns)
|
matcher.add_inclexcl(patterns)
|
||||||
return [path for path in files if matcher.match(path)]
|
return [path for path in files if matcher.match(path)]
|
||||||
@ -306,7 +306,7 @@ def test_load_patterns_from_file(tmpdir, lines, expected_roots, expected_numpatt
|
|||||||
def evaluate(filename):
|
def evaluate(filename):
|
||||||
roots = []
|
roots = []
|
||||||
inclexclpatterns = []
|
inclexclpatterns = []
|
||||||
load_pattern_file(open(filename, "rt"), roots, inclexclpatterns)
|
load_pattern_file(open(filename), roots, inclexclpatterns)
|
||||||
return roots, len(inclexclpatterns)
|
return roots, len(inclexclpatterns)
|
||||||
patternfile = tmpdir.join("patterns.txt")
|
patternfile = tmpdir.join("patterns.txt")
|
||||||
|
|
||||||
@ -356,7 +356,7 @@ def test_load_invalid_patterns_from_file(tmpdir, lines):
|
|||||||
with pytest.raises(argparse.ArgumentTypeError):
|
with pytest.raises(argparse.ArgumentTypeError):
|
||||||
roots = []
|
roots = []
|
||||||
inclexclpatterns = []
|
inclexclpatterns = []
|
||||||
load_pattern_file(open(filename, "rt"), roots, inclexclpatterns)
|
load_pattern_file(open(filename), roots, inclexclpatterns)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("lines, expected", [
|
@pytest.mark.parametrize("lines, expected", [
|
||||||
@ -400,7 +400,7 @@ def evaluate(filename):
|
|||||||
matcher = PatternMatcher(fallback=True)
|
matcher = PatternMatcher(fallback=True)
|
||||||
roots = []
|
roots = []
|
||||||
inclexclpatterns = []
|
inclexclpatterns = []
|
||||||
load_pattern_file(open(filename, "rt"), roots, inclexclpatterns)
|
load_pattern_file(open(filename), roots, inclexclpatterns)
|
||||||
matcher.add_inclexcl(inclexclpatterns)
|
matcher.add_inclexcl(inclexclpatterns)
|
||||||
return [path for path in files if matcher.match(path)]
|
return [path for path in files if matcher.match(path)]
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ def user_exists(username):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@functools.lru_cache()
|
@functools.lru_cache
|
||||||
def are_acls_working():
|
def are_acls_working():
|
||||||
with unopened_tempfile() as filepath:
|
with unopened_tempfile() as filepath:
|
||||||
open(filepath, 'w').close()
|
open(filepath, 'w').close()
|
||||||
@ -118,12 +118,12 @@ def test_non_ascii_acl(self):
|
|||||||
# but in practice they seem to be out there and must not make our code explode.
|
# but in practice they seem to be out there and must not make our code explode.
|
||||||
file = tempfile.NamedTemporaryFile()
|
file = tempfile.NamedTemporaryFile()
|
||||||
self.assert_equal(self.get_acl(file.name), {})
|
self.assert_equal(self.get_acl(file.name), {})
|
||||||
nothing_special = 'user::rw-\ngroup::r--\nmask::rw-\nother::---\n'.encode('ascii')
|
nothing_special = b'user::rw-\ngroup::r--\nmask::rw-\nother::---\n'
|
||||||
# TODO: can this be tested without having an existing system user übel with uid 666 gid 666?
|
# TODO: can this be tested without having an existing system user übel with uid 666 gid 666?
|
||||||
user_entry = 'user:übel:rw-:666'.encode('utf-8')
|
user_entry = 'user:übel:rw-:666'.encode()
|
||||||
user_entry_numeric = 'user:666:rw-:666'.encode('ascii')
|
user_entry_numeric = b'user:666:rw-:666'
|
||||||
group_entry = 'group:übel:rw-:666'.encode('utf-8')
|
group_entry = 'group:übel:rw-:666'.encode()
|
||||||
group_entry_numeric = 'group:666:rw-:666'.encode('ascii')
|
group_entry_numeric = b'group:666:rw-:666'
|
||||||
acl = b'\n'.join([nothing_special, user_entry, group_entry])
|
acl = b'\n'.join([nothing_special, user_entry, group_entry])
|
||||||
self.set_acl(file.name, access=acl, numeric_ids=False)
|
self.set_acl(file.name, access=acl, numeric_ids=False)
|
||||||
acl_access = self.get_acl(file.name, numeric_ids=False)['acl_access']
|
acl_access = self.get_acl(file.name, numeric_ids=False)['acl_access']
|
||||||
|
@ -528,14 +528,14 @@ def test_commit_nonce_reservation(self):
|
|||||||
self.repository.commit_nonce_reservation(0x200, 15)
|
self.repository.commit_nonce_reservation(0x200, 15)
|
||||||
|
|
||||||
self.repository.commit_nonce_reservation(0x200, None)
|
self.repository.commit_nonce_reservation(0x200, None)
|
||||||
with open(os.path.join(self.repository.path, "nonce"), "r") as fd:
|
with open(os.path.join(self.repository.path, "nonce")) as fd:
|
||||||
assert fd.read() == "0000000000000200"
|
assert fd.read() == "0000000000000200"
|
||||||
|
|
||||||
with pytest.raises(Exception):
|
with pytest.raises(Exception):
|
||||||
self.repository.commit_nonce_reservation(0x200, 15)
|
self.repository.commit_nonce_reservation(0x200, 15)
|
||||||
|
|
||||||
self.repository.commit_nonce_reservation(0x400, 0x200)
|
self.repository.commit_nonce_reservation(0x400, 0x200)
|
||||||
with open(os.path.join(self.repository.path, "nonce"), "r") as fd:
|
with open(os.path.join(self.repository.path, "nonce")) as fd:
|
||||||
assert fd.read() == "0000000000000400"
|
assert fd.read() == "0000000000000400"
|
||||||
|
|
||||||
|
|
||||||
@ -710,7 +710,7 @@ def get_head(self):
|
|||||||
return sorted(int(n) for n in os.listdir(os.path.join(self.tmppath, 'repository', 'data', '0')) if n.isdigit())[-1]
|
return sorted(int(n) for n in os.listdir(os.path.join(self.tmppath, 'repository', 'data', '0')) if n.isdigit())[-1]
|
||||||
|
|
||||||
def open_index(self):
|
def open_index(self):
|
||||||
return NSIndex.read(os.path.join(self.tmppath, 'repository', 'index.{}'.format(self.get_head())))
|
return NSIndex.read(os.path.join(self.tmppath, 'repository', f'index.{self.get_head()}'))
|
||||||
|
|
||||||
def corrupt_object(self, id_):
|
def corrupt_object(self, id_):
|
||||||
idx = self.open_index()
|
idx = self.open_index()
|
||||||
@ -723,18 +723,18 @@ def delete_segment(self, segment):
|
|||||||
os.unlink(os.path.join(self.tmppath, 'repository', 'data', '0', str(segment)))
|
os.unlink(os.path.join(self.tmppath, 'repository', 'data', '0', str(segment)))
|
||||||
|
|
||||||
def delete_index(self):
|
def delete_index(self):
|
||||||
os.unlink(os.path.join(self.tmppath, 'repository', 'index.{}'.format(self.get_head())))
|
os.unlink(os.path.join(self.tmppath, 'repository', f'index.{self.get_head()}'))
|
||||||
|
|
||||||
def rename_index(self, new_name):
|
def rename_index(self, new_name):
|
||||||
os.rename(os.path.join(self.tmppath, 'repository', 'index.{}'.format(self.get_head())),
|
os.rename(os.path.join(self.tmppath, 'repository', f'index.{self.get_head()}'),
|
||||||
os.path.join(self.tmppath, 'repository', new_name))
|
os.path.join(self.tmppath, 'repository', new_name))
|
||||||
|
|
||||||
def list_objects(self):
|
def list_objects(self):
|
||||||
return set(int(key) for key in self.repository.list())
|
return {int(key) for key in self.repository.list()}
|
||||||
|
|
||||||
def test_repair_corrupted_segment(self):
|
def test_repair_corrupted_segment(self):
|
||||||
self.add_objects([[1, 2, 3], [4, 5], [6]])
|
self.add_objects([[1, 2, 3], [4, 5], [6]])
|
||||||
self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects())
|
self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects())
|
||||||
self.check(status=True)
|
self.check(status=True)
|
||||||
self.corrupt_object(5)
|
self.corrupt_object(5)
|
||||||
self.assert_raises(IntegrityError, lambda: self.get_objects(5))
|
self.assert_raises(IntegrityError, lambda: self.get_objects(5))
|
||||||
@ -746,22 +746,22 @@ def test_repair_corrupted_segment(self):
|
|||||||
self.check(repair=True, status=True)
|
self.check(repair=True, status=True)
|
||||||
self.get_objects(4)
|
self.get_objects(4)
|
||||||
self.check(status=True)
|
self.check(status=True)
|
||||||
self.assert_equal(set([1, 2, 3, 4, 6]), self.list_objects())
|
self.assert_equal({1, 2, 3, 4, 6}, self.list_objects())
|
||||||
|
|
||||||
def test_repair_missing_segment(self):
|
def test_repair_missing_segment(self):
|
||||||
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
||||||
self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects())
|
self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects())
|
||||||
self.check(status=True)
|
self.check(status=True)
|
||||||
self.delete_segment(2)
|
self.delete_segment(2)
|
||||||
self.repository.rollback()
|
self.repository.rollback()
|
||||||
self.check(repair=True, status=True)
|
self.check(repair=True, status=True)
|
||||||
self.assert_equal(set([1, 2, 3]), self.list_objects())
|
self.assert_equal({1, 2, 3}, self.list_objects())
|
||||||
|
|
||||||
def test_repair_missing_commit_segment(self):
|
def test_repair_missing_commit_segment(self):
|
||||||
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
||||||
self.delete_segment(3)
|
self.delete_segment(3)
|
||||||
self.assert_raises(Repository.ObjectNotFound, lambda: self.get_objects(4))
|
self.assert_raises(Repository.ObjectNotFound, lambda: self.get_objects(4))
|
||||||
self.assert_equal(set([1, 2, 3]), self.list_objects())
|
self.assert_equal({1, 2, 3}, self.list_objects())
|
||||||
|
|
||||||
def test_repair_corrupted_commit_segment(self):
|
def test_repair_corrupted_commit_segment(self):
|
||||||
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
||||||
@ -771,7 +771,7 @@ def test_repair_corrupted_commit_segment(self):
|
|||||||
self.assert_raises(Repository.ObjectNotFound, lambda: self.get_objects(4))
|
self.assert_raises(Repository.ObjectNotFound, lambda: self.get_objects(4))
|
||||||
self.check(status=True)
|
self.check(status=True)
|
||||||
self.get_objects(3)
|
self.get_objects(3)
|
||||||
self.assert_equal(set([1, 2, 3]), self.list_objects())
|
self.assert_equal({1, 2, 3}, self.list_objects())
|
||||||
|
|
||||||
def test_repair_no_commits(self):
|
def test_repair_no_commits(self):
|
||||||
self.add_objects([[1, 2, 3]])
|
self.add_objects([[1, 2, 3]])
|
||||||
@ -786,14 +786,14 @@ def test_repair_no_commits(self):
|
|||||||
self.assert_equal(self.list_indices(), ['index.2'])
|
self.assert_equal(self.list_indices(), ['index.2'])
|
||||||
self.check(status=True)
|
self.check(status=True)
|
||||||
self.get_objects(3)
|
self.get_objects(3)
|
||||||
self.assert_equal(set([1, 2, 3]), self.list_objects())
|
self.assert_equal({1, 2, 3}, self.list_objects())
|
||||||
|
|
||||||
def test_repair_missing_index(self):
|
def test_repair_missing_index(self):
|
||||||
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
||||||
self.delete_index()
|
self.delete_index()
|
||||||
self.check(status=True)
|
self.check(status=True)
|
||||||
self.get_objects(4)
|
self.get_objects(4)
|
||||||
self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects())
|
self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects())
|
||||||
|
|
||||||
def test_repair_index_too_new(self):
|
def test_repair_index_too_new(self):
|
||||||
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
self.add_objects([[1, 2, 3], [4, 5, 6]])
|
||||||
@ -802,7 +802,7 @@ def test_repair_index_too_new(self):
|
|||||||
self.check(status=True)
|
self.check(status=True)
|
||||||
self.assert_equal(self.list_indices(), ['index.3'])
|
self.assert_equal(self.list_indices(), ['index.3'])
|
||||||
self.get_objects(4)
|
self.get_objects(4)
|
||||||
self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects())
|
self.assert_equal({1, 2, 3, 4, 5, 6}, self.list_objects())
|
||||||
|
|
||||||
def test_crash_before_compact(self):
|
def test_crash_before_compact(self):
|
||||||
self.repository.put(H(0), b'data')
|
self.repository.put(H(0), b'data')
|
||||||
|
@ -54,7 +54,7 @@ def key_valid(path):
|
|||||||
"""
|
"""
|
||||||
keyfile = os.path.join(get_keys_dir(),
|
keyfile = os.path.join(get_keys_dir(),
|
||||||
os.path.basename(path))
|
os.path.basename(path))
|
||||||
with open(keyfile, 'r') as f:
|
with open(keyfile) as f:
|
||||||
return f.read().startswith(KeyfileKey.FILE_ID)
|
return f.read().startswith(KeyfileKey.FILE_ID)
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ def upgrade(self, dryrun=True, inplace=False, progress=False):
|
|||||||
with self:
|
with self:
|
||||||
backup = None
|
backup = None
|
||||||
if not inplace:
|
if not inplace:
|
||||||
backup = '{}.before-upgrade-{:%Y-%m-%d-%H:%M:%S}'.format(self.path, datetime.datetime.now())
|
backup = f'{self.path}.before-upgrade-{datetime.datetime.now():%Y-%m-%d-%H:%M:%S}'
|
||||||
logger.info('making a hardlink copy in %s', backup)
|
logger.info('making a hardlink copy in %s', backup)
|
||||||
if not dryrun:
|
if not dryrun:
|
||||||
shutil.copytree(self.path, backup, copy_function=os.link)
|
shutil.copytree(self.path, backup, copy_function=os.link)
|
||||||
@ -144,7 +144,7 @@ def convert_keyfiles(keyfile, dryrun):
|
|||||||
problem because the keyfiles are small (compared to, say,
|
problem because the keyfiles are small (compared to, say,
|
||||||
all the segments)."""
|
all the segments)."""
|
||||||
logger.info("converting keyfile %s" % keyfile)
|
logger.info("converting keyfile %s" % keyfile)
|
||||||
with open(keyfile, 'r') as f:
|
with open(keyfile) as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
data = data.replace(AtticKeyfileKey.FILE_ID, KeyfileKey.FILE_ID, 1)
|
data = data.replace(AtticKeyfileKey.FILE_ID, KeyfileKey.FILE_ID, 1)
|
||||||
keyfile = os.path.join(get_keys_dir(), os.path.basename(keyfile))
|
keyfile = os.path.join(get_keys_dir(), os.path.basename(keyfile))
|
||||||
@ -214,12 +214,12 @@ def copy_cache_file(path):
|
|||||||
if os.path.exists(borg_file):
|
if os.path.exists(borg_file):
|
||||||
logger.warning("borg cache file already exists in %s, not copying from Attic", borg_file)
|
logger.warning("borg cache file already exists in %s, not copying from Attic", borg_file)
|
||||||
else:
|
else:
|
||||||
logger.info("copying attic cache file from %s to %s" % (attic_file, borg_file))
|
logger.info(f"copying attic cache file from {attic_file} to {borg_file}")
|
||||||
if not dryrun:
|
if not dryrun:
|
||||||
shutil.copyfile(attic_file, borg_file)
|
shutil.copyfile(attic_file, borg_file)
|
||||||
return borg_file
|
return borg_file
|
||||||
else:
|
else:
|
||||||
logger.warning("no %s cache file found in %s" % (path, attic_file))
|
logger.warning(f"no {path} cache file found in {attic_file}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# XXX: untested, because generating cache files is a PITA, see
|
# XXX: untested, because generating cache files is a PITA, see
|
||||||
@ -270,7 +270,7 @@ def find_key_file(cls, repository):
|
|||||||
raise KeyfileNotFoundError(repository.path, keys_dir)
|
raise KeyfileNotFoundError(repository.path, keys_dir)
|
||||||
for name in os.listdir(keys_dir):
|
for name in os.listdir(keys_dir):
|
||||||
filename = os.path.join(keys_dir, name)
|
filename = os.path.join(keys_dir, name)
|
||||||
with open(filename, 'r') as fd:
|
with open(filename) as fd:
|
||||||
line = fd.readline().strip()
|
line = fd.readline().strip()
|
||||||
if line and line.startswith(cls.FILE_ID) and line[10:] == repository.id_str:
|
if line and line.startswith(cls.FILE_ID) and line[10:] == repository.id_str:
|
||||||
return filename
|
return filename
|
||||||
@ -319,7 +319,7 @@ def find_key_file(cls, repository):
|
|||||||
raise KeyfileNotFoundError(repository.path, keys_dir)
|
raise KeyfileNotFoundError(repository.path, keys_dir)
|
||||||
for name in os.listdir(keys_dir):
|
for name in os.listdir(keys_dir):
|
||||||
filename = os.path.join(keys_dir, name)
|
filename = os.path.join(keys_dir, name)
|
||||||
with open(filename, 'r') as fd:
|
with open(filename) as fd:
|
||||||
line = fd.readline().strip()
|
line = fd.readline().strip()
|
||||||
if line and line.startswith(cls.FILE_ID) and line[len(cls.FILE_ID) + 1:] == repository.id_str:
|
if line and line.startswith(cls.FILE_ID) and line[len(cls.FILE_ID) + 1:] == repository.id_str:
|
||||||
return filename
|
return filename
|
||||||
|
@ -91,7 +91,7 @@ def get_all(path, follow_symlinks=False):
|
|||||||
pass
|
pass
|
||||||
elif e.errno == errno.EPERM:
|
elif e.errno == errno.EPERM:
|
||||||
# we were not permitted to read this attribute, still can continue trying to read others
|
# we were not permitted to read this attribute, still can continue trying to read others
|
||||||
logger.warning('%s: Operation not permitted when reading extended attribute %s' % (
|
logger.warning('{}: Operation not permitted when reading extended attribute {}'.format(
|
||||||
path_str, name_str))
|
path_str, name_str))
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
Loading…
Reference in New Issue
Block a user