Browse Source

Merge branch '1.0-maint' into master

# Conflicts:
#	src/borg/archive.py
#	src/borg/archiver.py
#	src/borg/helpers.py
Marian Beermann 8 năm trước cách đây
mục cha
commit
a9db2a2e55
7 tập tin đã thay đổi với 32 bổ sung12 xóa
  1. 1 0
      README.rst
  2. 1 1
      conftest.py
  3. 3 0
      docs/changes.rst
  4. 10 1
      docs/installation.rst
  5. 12 6
      src/borg/archive.py
  6. 3 3
      src/borg/archiver.py
  7. 2 1
      src/borg/testsuite/archiver.py

+ 1 - 0
README.rst

@@ -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

+ 1 - 1
conftest.py

@@ -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
 

+ 3 - 0
docs/changes.rst

@@ -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:
 

+ 10 - 1
docs/installation.rst

@@ -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::
 

+ 12 - 6
src/borg/archive.py

@@ -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,

+ 3 - 3
src/borg/archiver.py

@@ -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:

+ 2 - 1
src/borg/testsuite/archiver.py

@@ -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