mirror of https://github.com/borgbackup/borg.git
Merge branch 'master' of github.com:borgbackup/borg into docfix-6231
This commit is contained in:
commit
e00c12519f
99
setup.cfg
99
setup.cfg
|
@ -76,112 +76,33 @@ markers =
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
# for reference ...
|
# for reference ...
|
||||||
# E121 continuation line under-indented for hanging indent
|
|
||||||
# E122 continuation line missing indentation or outdented
|
|
||||||
# E123 closing bracket does not match indentation of opening bracket's line
|
|
||||||
# E125 continuation line with same indent as next logical line
|
|
||||||
# E126 continuation line over-indented for hanging indent
|
|
||||||
# E127 continuation line over-indented for visual indent
|
|
||||||
# E128 continuation line under-indented for visual indent
|
|
||||||
# E221 multiple spaces before operator
|
|
||||||
# E226 missing whitespace around arithmetic operator
|
|
||||||
# E261 at least two spaces before inline comment
|
|
||||||
# E265 block comment should start with '# '
|
|
||||||
# E301 expected 1 blank line
|
|
||||||
# E305 expected 2 blank lines after class or function definition
|
|
||||||
# E401 multiple imports on one line
|
|
||||||
# E402 module level import not at top
|
# E402 module level import not at top
|
||||||
# E501 line too long
|
# E501 line too long
|
||||||
# E722 do not use bare except
|
|
||||||
# E731 do not assign a lambda expression, use def
|
|
||||||
# E741 ambiguous variable name
|
|
||||||
# F401 import unused
|
# F401 import unused
|
||||||
# F403 from ... import * used, unable to detect undefined names
|
|
||||||
# F405 undefined or defined from star imports
|
# F405 undefined or defined from star imports
|
||||||
# F811 redef of unused var
|
# F811 redef of unused var
|
||||||
# F821 undefined name
|
|
||||||
# W391 blank line at end of file
|
|
||||||
# #### Pick either W503, or W504 - latest recommendation from pep8 is to ignore W503
|
# #### Pick either W503, or W504 - latest recommendation from pep8 is to ignore W503
|
||||||
# W503 line break before binary operator
|
# W503 line break before binary operator
|
||||||
# W504 line break after binary operator
|
# W504 line break after binary operator
|
||||||
|
|
||||||
# borg code style guidelines:
|
# borg code style guidelines:
|
||||||
# Ignoring E203 due to https://github.com/PyCQA/pycodestyle/issues/373
|
# Ignoring E203 due to https://github.com/PyCQA/pycodestyle/issues/373
|
||||||
ignore = E226, W503, E203
|
ignore = W503, E203, F405, E402
|
||||||
|
|
||||||
# Code style violation exceptions:
|
# Code style violation exceptions:
|
||||||
# please note that the values are adjusted so that they do not cause failures
|
# please note that the values are adjusted so that they do not cause failures
|
||||||
# with existing code. if you want to change them, you should first fix all
|
# with existing code. if you want to change them, you should first fix all
|
||||||
# flake8 failures that appear with your change.
|
# flake8 failures that appear with your change.
|
||||||
per_file_ignores =
|
per_file_ignores =
|
||||||
docs/conf.py:E121,E126,E265,E305,E401,E402
|
src/borg/archive.py:E501
|
||||||
src/borg/archive.py:E122,E125,E127,E402,E501,F401,F405,W504
|
src/borg/archiver/help_cmd.py:E501
|
||||||
src/borg/archiver/__init__.py:E402,E501,E722,E741,F405
|
src/borg/cache.py:E501
|
||||||
src/borg/archiver/_common.py:E501,F405
|
src/borg/helpers/__init__.py:F401
|
||||||
src/borg/archiver/benchmark_cmd.py:F405
|
src/borg/platform/__init__.py:F401
|
||||||
src/borg/archiver/config_cmd.py:F405,E722
|
src/borg/testsuite/archiver/disk_full.py:F811
|
||||||
src/borg/archiver/create_cmd.py:E501,F405
|
src/borg/testsuite/archiver/return_codes.py:F811
|
||||||
src/borg/archiver/debug_cmd.py:F405
|
src/borg/testsuite/benchmark.py:F811
|
||||||
src/borg/archiver/delete_cmd.py:F405
|
src/borg/testsuite/platform.py:F811
|
||||||
src/borg/archiver/diff_cmd.py:F405
|
|
||||||
src/borg/archiver/help_cmd.py:E501,F405
|
|
||||||
src/borg/archiver/key_cmds.py:F405
|
|
||||||
src/borg/archiver/prune_cmd.py:F405
|
|
||||||
src/borg/archiver/rcompress_cmd.py:F405
|
|
||||||
src/borg/archiver/recreate_cmd.py:F405
|
|
||||||
src/borg/archiver/rdelete_cmd.py:F405
|
|
||||||
src/borg/archiver/rlist_cmd.py:E501
|
|
||||||
src/borg/archiver/tar_cmds.py:F405
|
|
||||||
src/borg/cache.py:E127,E128,E402,E501,E722,W504
|
|
||||||
src/borg/fuse.py:E402,E501,E722,W504
|
|
||||||
src/borg/fuse_impl.py:F811
|
|
||||||
src/borg/locking.py:E128,E501,E722
|
|
||||||
src/borg/manifest.py:E128,E402,E501,F405
|
|
||||||
src/borg/remote.py:E128,E501,F405
|
|
||||||
src/borg/repository.py:E126,E128,E501,F401,F405,W504
|
|
||||||
src/borg/upgrader.py:E501
|
|
||||||
src/borg/xattr.py:E402
|
|
||||||
src/borg/crypto/key.py:E125,E128,E402,E501,F401,F405,W504
|
|
||||||
src/borg/crypto/keymanager.py:E126,E128,E501,F401
|
|
||||||
src/borg/crypto/nonces.py:E128,E501
|
|
||||||
src/borg/helpers/__init__.py:F401,F405
|
|
||||||
src/borg/helpers/checks.py:F401
|
|
||||||
src/borg/helpers/errors.py:F405
|
|
||||||
src/borg/helpers/fs.py:F405
|
|
||||||
src/borg/helpers/misc.py:E402,E722,F401,F405
|
|
||||||
src/borg/helpers/msgpack.py:E127,F405
|
|
||||||
src/borg/helpers/parseformat.py:E402,E501,E741,F401,F405
|
|
||||||
src/borg/helpers/process.py:E402,F401,W504
|
|
||||||
src/borg/helpers/progress.py:E402
|
|
||||||
src/borg/helpers/shellpattern.py:E501
|
|
||||||
src/borg/platform/__init__.py:F401,F811
|
|
||||||
src/borg/platform/base.py:E402
|
|
||||||
src/borg/testsuite/__init__.py:E501,F401
|
|
||||||
src/borg/testsuite/archive.py:E128,W504
|
|
||||||
src/borg/testsuite/archiver/__init__.py:E128,E501,E722,F401,F405,F811
|
|
||||||
src/borg/testsuite/archiver/debug_cmds.py:E501,F405
|
|
||||||
src/borg/testsuite/archiver/disk_full.py:F401,F405,F811
|
|
||||||
src/borg/testsuite/archiver/extract_cmd.py:F405
|
|
||||||
src/borg/testsuite/archiver/mount_cmds.py:E501,E722
|
|
||||||
src/borg/testsuite/archiver/prune_cmd.py:F405
|
|
||||||
src/borg/testsuite/archiver/rcompress_cmd.py:F405
|
|
||||||
src/borg/testsuite/archiver/recreate_cmd.py:F405
|
|
||||||
src/borg/testsuite/archiver/return_codes.py:F401,F405,F811
|
|
||||||
src/borg/testsuite/benchmark.py:F401,F811
|
|
||||||
src/borg/testsuite/chunker.py:E501,F405
|
|
||||||
src/borg/testsuite/chunker_pytest.py:F401,F405
|
|
||||||
src/borg/testsuite/chunker_slow.py:F405
|
|
||||||
src/borg/testsuite/crypto.py:E126,E501,E741
|
|
||||||
src/borg/testsuite/file_integrity.py:F401
|
|
||||||
src/borg/testsuite/hashindex.py:F401
|
|
||||||
src/borg/testsuite/helpers.py:E126,E127,E128,E501,F401
|
|
||||||
src/borg/testsuite/key.py:E501,F401
|
|
||||||
src/borg/testsuite/locking.py:E126,E128,E501,E722,F401
|
|
||||||
src/borg/testsuite/patterns.py:E123
|
|
||||||
src/borg/testsuite/platform.py:E128,E501,F401,F811
|
|
||||||
src/borg/testsuite/repository.py:E128,E501,F401
|
|
||||||
src/borg/testsuite/shellpattern.py:E123
|
|
||||||
src/borg/testsuite/upgrader.py:F405
|
|
||||||
|
|
||||||
max_line_length = 120
|
max_line_length = 120
|
||||||
exclude = build,dist,.git,.idea,.cache,.tox
|
exclude = build,dist,.git,.idea,.cache,.tox
|
||||||
|
|
|
@ -6,7 +6,7 @@ import sys
|
||||||
import time
|
import time
|
||||||
from collections import OrderedDict, defaultdict
|
from collections import OrderedDict, defaultdict
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from datetime import datetime, timedelta
|
from datetime import timedelta
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from getpass import getuser
|
from getpass import getuser
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
@ -22,7 +22,7 @@ logger = create_logger()
|
||||||
from . import xattr
|
from . import xattr
|
||||||
from .chunker import get_chunker, Chunk
|
from .chunker import get_chunker, Chunk
|
||||||
from .cache import ChunkListEntry
|
from .cache import ChunkListEntry
|
||||||
from .crypto.key import key_factory, UnsupportedPayloadError, AEADKeyBase
|
from .crypto.key import key_factory, UnsupportedPayloadError
|
||||||
from .compress import Compressor, CompressionSpec
|
from .compress import Compressor, CompressionSpec
|
||||||
from .constants import * # NOQA
|
from .constants import * # NOQA
|
||||||
from .crypto.low_level import IntegrityError as IntegrityErrorBase
|
from .crypto.low_level import IntegrityError as IntegrityErrorBase
|
||||||
|
@ -974,8 +974,8 @@ Duration: {0.duration}
|
||||||
if not self.noacls:
|
if not self.noacls:
|
||||||
acl_set(path, item, self.numeric_ids, fd=fd)
|
acl_set(path, item, self.numeric_ids, fd=fd)
|
||||||
if not self.noxattrs and "xattrs" in item:
|
if not self.noxattrs and "xattrs" in item:
|
||||||
# chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include
|
# chown removes Linux capabilities, so set the extended attributes at the end, after chown,
|
||||||
# the Linux capabilities in the "security.capability" attribute.
|
# since they include the Linux capabilities in the "security.capability" attribute.
|
||||||
warning = xattr.set_all(fd or path, item.xattrs, follow_symlinks=False)
|
warning = xattr.set_all(fd or path, item.xattrs, follow_symlinks=False)
|
||||||
if warning:
|
if warning:
|
||||||
set_ec(EXIT_WARNING)
|
set_ec(EXIT_WARNING)
|
||||||
|
|
|
@ -570,8 +570,8 @@ def format_tb(exc):
|
||||||
remote = isinstance(exc, RemoteRepository.RPCError)
|
remote = isinstance(exc, RemoteRepository.RPCError)
|
||||||
if remote:
|
if remote:
|
||||||
prefix = "Borg server: "
|
prefix = "Borg server: "
|
||||||
trace_back = "\n".join(prefix + l for l in exc.exception_full.splitlines())
|
trace_back = "\n".join(prefix + line for line in exc.exception_full.splitlines())
|
||||||
sys_info = "\n".join(prefix + l for l in exc.sysinfo.splitlines())
|
sys_info = "\n".join(prefix + line for line in exc.sysinfo.splitlines())
|
||||||
else:
|
else:
|
||||||
trace_back = traceback.format_exc()
|
trace_back = traceback.format_exc()
|
||||||
sys_info = sysinfo()
|
sys_info = sysinfo()
|
||||||
|
|
|
@ -85,7 +85,8 @@ def with_repository(
|
||||||
:param manifest: load manifest and repo_objs (key), pass them as keyword arguments
|
:param manifest: load manifest and repo_objs (key), pass them as keyword arguments
|
||||||
:param cache: open cache, pass it as keyword argument (implies manifest)
|
:param cache: open cache, pass it as keyword argument (implies manifest)
|
||||||
:param secure: do assert_secure after loading manifest
|
:param secure: do assert_secure after loading manifest
|
||||||
:param compatibility: mandatory if not create and (manifest or cache), specifies mandatory feature categories to check
|
:param compatibility: mandatory if not create and (manifest or cache), specifies mandatory
|
||||||
|
feature categories to check
|
||||||
"""
|
"""
|
||||||
# Note: with_repository decorator does not have a "key" argument (yet?)
|
# Note: with_repository decorator does not have a "key" argument (yet?)
|
||||||
compatibility = compat_check(
|
compatibility = compat_check(
|
||||||
|
|
|
@ -50,7 +50,7 @@ class ConfigMixIn:
|
||||||
if check_value:
|
if check_value:
|
||||||
try:
|
try:
|
||||||
bin_id = unhexlify(value)
|
bin_id = unhexlify(value)
|
||||||
except:
|
except: # noqa
|
||||||
raise ValueError("Invalid value, must be 64 hex digits") from None
|
raise ValueError("Invalid value, must be 64 hex digits") from None
|
||||||
if len(bin_id) != 32:
|
if len(bin_id) != 32:
|
||||||
raise ValueError("Invalid value, must be 64 hex digits")
|
raise ValueError("Invalid value, must be 64 hex digits")
|
||||||
|
|
|
@ -66,7 +66,7 @@ class RListMixIn:
|
||||||
# Strings are left-aligned, numbers are right-aligned.
|
# Strings are left-aligned, numbers are right-aligned.
|
||||||
# Note: time columns except ``isomtime``, ``isoctime`` and ``isoatime`` cannot be padded.
|
# Note: time columns except ``isomtime``, ``isoctime`` and ``isoatime`` cannot be padded.
|
||||||
$ borg rlist --format '{archive:36} {time} [{id}]{NL}' /path/to/repo
|
$ borg rlist --format '{archive:36} {time} [{id}]{NL}' /path/to/repo
|
||||||
ArchiveFoo Thu, 2021-12-09 10:22:28 [0b8e9a312bef3f2f6e2d0fc110c196827786c15eba0188738e81697a7fa3b274]
|
ArchiveFoo Thu, 2021-12-09 10:22:28 [0b8e9...3b274]
|
||||||
...
|
...
|
||||||
|
|
||||||
The following keys are always available:
|
The following keys are always available:
|
||||||
|
|
|
@ -534,7 +534,7 @@ class LocalCache(CacheStatsMixin):
|
||||||
if sync and self.manifest.id != self.cache_config.manifest_id:
|
if sync and self.manifest.id != self.cache_config.manifest_id:
|
||||||
self.sync()
|
self.sync()
|
||||||
self.commit()
|
self.commit()
|
||||||
except:
|
except: # noqa
|
||||||
self.close()
|
self.close()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
@ -895,8 +895,9 @@ class LocalCache(CacheStatsMixin):
|
||||||
|
|
||||||
self.begin_txn()
|
self.begin_txn()
|
||||||
with cache_if_remote(self.repository, decrypted_cache=self.repo_objs) as decrypted_repository:
|
with cache_if_remote(self.repository, decrypted_cache=self.repo_objs) as decrypted_repository:
|
||||||
# TEMPORARY HACK: to avoid archive index caching, create a FILE named ~/.cache/borg/REPOID/chunks.archive.d -
|
# TEMPORARY HACK:
|
||||||
# this is only recommended if you have a fast, low latency connection to your repo (e.g. if repo is local disk)
|
# to avoid archive index caching, create a FILE named ~/.cache/borg/REPOID/chunks.archive.d -
|
||||||
|
# this is only recommended if you have a fast, low latency connection to your repo (e.g. if repo is local).
|
||||||
self.do_cache = os.path.isdir(archive_path)
|
self.do_cache = os.path.isdir(archive_path)
|
||||||
self.chunks = create_master_idx(self.chunks)
|
self.chunks = create_master_idx(self.chunks)
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ class KeyManager:
|
||||||
def import_paperkey(self, args):
|
def import_paperkey(self, args):
|
||||||
try:
|
try:
|
||||||
# imported here because it has global side effects
|
# imported here because it has global side effects
|
||||||
import readline
|
import readline # noqa
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print("Note: No line editing available due to missing readline support")
|
print("Note: No line editing available due to missing readline support")
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ def fuse_main():
|
||||||
if has_pyfuse3:
|
if has_pyfuse3:
|
||||||
try:
|
try:
|
||||||
trio.run(llfuse.main)
|
trio.run(llfuse.main)
|
||||||
except:
|
except: # noqa
|
||||||
return 1 # TODO return signal number if it was killed by signal
|
return 1 # TODO return signal number if it was killed by signal
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -31,6 +31,6 @@ for FUSE_IMPL in BORG_FUSE_IMPL.split(","):
|
||||||
else:
|
else:
|
||||||
raise RuntimeError("unknown fuse implementation in BORG_FUSE_IMPL: '%s'" % BORG_FUSE_IMPL)
|
raise RuntimeError("unknown fuse implementation in BORG_FUSE_IMPL: '%s'" % BORG_FUSE_IMPL)
|
||||||
else:
|
else:
|
||||||
llfuse = None
|
llfuse = None # noqa
|
||||||
has_llfuse = False
|
has_llfuse = False
|
||||||
has_pyfuse3 = False
|
has_pyfuse3 = False
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from .errors import Error
|
from .errors import Error
|
||||||
from ..platformflags import is_win32, is_linux, is_freebsd, is_darwin
|
from ..platformflags import is_win32
|
||||||
|
|
||||||
|
|
||||||
class PythonLibcTooOld(Error):
|
class PythonLibcTooOld(Error):
|
||||||
|
|
|
@ -13,7 +13,6 @@ logger = create_logger()
|
||||||
|
|
||||||
from . import msgpack
|
from . import msgpack
|
||||||
from .. import __version__ as borg_version
|
from .. import __version__ as borg_version
|
||||||
from .. import chunker
|
|
||||||
|
|
||||||
|
|
||||||
def sysinfo():
|
def sysinfo():
|
||||||
|
@ -35,7 +34,7 @@ def sysinfo():
|
||||||
linux_distribution = None
|
linux_distribution = None
|
||||||
try:
|
try:
|
||||||
msgpack_version = ".".join(str(v) for v in msgpack.version)
|
msgpack_version = ".".join(str(v) for v in msgpack.version)
|
||||||
except:
|
except: # noqa
|
||||||
msgpack_version = "unknown"
|
msgpack_version = "unknown"
|
||||||
from ..fuse_impl import llfuse, BORG_FUSE_IMPL
|
from ..fuse_impl import llfuse, BORG_FUSE_IMPL
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import re
|
||||||
import shlex
|
import shlex
|
||||||
import stat
|
import stat
|
||||||
import uuid
|
import uuid
|
||||||
from typing import List, Dict, Set, Tuple, ClassVar, Any, TYPE_CHECKING, Literal
|
from typing import Dict, Set, Tuple, ClassVar, Any, TYPE_CHECKING, Literal
|
||||||
from binascii import hexlify
|
from binascii import hexlify
|
||||||
from collections import Counter, OrderedDict
|
from collections import Counter, OrderedDict
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
@ -27,7 +27,6 @@ from .time import OutputTimestamp, format_time, safe_timestamp
|
||||||
from .. import __version__ as borg_version
|
from .. import __version__ as borg_version
|
||||||
from .. import __version_tuple__ as borg_version_tuple
|
from .. import __version_tuple__ as borg_version_tuple
|
||||||
from ..constants import * # NOQA
|
from ..constants import * # NOQA
|
||||||
from ..platformflags import is_win32
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..item import ItemDiff
|
from ..item import ItemDiff
|
||||||
|
@ -374,8 +373,8 @@ def format_archive(archive):
|
||||||
|
|
||||||
|
|
||||||
def parse_stringified_list(s):
|
def parse_stringified_list(s):
|
||||||
l = re.split(" *, *", s)
|
items = re.split(" *, *", s)
|
||||||
return [item for item in l if item != ""]
|
return [item for item in items if item != ""]
|
||||||
|
|
||||||
|
|
||||||
class Location:
|
class Location:
|
||||||
|
@ -457,7 +456,7 @@ class Location:
|
||||||
(?:file://)? # optional file protocol
|
(?:file://)? # optional file protocol
|
||||||
(?P<path>
|
(?P<path>
|
||||||
(?:[a-zA-Z]:)? # Drive letter followed by a colon (optional)
|
(?:[a-zA-Z]:)? # Drive letter followed by a colon (optional)
|
||||||
(?:[^:]+) # Anything which does not contain a :, at least one character
|
(?:[^:]+) # Anything which does not contain a :, at least one char
|
||||||
)
|
)
|
||||||
""",
|
""",
|
||||||
re.VERBOSE,
|
re.VERBOSE,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
|
||||||
import shlex
|
import shlex
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -11,7 +10,7 @@ import traceback
|
||||||
|
|
||||||
from .. import __version__
|
from .. import __version__
|
||||||
|
|
||||||
from ..platformflags import is_win32, is_linux, is_freebsd, is_darwin
|
from ..platformflags import is_win32
|
||||||
from ..logger import create_logger
|
from ..logger import create_logger
|
||||||
|
|
||||||
logger = create_logger()
|
logger = create_logger()
|
||||||
|
|
|
@ -6,10 +6,9 @@ from queue import LifoQueue
|
||||||
def translate(pat, match_end=r"\Z"):
|
def translate(pat, match_end=r"\Z"):
|
||||||
"""Translate a shell-style pattern to a regular expression.
|
"""Translate a shell-style pattern to a regular expression.
|
||||||
|
|
||||||
The pattern may include ``**<sep>`` (<sep> stands for the platform-specific path separator; "/" on POSIX systems) for
|
The pattern may include ``**<sep>`` (<sep> stands for the platform-specific path separator; "/" on POSIX systems)
|
||||||
matching zero or more directory levels and "*" for matching zero or more arbitrary characters with the exception of
|
for matching zero or more directory levels and "*" for matching zero or more arbitrary characters except any path
|
||||||
any path separator. Wrap meta-characters in brackets for a literal match (i.e. "[?]" to match the literal character
|
separator. Wrap meta-characters in brackets for a literal match (i.e. "[?]" to match the literal character "?").
|
||||||
"?").
|
|
||||||
|
|
||||||
Using match_end=regex one can give a regular expression that is used to match after the regex that is generated from
|
Using match_end=regex one can give a regular expression that is used to match after the regex that is generated from
|
||||||
the pattern. The default is to match the end of the string.
|
the pattern. The default is to match the end of the string.
|
||||||
|
|
|
@ -157,11 +157,11 @@ class ExclusiveLock:
|
||||||
# should be cleaned up anyway. Try to clean up, but don't crash.
|
# should be cleaned up anyway. Try to clean up, but don't crash.
|
||||||
try:
|
try:
|
||||||
os.unlink(temp_unique_name)
|
os.unlink(temp_unique_name)
|
||||||
except:
|
except: # noqa
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
os.rmdir(temp_path)
|
os.rmdir(temp_path)
|
||||||
except:
|
except: # noqa
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def release(self):
|
def release(self):
|
||||||
|
@ -417,7 +417,7 @@ class Lock:
|
||||||
# restore the roster state as before (undo the roster change):
|
# restore the roster state as before (undo the roster change):
|
||||||
if remove is not None:
|
if remove is not None:
|
||||||
self._roster.modify(remove, ADD)
|
self._roster.modify(remove, ADD)
|
||||||
except:
|
except: # noqa
|
||||||
# avoid orphan lock when an exception happens here, e.g. Ctrl-C!
|
# avoid orphan lock when an exception happens here, e.g. Ctrl-C!
|
||||||
self._lock.release()
|
self._lock.release()
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -164,7 +164,8 @@ class Archives(abc.MutableMapping):
|
||||||
consider_checkpoints = getattr(args, "consider_checkpoints", None)
|
consider_checkpoints = getattr(args, "consider_checkpoints", None)
|
||||||
if name is not None:
|
if name is not None:
|
||||||
raise Error(
|
raise Error(
|
||||||
"Giving a specific name is incompatible with options --first, --last, -a / --match-archives, and --consider-checkpoints."
|
"Giving a specific name is incompatible with options --first, --last, "
|
||||||
|
"-a / --match-archives, and --consider-checkpoints."
|
||||||
)
|
)
|
||||||
return self.list(
|
return self.list(
|
||||||
sort_by=args.sort_by.split(","),
|
sort_by=args.sort_by.split(","),
|
||||||
|
|
|
@ -108,7 +108,7 @@ class UnexpectedRPCDataFormatFromServer(Error):
|
||||||
# All method calls on the remote repository object must be allowlisted in RepositoryServer.rpc_methods and have api
|
# All method calls on the remote repository object must be allowlisted in RepositoryServer.rpc_methods and have api
|
||||||
# stubs in RemoteRepository. The @api decorator on these stubs is used to set server version requirements.
|
# stubs in RemoteRepository. The @api decorator on these stubs is used to set server version requirements.
|
||||||
#
|
#
|
||||||
# Method parameters are identified only by name and never by position. Unknown parameters are ignored by the server side.
|
# Method parameters are identified only by name and never by position. Unknown parameters are ignored by the server.
|
||||||
# If a new parameter is important and may not be ignored, on the client a parameter specific version requirement needs
|
# If a new parameter is important and may not be ignored, on the client a parameter specific version requirement needs
|
||||||
# to be added.
|
# to be added.
|
||||||
# When parameters are removed, they need to be preserved as defaulted parameters on the client stubs so that older
|
# When parameters are removed, they need to be preserved as defaulted parameters on the client stubs so that older
|
||||||
|
|
|
@ -881,13 +881,15 @@ class Repository:
|
||||||
#
|
#
|
||||||
# Now we crash. But only segment 2 gets deleted, while segment 1 is still around. Now key 1
|
# Now we crash. But only segment 2 gets deleted, while segment 1 is still around. Now key 1
|
||||||
# is suddenly undeleted (because the delete in segment 2 is now missing).
|
# is suddenly undeleted (because the delete in segment 2 is now missing).
|
||||||
# Again, note the requirement here. We delete these in the correct order that this doesn't happen,
|
# Again, note the requirement here. We delete these in the correct order that this doesn't
|
||||||
# and only if the FS materialization of these deletes is reordered or parts dropped this can happen.
|
# happen, and only if the FS materialization of these deletes is reordered or parts dropped
|
||||||
# In this case it doesn't cause outright corruption, 'just' an index count mismatch, which will be
|
# this can happen.
|
||||||
# fixed by borg-check --repair.
|
# In this case it doesn't cause outright corruption, 'just' an index count mismatch, which
|
||||||
|
# will be fixed by borg-check --repair.
|
||||||
#
|
#
|
||||||
# Note that in this check the index state is the proxy for a "most definitely settled" repository state,
|
# Note that in this check the index state is the proxy for a "most definitely settled"
|
||||||
# i.e. the assumption is that *all* operations on segments <= index state are completed and stable.
|
# repository state, i.e. the assumption is that *all* operations on segments <= index state
|
||||||
|
# are completed and stable.
|
||||||
try:
|
try:
|
||||||
new_segment, size = self.io.write_delete(key, raise_full=True)
|
new_segment, size = self.io.write_delete(key, raise_full=True)
|
||||||
except LoggedIO.SegmentFull:
|
except LoggedIO.SegmentFull:
|
||||||
|
|
|
@ -19,7 +19,7 @@ try:
|
||||||
except: # noqa
|
except: # noqa
|
||||||
raises = None
|
raises = None
|
||||||
|
|
||||||
from ..fuse_impl import llfuse, has_llfuse, has_pyfuse3
|
from ..fuse_impl import llfuse, has_llfuse, has_pyfuse3 # NOQA
|
||||||
from .. import platform
|
from .. import platform
|
||||||
from ..platformflags import is_win32
|
from ..platformflags import is_win32
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import time
|
||||||
|
|
||||||
from ...constants import * # NOQA
|
from ...constants import * # NOQA
|
||||||
from .. import are_symlinks_supported, are_hardlinks_supported
|
from .. import are_symlinks_supported, are_hardlinks_supported
|
||||||
from ..platform import is_win32, is_darwin
|
from ...platformflags import is_win32, is_darwin
|
||||||
from . import cmd, create_regular_file, RK_ENCRYPTION, assert_line_exists, generate_archiver_tests
|
from . import cmd, create_regular_file, RK_ENCRYPTION, assert_line_exists, generate_archiver_tests
|
||||||
|
|
||||||
pytest_generate_tests = lambda metafunc: generate_archiver_tests(metafunc, kinds="local,remote,binary") # NOQA
|
pytest_generate_tests = lambda metafunc: generate_archiver_tests(metafunc, kinds="local,remote,binary") # NOQA
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
"""
|
"""
|
||||||
test_disk_full is very slow and not recommended to be included in daily testing.
|
test_disk_full is very slow and not recommended to be included in daily testing.
|
||||||
for this test, an empty, writable 16MB filesystem mounted on DF_MOUNT is required.
|
for this test, an empty, writable 700MB filesystem mounted on DF_MOUNT is required.
|
||||||
for speed and other reasons, it is recommended that the underlying block device is
|
for speed and other reasons, it is recommended that the underlying block device is
|
||||||
in RAM, not a magnetic or flash disk.
|
in RAM, not a magnetic or flash disk.
|
||||||
|
|
||||||
assuming /tmp is a tmpfs (in memory filesystem), one can use this:
|
assuming /dev/shm is a tmpfs (in memory filesystem), one can use this:
|
||||||
dd if=/dev/zero of=/tmp/borg-disk bs=16M count=1
|
|
||||||
mkfs.ext4 /tmp/borg-disk
|
dd if=/dev/zero of=/dev/shm/borg-disk bs=1M count=700
|
||||||
|
mkfs.ext4 /dev/shm/borg-disk
|
||||||
mkdir /tmp/borg-mount
|
mkdir /tmp/borg-mount
|
||||||
sudo mount /tmp/borg-disk /tmp/borg-mount
|
sudo mount /dev/shm/borg-disk /tmp/borg-mount
|
||||||
|
sudo chown myuser /tmp/borg-mount/
|
||||||
|
|
||||||
if the directory does not exist, the test will be skipped.
|
if the directory does not exist, the test will be skipped.
|
||||||
"""
|
"""
|
||||||
|
@ -20,47 +22,46 @@ import shutil
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ...constants import * # NOQA
|
from ...constants import * # NOQA
|
||||||
from . import cmd_fixture
|
from . import cmd_fixture # NOQA
|
||||||
|
|
||||||
DF_MOUNT = "/tmp/borg-mount"
|
DF_MOUNT = "/tmp/borg-mount"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skipif(not os.path.exists(DF_MOUNT), reason="needs a 16MB fs mounted on %s" % DF_MOUNT)
|
def make_files(dir, count, size, rnd=True):
|
||||||
def test_disk_full(cmd_fixture, monkeypatch):
|
shutil.rmtree(dir, ignore_errors=True)
|
||||||
def make_files(dir, count, size, rnd=True):
|
os.mkdir(dir)
|
||||||
shutil.rmtree(dir, ignore_errors=True)
|
if rnd:
|
||||||
os.mkdir(dir)
|
count = random.randint(1, count)
|
||||||
if rnd:
|
if size > 1:
|
||||||
count = random.randint(1, count)
|
size = random.randint(1, size)
|
||||||
if size > 1:
|
for i in range(count):
|
||||||
size = random.randint(1, size)
|
fn = os.path.join(dir, "file%03d" % i)
|
||||||
for i in range(count):
|
with open(fn, "wb") as f:
|
||||||
fn = os.path.join(dir, "file%03d" % i)
|
data = os.urandom(size)
|
||||||
with open(fn, "wb") as f:
|
f.write(data)
|
||||||
data = os.urandom(size)
|
|
||||||
f.write(data)
|
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(not os.path.exists(DF_MOUNT), reason="needs a 700MB fs mounted on %s" % DF_MOUNT)
|
||||||
|
@pytest.mark.parametrize("test_pass", range(10))
|
||||||
|
def test_disk_full(test_pass, cmd_fixture, monkeypatch):
|
||||||
monkeypatch.setenv("BORG_CHECK_I_KNOW_WHAT_I_AM_DOING", "YES")
|
monkeypatch.setenv("BORG_CHECK_I_KNOW_WHAT_I_AM_DOING", "YES")
|
||||||
mount = DF_MOUNT
|
monkeypatch.setenv("BORG_DELETE_I_KNOW_WHAT_I_AM_DOING", "YES")
|
||||||
assert os.path.exists(mount)
|
repo = os.path.join(DF_MOUNT, "repo")
|
||||||
repo = os.path.join(mount, "repo")
|
input = os.path.join(DF_MOUNT, "input")
|
||||||
input = os.path.join(mount, "input")
|
shutil.rmtree(repo, ignore_errors=True)
|
||||||
reserve = os.path.join(mount, "reserve")
|
shutil.rmtree(input, ignore_errors=True)
|
||||||
for j in range(100):
|
rc, out = cmd_fixture(f"--repo={repo}", "rcreate", "--encryption=none")
|
||||||
shutil.rmtree(repo, ignore_errors=True)
|
if rc != EXIT_SUCCESS:
|
||||||
shutil.rmtree(input, ignore_errors=True)
|
print("rcreate", rc, out)
|
||||||
# keep some space and some inodes in reserve that we can free up later:
|
assert rc == EXIT_SUCCESS
|
||||||
make_files(reserve, 80, 100000, rnd=False)
|
try:
|
||||||
rc, out = cmd_fixture(f"--repo={repo}", "rcreate")
|
|
||||||
if rc != EXIT_SUCCESS:
|
|
||||||
print("rcreate", rc, out)
|
|
||||||
assert rc == EXIT_SUCCESS
|
|
||||||
try:
|
try:
|
||||||
success, i = True, 0
|
success, i = True, 0
|
||||||
while success:
|
while success:
|
||||||
i += 1
|
i += 1
|
||||||
try:
|
try:
|
||||||
make_files(input, 20, 200000)
|
# have some randomness here to produce different out of space conditions:
|
||||||
|
make_files(input, 40, 1000000, rnd=True)
|
||||||
except OSError as err:
|
except OSError as err:
|
||||||
if err.errno == errno.ENOSPC:
|
if err.errno == errno.ENOSPC:
|
||||||
# already out of space
|
# already out of space
|
||||||
|
@ -74,11 +75,11 @@ def test_disk_full(cmd_fixture, monkeypatch):
|
||||||
finally:
|
finally:
|
||||||
# make sure repo is not locked
|
# make sure repo is not locked
|
||||||
shutil.rmtree(os.path.join(repo, "lock.exclusive"), ignore_errors=True)
|
shutil.rmtree(os.path.join(repo, "lock.exclusive"), ignore_errors=True)
|
||||||
os.remove(os.path.join(repo, "lock.roster"))
|
shutil.rmtree(os.path.join(repo, "lock.roster"), ignore_errors=True)
|
||||||
finally:
|
finally:
|
||||||
# now some error happened, likely we are out of disk space.
|
# now some error happened, likely we are out of disk space.
|
||||||
# free some space such that we can expect borg to be able to work normally:
|
# free some space such that we can expect borg to be able to work normally:
|
||||||
shutil.rmtree(reserve, ignore_errors=True)
|
shutil.rmtree(input, ignore_errors=True)
|
||||||
rc, out = cmd_fixture(f"--repo={repo}", "rlist")
|
rc, out = cmd_fixture(f"--repo={repo}", "rlist")
|
||||||
if rc != EXIT_SUCCESS:
|
if rc != EXIT_SUCCESS:
|
||||||
print("rlist", rc, out)
|
print("rlist", rc, out)
|
||||||
|
@ -86,3 +87,6 @@ def test_disk_full(cmd_fixture, monkeypatch):
|
||||||
if rc != EXIT_SUCCESS:
|
if rc != EXIT_SUCCESS:
|
||||||
print("check", rc, out)
|
print("check", rc, out)
|
||||||
assert rc == EXIT_SUCCESS
|
assert rc == EXIT_SUCCESS
|
||||||
|
finally:
|
||||||
|
# try to free the space allocated for the repo
|
||||||
|
cmd_fixture(f"--repo={repo}", "rdelete")
|
||||||
|
|
|
@ -13,7 +13,7 @@ from ...helpers import EXIT_WARNING
|
||||||
from ...helpers import flags_noatime, flags_normal
|
from ...helpers import flags_noatime, flags_normal
|
||||||
from .. import changedir, same_ts_ns
|
from .. import changedir, same_ts_ns
|
||||||
from .. import are_symlinks_supported, are_hardlinks_supported, is_utime_fully_supported, is_birthtime_fully_supported
|
from .. import are_symlinks_supported, are_hardlinks_supported, is_utime_fully_supported, is_birthtime_fully_supported
|
||||||
from ..platform import is_darwin, is_win32
|
from ...platformflags import is_darwin, is_win32
|
||||||
from . import (
|
from . import (
|
||||||
RK_ENCRYPTION,
|
RK_ENCRYPTION,
|
||||||
requires_hardlinks,
|
requires_hardlinks,
|
||||||
|
|
|
@ -283,7 +283,7 @@ def test_migrate_lock_alive(archivers, request):
|
||||||
try:
|
try:
|
||||||
with open(assert_data_file, "wb") as _out:
|
with open(assert_data_file, "wb") as _out:
|
||||||
pickle.dump(assert_data, _out)
|
pickle.dump(assert_data, _out)
|
||||||
except:
|
except: # noqa
|
||||||
pass
|
pass
|
||||||
try:
|
try:
|
||||||
return migrate_lock(self, old_id, new_id)
|
return migrate_lock(self, old_id, new_id)
|
||||||
|
@ -297,7 +297,7 @@ def test_migrate_lock_alive(archivers, request):
|
||||||
try:
|
try:
|
||||||
with open(assert_data_file, "wb") as _out:
|
with open(assert_data_file, "wb") as _out:
|
||||||
pickle.dump(assert_data, _out)
|
pickle.dump(assert_data, _out)
|
||||||
except:
|
except: # noqa
|
||||||
pass
|
pass
|
||||||
|
|
||||||
wrapper.num_calls = 0
|
wrapper.num_calls = 0
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from ...constants import * # NOQA
|
from ...constants import * # NOQA
|
||||||
from . import cmd_fixture, changedir
|
from . import cmd_fixture, changedir # NOQA
|
||||||
|
|
||||||
|
|
||||||
def test_return_codes(cmd_fixture, tmpdir):
|
def test_return_codes(cmd_fixture, tmpdir):
|
||||||
|
|
|
@ -10,7 +10,7 @@ import os
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from .archiver import changedir, cmd_fixture
|
from .archiver import changedir, cmd_fixture # NOQA
|
||||||
from .item import Item
|
from .item import Item
|
||||||
from ..constants import zeros
|
from ..constants import zeros
|
||||||
|
|
||||||
|
|
|
@ -202,9 +202,9 @@ class CryptoTestCase(BaseTestCase):
|
||||||
ikm = b"\x0b" * 22
|
ikm = b"\x0b" * 22
|
||||||
salt = bytes.fromhex("000102030405060708090a0b0c")
|
salt = bytes.fromhex("000102030405060708090a0b0c")
|
||||||
info = bytes.fromhex("f0f1f2f3f4f5f6f7f8f9")
|
info = bytes.fromhex("f0f1f2f3f4f5f6f7f8f9")
|
||||||
l = 42
|
length = 42
|
||||||
|
|
||||||
okm = hkdf_hmac_sha512(ikm, salt, info, l)
|
okm = hkdf_hmac_sha512(ikm, salt, info, length)
|
||||||
assert okm == bytes.fromhex(
|
assert okm == bytes.fromhex(
|
||||||
"832390086cda71fb47625bb5ceb168e4c8e26a1a16ed34d9fc7fe92c1481579338da362cb8d9f925d7cb"
|
"832390086cda71fb47625bb5ceb168e4c8e26a1a16ed34d9fc7fe92c1481579338da362cb8d9f925d7cb"
|
||||||
)
|
)
|
||||||
|
@ -222,9 +222,9 @@ class CryptoTestCase(BaseTestCase):
|
||||||
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7"
|
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7"
|
||||||
"d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
|
"d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"
|
||||||
)
|
)
|
||||||
l = 82
|
length = 82
|
||||||
|
|
||||||
okm = hkdf_hmac_sha512(ikm, salt, info, l)
|
okm = hkdf_hmac_sha512(ikm, salt, info, length)
|
||||||
assert okm == bytes.fromhex(
|
assert okm == bytes.fromhex(
|
||||||
"ce6c97192805b346e6161e821ed165673b84f400a2b514b2fe23d84cd189ddf1b695b48cbd1c838844"
|
"ce6c97192805b346e6161e821ed165673b84f400a2b514b2fe23d84cd189ddf1b695b48cbd1c838844"
|
||||||
"1137b3ce28f16aa64ba33ba466b24df6cfcb021ecff235f6a2056ce3af1de44d572097a8505d9e7a93"
|
"1137b3ce28f16aa64ba33ba466b24df6cfcb021ecff235f6a2056ce3af1de44d572097a8505d9e7a93"
|
||||||
|
@ -234,9 +234,9 @@ class CryptoTestCase(BaseTestCase):
|
||||||
ikm = bytes.fromhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
|
ikm = bytes.fromhex("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
|
||||||
salt = None
|
salt = None
|
||||||
info = b""
|
info = b""
|
||||||
l = 42
|
length = 42
|
||||||
|
|
||||||
okm = hkdf_hmac_sha512(ikm, salt, info, l)
|
okm = hkdf_hmac_sha512(ikm, salt, info, length)
|
||||||
assert okm == bytes.fromhex(
|
assert okm == bytes.fromhex(
|
||||||
"f5fa02b18298a72a8c23898a8703472c6eb179dc204c03425c970e3b164bf90fff22d04836d0e2343bac"
|
"f5fa02b18298a72a8c23898a8703472c6eb179dc204c03425c970e3b164bf90fff22d04836d0e2343bac"
|
||||||
)
|
)
|
||||||
|
@ -245,9 +245,9 @@ class CryptoTestCase(BaseTestCase):
|
||||||
ikm = bytes.fromhex("0b0b0b0b0b0b0b0b0b0b0b")
|
ikm = bytes.fromhex("0b0b0b0b0b0b0b0b0b0b0b")
|
||||||
salt = bytes.fromhex("000102030405060708090a0b0c")
|
salt = bytes.fromhex("000102030405060708090a0b0c")
|
||||||
info = bytes.fromhex("f0f1f2f3f4f5f6f7f8f9")
|
info = bytes.fromhex("f0f1f2f3f4f5f6f7f8f9")
|
||||||
l = 42
|
length = 42
|
||||||
|
|
||||||
okm = hkdf_hmac_sha512(ikm, salt, info, l)
|
okm = hkdf_hmac_sha512(ikm, salt, info, length)
|
||||||
assert okm == bytes.fromhex(
|
assert okm == bytes.fromhex(
|
||||||
"7413e8997e020610fbf6823f2ce14bff01875db1ca55f68cfcf3954dc8aff53559bd5e3028b080f7c068"
|
"7413e8997e020610fbf6823f2ce14bff01875db1ca55f68cfcf3954dc8aff53559bd5e3028b080f7c068"
|
||||||
)
|
)
|
||||||
|
@ -256,9 +256,9 @@ class CryptoTestCase(BaseTestCase):
|
||||||
ikm = bytes.fromhex("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c")
|
ikm = bytes.fromhex("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c")
|
||||||
salt = None
|
salt = None
|
||||||
info = b""
|
info = b""
|
||||||
l = 42
|
length = 42
|
||||||
|
|
||||||
okm = hkdf_hmac_sha512(ikm, salt, info, l)
|
okm = hkdf_hmac_sha512(ikm, salt, info, length)
|
||||||
assert okm == bytes.fromhex(
|
assert okm == bytes.fromhex(
|
||||||
"1407d46013d98bc6decefcfee55f0f90b0c7f63d68eb1a80eaf07e953cfc0a3a5240a155d6e4daa965bb"
|
"1407d46013d98bc6decefcfee55f0f90b0c7f63d68eb1a80eaf07e953cfc0a3a5240a155d6e4daa965bb"
|
||||||
)
|
)
|
||||||
|
@ -315,7 +315,8 @@ def test_repo_key_detect_does_not_raise_integrity_error(getpass, monkeypatch):
|
||||||
This is a regression test for a bug I introduced and fixed:
|
This is a regression test for a bug I introduced and fixed:
|
||||||
|
|
||||||
Traceback (most recent call last):
|
Traceback (most recent call last):
|
||||||
File "/home/user/borg-master/src/borg/testsuite/crypto.py", line 384, in test_repo_key_detect_does_not_raise_integrity_error
|
File "/home/user/borg-master/src/borg/testsuite/crypto.py", line 384,
|
||||||
|
in test_repo_key_detect_does_not_raise_integrity_error
|
||||||
RepoKey.detect(repository, manifest_data=None)
|
RepoKey.detect(repository, manifest_data=None)
|
||||||
File "/home/user/borg-master/src/borg/crypto/key.py", line 402, in detect
|
File "/home/user/borg-master/src/borg/crypto/key.py", line 402, in detect
|
||||||
if not key.load(target, passphrase):
|
if not key.load(target, passphrase):
|
||||||
|
@ -335,7 +336,8 @@ def test_repo_key_detect_does_not_raise_integrity_error(getpass, monkeypatch):
|
||||||
|
|
||||||
1. FlexiKey.decrypt_key_file() is supposed to signal the decryption failure by returning None
|
1. FlexiKey.decrypt_key_file() is supposed to signal the decryption failure by returning None
|
||||||
2. FlexiKey.detect() relies on that interface - it tries an empty passphrase before prompting the user
|
2. FlexiKey.detect() relies on that interface - it tries an empty passphrase before prompting the user
|
||||||
3. my initial implementation of decrypt_key_file_argon2() was simply passing through the IntegrityError() from AES256_CTR_BASE.decrypt()
|
3. my initial implementation of decrypt_key_file_argon2() was simply passing through the IntegrityError()
|
||||||
|
from AES256_CTR_BASE.decrypt()
|
||||||
"""
|
"""
|
||||||
repository = MagicMock(id=b"repository_id")
|
repository = MagicMock(id=b"repository_id")
|
||||||
getpass.return_value = "hello, pass phrase"
|
getpass.return_value = "hello, pass phrase"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from ..crypto.file_integrity import IntegrityCheckedFile, DetachedIntegrityCheckedFile, FileIntegrityError
|
from ..crypto.file_integrity import DetachedIntegrityCheckedFile, FileIntegrityError
|
||||||
|
|
||||||
|
|
||||||
class TestReadIntegrityFile:
|
class TestReadIntegrityFile:
|
||||||
|
|
|
@ -8,7 +8,7 @@ import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
from ..hashindex import NSIndex, ChunkIndex, ChunkIndexEntry
|
from ..hashindex import NSIndex, ChunkIndex
|
||||||
from ..crypto.file_integrity import IntegrityCheckedFile, FileIntegrityError
|
from ..crypto.file_integrity import IntegrityCheckedFile, FileIntegrityError
|
||||||
from . import BaseTestCase, unopened_tempfile
|
from . import BaseTestCase, unopened_tempfile
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ from ..helpers import eval_escapes
|
||||||
from ..helpers import safe_unlink
|
from ..helpers import safe_unlink
|
||||||
from ..helpers import text_to_json, binary_to_json
|
from ..helpers import text_to_json, binary_to_json
|
||||||
from ..helpers.passphrase import Passphrase, PasswordRetriesExceeded
|
from ..helpers.passphrase import Passphrase, PasswordRetriesExceeded
|
||||||
from ..platform import is_cygwin, is_win32, is_darwin, swidth
|
from ..platform import is_cygwin, is_win32, is_darwin
|
||||||
|
|
||||||
from . import BaseTestCase, FakeInputs, are_hardlinks_supported
|
from . import BaseTestCase, FakeInputs, are_hardlinks_supported
|
||||||
from . import rejected_dotdot_paths
|
from . import rejected_dotdot_paths
|
||||||
|
@ -178,11 +178,13 @@ class TestLocationWithoutEnv:
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]/some/path"))
|
repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]/some/path"))
|
||||||
== "Location(proto='ssh', user='user', host='2a02:0001:0002:0003:0004:0005:0006:0007', port=None, path='/some/path')"
|
== "Location(proto='ssh', user='user', "
|
||||||
|
"host='2a02:0001:0002:0003:0004:0005:0006:0007', port=None, path='/some/path')"
|
||||||
)
|
)
|
||||||
assert (
|
assert (
|
||||||
repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]:1234/some/path"))
|
repr(Location("ssh://user@[2a02:0001:0002:0003:0004:0005:0006:0007]:1234/some/path"))
|
||||||
== "Location(proto='ssh', user='user', host='2a02:0001:0002:0003:0004:0005:0006:0007', port=1234, path='/some/path')"
|
== "Location(proto='ssh', user='user', "
|
||||||
|
"host='2a02:0001:0002:0003:0004:0005:0006:0007', port=1234, path='/some/path')"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_socket(self, monkeypatch, keys_dir):
|
def test_socket(self, monkeypatch, keys_dir):
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import re
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from binascii import hexlify, unhexlify, a2b_base64
|
from binascii import hexlify, unhexlify, a2b_base64
|
||||||
from unittest.mock import MagicMock
|
from unittest.mock import MagicMock
|
||||||
|
|
|
@ -148,28 +148,28 @@ class TestExclusiveLock:
|
||||||
while not timer.timed_out():
|
while not timer.timed_out():
|
||||||
cycle += 1
|
cycle += 1
|
||||||
try:
|
try:
|
||||||
with ExclusiveLock(
|
# This timeout is only for not exceeding the given timeout by more than 5%.
|
||||||
lockpath, id=id, timeout=timeout / 20, sleep=-1
|
# With sleep<0 it's constantly polling anyway.
|
||||||
): # This timeout is only for not exceeding the given timeout by more than 5%. With sleep<0 it's constantly polling anyway.
|
with ExclusiveLock(lockpath, id=id, timeout=timeout / 20, sleep=-1):
|
||||||
lock_owner_count = lock_owner_counter.incr()
|
lock_owner_count = lock_owner_counter.incr()
|
||||||
print_locked(
|
print_locked(
|
||||||
"Thread %2d: Acquired the lock. It's my %d. loop cycle. I am the %d. who has the lock concurrently."
|
"Thread %2d: Acquired the lock. It's my %d. loop cycle. "
|
||||||
% (thread_id, cycle, lock_owner_count)
|
"I am the %d. who has the lock concurrently." % (thread_id, cycle, lock_owner_count)
|
||||||
)
|
)
|
||||||
time.sleep(0.005)
|
time.sleep(0.005)
|
||||||
lock_owner_count = lock_owner_counter.decr()
|
lock_owner_count = lock_owner_counter.decr()
|
||||||
print_locked(
|
print_locked(
|
||||||
"Thread %2d: Releasing the lock, finishing my %d. loop cycle. Currently, %d colleagues still have the lock."
|
"Thread %2d: Releasing the lock, finishing my %d. loop cycle. "
|
||||||
% (thread_id, cycle, lock_owner_count)
|
"Currently, %d colleagues still have the lock." % (thread_id, cycle, lock_owner_count)
|
||||||
)
|
)
|
||||||
except LockTimeout:
|
except LockTimeout:
|
||||||
print_locked("Thread %2d: Got LockTimeout, finishing my %d. loop cycle." % (thread_id, cycle))
|
print_locked("Thread %2d: Got LockTimeout, finishing my %d. loop cycle." % (thread_id, cycle))
|
||||||
except:
|
except: # noqa
|
||||||
exception_count = exception_counter.incr()
|
exception_count = exception_counter.incr()
|
||||||
e = format_exc()
|
e = format_exc()
|
||||||
print_locked(
|
print_locked(
|
||||||
"Thread %2d: Exception thrown, finishing my %d. loop cycle. It's the %d. exception seen until now: %s"
|
"Thread %2d: Exception thrown, finishing my %d. loop cycle. "
|
||||||
% (thread_id, cycle, exception_count, e)
|
"It's the %d. exception seen until now: %s" % (thread_id, cycle, exception_count, e)
|
||||||
)
|
)
|
||||||
|
|
||||||
print_locked("Thread %2d: Loop timed out--terminating after %d loop cycles." % (thread_id, cycle))
|
print_locked("Thread %2d: Loop timed out--terminating after %d loop cycles." % (thread_id, cycle))
|
||||||
|
|
|
@ -5,11 +5,11 @@ import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from ..platformflags import is_win32, is_linux, is_freebsd, is_darwin
|
from ..platformflags import is_win32
|
||||||
from ..platform import acl_get, acl_set, swidth
|
from ..platform import acl_get, acl_set, swidth
|
||||||
from ..platform import get_process_id, process_alive
|
from ..platform import get_process_id, process_alive
|
||||||
from . import BaseTestCase, unopened_tempfile
|
from . import BaseTestCase, unopened_tempfile
|
||||||
from .locking import free_pid
|
from .locking import free_pid # NOQA
|
||||||
|
|
||||||
|
|
||||||
ACCESS_ACL = """
|
ACCESS_ACL = """
|
||||||
|
@ -186,7 +186,9 @@ class PlatformDarwinTestCase(BaseTestCase):
|
||||||
self.assert_equal(self.get_acl(file.name), {})
|
self.assert_equal(self.get_acl(file.name), {})
|
||||||
self.set_acl(
|
self.set_acl(
|
||||||
file.name,
|
file.name,
|
||||||
b"!#acl 1\ngroup:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\nuser:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
|
b"!#acl 1\n"
|
||||||
|
b"group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\n"
|
||||||
|
b"user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
|
||||||
numeric_ids=False,
|
numeric_ids=False,
|
||||||
)
|
)
|
||||||
self.assert_in(
|
self.assert_in(
|
||||||
|
@ -197,7 +199,9 @@ class PlatformDarwinTestCase(BaseTestCase):
|
||||||
)
|
)
|
||||||
self.set_acl(
|
self.set_acl(
|
||||||
file2.name,
|
file2.name,
|
||||||
b"!#acl 1\ngroup:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\nuser:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
|
b"!#acl 1\n"
|
||||||
|
b"group:ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000000:staff:0:allow:read\n"
|
||||||
|
b"user:FFFFEEEE-DDDD-CCCC-BBBB-AAAA00000000:root:0:allow:read\n",
|
||||||
numeric_ids=True,
|
numeric_ids=True,
|
||||||
)
|
)
|
||||||
self.assert_in(
|
self.assert_in(
|
||||||
|
|
Loading…
Reference in New Issue