Merge branch '1.0-maint' into master

# Conflicts:
#	src/borg/archive.py
#	src/borg/archiver.py
#	src/borg/helpers.py
This commit is contained in:
Marian Beermann 2016-12-17 13:26:28 +01:00
commit a9db2a2e55
7 changed files with 32 additions and 12 deletions

View File

@ -75,6 +75,7 @@ Main features
* FreeBSD
* OpenBSD and NetBSD (no xattrs/ACLs support or binaries yet)
* Cygwin (not supported, no binaries yet)
* Linux Subsystem of Windows 10 (not supported)
**Free and Open Source Software**
* security and functionality can be audited independently

View File

@ -3,7 +3,7 @@ import os
import pytest
# needed to get pretty assertion failures in unit tests:
pytest.register_assert_rewrite('borg')
pytest.register_assert_rewrite('borg.testsuite')
from borg.logger import setup_logging

View File

@ -82,6 +82,9 @@ Bug fixes:
- skip corrupted chunks during manifest rebuild
- fix TypeError in integrity error handler, #1903, #1894
- fix location parser for archives with @ char (regression introduced in 1.0.8), #1930
- fix wrong duration/timestamps if system clock jumped during a create
- fix progress display not updating if system clock jumps backwards
- fix checkpoint interval being incorrect if system clock jumps
Other changes:

View File

@ -290,12 +290,21 @@ and commands to make fuse work for using the mount command.
sysctl vfs.usermount=1
Windows 10's Linux Subsystem
++++++++++++++++++++++++++++
.. note::
Running under Windows 10's Linux Subsystem is experimental and has not been tested much yet.
Just follow the Ubuntu Linux installation steps. You can omit the FUSE stuff, it won't work anyway.
Cygwin
++++++
.. note::
Running under Cygwin is experimental and has only been tested with Cygwin
(x86-64) v2.5.2.
(x86-64) v2.5.2. Remote repositories are known broken, local repositories should work.
Use the Cygwin installer to install the dependencies::

View File

@ -5,7 +5,7 @@ import stat
import sys
import time
from contextlib import contextmanager
from datetime import datetime, timezone
from datetime import datetime, timezone, timedelta
from functools import partial
from getpass import getuser
from io import BytesIO
@ -81,7 +81,7 @@ class Statistics:
return format_file_size(self.csize)
def show_progress(self, item=None, final=False, stream=None, dt=None):
now = time.time()
now = time.monotonic()
if dt is None or now - self.last_progress > dt:
self.last_progress = now
columns, lines = get_terminal_size()
@ -255,7 +255,7 @@ class Archive:
def __init__(self, repository, key, manifest, name, cache=None, create=False,
checkpoint_interval=300, numeric_owner=False, noatime=False, noctime=False, progress=False,
chunker_params=CHUNKER_PARAMS, start=None, end=None, compression=None, compression_files=None,
chunker_params=CHUNKER_PARAMS, start=None, start_monotonic=None, end=None, compression=None, compression_files=None,
consider_part_files=False):
self.cwd = os.getcwd()
self.key = key
@ -270,10 +270,13 @@ class Archive:
self.numeric_owner = numeric_owner
self.noatime = noatime
self.noctime = noctime
assert (start is None) == (start_monotonic is None), 'Logic error: if start is given, start_monotonic must be given as well and vice versa.'
if start is None:
start = datetime.utcnow()
start_monotonic = time.monotonic()
self.chunker_params = chunker_params
self.start = start
self.start_monotonic = start_monotonic
if end is None:
end = datetime.utcnow()
self.end = end
@ -288,7 +291,7 @@ class Archive:
key.compression_decider2 = CompressionDecider2(compression or CompressionSpec('none'))
if name in manifest.archives:
raise self.AlreadyExists(name)
self.last_checkpoint = time.time()
self.last_checkpoint = time.monotonic()
i = 0
while True:
self.checkpoint_name = '%s.checkpoint%s' % (name, i and ('.%d' % i) or '')
@ -381,14 +384,17 @@ Number of files: {0.stats.nfiles}'''.format(
if name in self.manifest.archives:
raise self.AlreadyExists(name)
self.items_buffer.flush(flush=True)
duration = timedelta(seconds=time.monotonic() - self.start_monotonic)
if timestamp is None:
self.end = datetime.utcnow()
self.start = self.end - duration
start = self.start
end = self.end
else:
self.end = timestamp
start = timestamp
end = timestamp # we only have 1 value
self.start = timestamp - duration
end = timestamp
start = self.start
metadata = {
'version': 1,
'name': name,

View File

@ -12,11 +12,11 @@ import stat
import subprocess
import sys
import textwrap
import time
import traceback
from binascii import unhexlify
from datetime import datetime
from itertools import zip_longest
from operator import attrgetter
from .logger import create_logger, setup_logging
logger = create_logger()
@ -327,7 +327,6 @@ class Archiver:
if args.progress:
archive.stats.show_progress(final=True)
if args.stats:
archive.end = datetime.utcnow()
log_multi(DASHES,
str(archive),
DASHES,
@ -341,6 +340,7 @@ class Archiver:
self.ignore_inode = args.ignore_inode
dry_run = args.dry_run
t0 = datetime.utcnow()
t0_monotonic = time.monotonic()
if not dry_run:
with Cache(repository, key, manifest, do_files=args.cache_files, progress=args.progress,
lock_wait=self.lock_wait) as cache:
@ -348,7 +348,7 @@ class Archiver:
create=True, checkpoint_interval=args.checkpoint_interval,
numeric_owner=args.numeric_owner, noatime=args.noatime, noctime=args.noctime,
progress=args.progress,
chunker_params=args.chunker_params, start=t0,
chunker_params=args.chunker_params, start=t0, start_monotonic=t0_monotonic,
compression=args.compression, compression_files=args.compression_files)
create_inner(archive, cache)
else:

View File

@ -328,7 +328,8 @@ class ArchiverTestCaseBase(BaseTestCase):
except PermissionError:
have_root = False
except OSError as e:
if e.errno != errno.EINVAL:
# Note: ENOSYS "Function not implemented" happens as non-root on Win 10 Linux Subsystem.
if e.errno not in (errno.EINVAL, errno.ENOSYS):
raise
have_root = False
return have_root