Răsfoiți Sursa

remove posix issues and fixup for unsupported methodes

Emmo Emminghaus 6 ani în urmă
părinte
comite
558ca61d20

+ 32 - 29
src/borg/archive.py

@@ -680,43 +680,46 @@ Utilization of max. archive size: {csize_max:.0%}
         gid = item.gid if gid is None else gid
         # This code is a bit of a mess due to os specific differences
         try:
+            try:
+                if fd:
+                    os.fchown(fd, uid, gid)
+                else:
+                    os.chown(path, uid, gid, follow_symlinks=False)
+            except OSError:
+                pass
             if fd:
-                os.fchown(fd, uid, gid)
+                os.fchmod(fd, item.mode)
+            elif not symlink:
+                os.chmod(path, item.mode)
+            elif has_lchmod:  # Not available on Linux
+                os.lchmod(path, item.mode)
+            mtime = item.mtime
+            if 'atime' in item:
+                atime = item.atime
             else:
-                os.chown(path, uid, gid, follow_symlinks=False)
-        except OSError:
-            pass
-        if fd:
-            os.fchmod(fd, item.mode)
-        elif not symlink:
-            os.chmod(path, item.mode)
-        elif has_lchmod:  # Not available on Linux
-            os.lchmod(path, item.mode)
-        mtime = item.mtime
-        if 'atime' in item:
-            atime = item.atime
-        else:
-            # old archives only had mtime in item metadata
-            atime = mtime
-        if 'birthtime' in item:
-            birthtime = item.birthtime
+                # old archives only had mtime in item metadata
+                atime = mtime
+            if 'birthtime' in item:
+                birthtime = item.birthtime
+                try:
+                    # This should work on FreeBSD, NetBSD, and Darwin and be harmless on other platforms.
+                    # See utimes(2) on either of the BSDs for details.
+                    if fd:
+                        os.utime(fd, None, ns=(atime, birthtime))
+                    else:
+                        os.utime(path, None, ns=(atime, birthtime), follow_symlinks=False)
+                except OSError:
+                    # some systems don't support calling utime on a symlink
+                    pass
             try:
-                # This should work on FreeBSD, NetBSD, and Darwin and be harmless on other platforms.
-                # See utimes(2) on either of the BSDs for details.
                 if fd:
-                    os.utime(fd, None, ns=(atime, birthtime))
+                    os.utime(fd, None, ns=(atime, mtime))
                 else:
-                    os.utime(path, None, ns=(atime, birthtime), follow_symlinks=False)
+                    os.utime(path, None, ns=(atime, mtime), follow_symlinks=False)
             except OSError:
                 # some systems don't support calling utime on a symlink
                 pass
-        try:
-            if fd:
-                os.utime(fd, None, ns=(atime, mtime))
-            else:
-                os.utime(path, None, ns=(atime, mtime), follow_symlinks=False)
-        except OSError:
-            # some systems don't support calling utime on a symlink
+        except AttributeError:
             pass
         acl_set(path, item, self.numeric_owner, fd=fd)
         # chown removes Linux capabilities, so set the extended attributes at the end, after chown, since they include

+ 7 - 1
src/borg/helpers/checks.py

@@ -1,4 +1,5 @@
 import os
+import sys
 
 from .errors import Error
 
@@ -8,9 +9,14 @@ class PythonLibcTooOld(Error):
 
 
 def check_python():
-    required_funcs = {os.stat, os.utime, os.chown}
+    if sys.platform.startswith(('win32', )):
+        required_funcs = {os.stat}
+    else:
+        required_funcs = {os.stat, os.utime, os.chown}
     if not os.supports_follow_symlinks.issuperset(required_funcs):
         raise PythonLibcTooOld
+    pass
+
 
 
 class ExtensionModuleError(Error):

+ 1 - 0
src/borg/platform/__init__.py

@@ -19,6 +19,7 @@ if not sys.platform.startswith(('win32', )):
     from .posix import process_alive, local_pid_alive
     # posix swidth implementation works for: linux, freebsd, darwin, openindiana, cygwin
     from .posix import swidth
+    from .posix import get_errno
     from .posix import uid2user, user2uid, gid2group, group2gid, getosusername
 
 if sys.platform.startswith('linux'):  # pragma: linux only

+ 1 - 2
src/borg/platform/xattr.py

@@ -1,8 +1,6 @@
 import errno
 import os
 
-from .posix import get_errno
-
 from ..helpers import Buffer
 
 
@@ -39,6 +37,7 @@ class BufferTooSmallError(Exception):
 
 
 def _check(rv, path=None, detect_buffer_too_small=False):
+    from . import get_errno # circular reference if imported at global level!
     if rv < 0:
         e = get_errno()
         if detect_buffer_too_small and e == errno.ERANGE:

+ 4 - 0
src/borg/repository.py

@@ -652,6 +652,10 @@ class Repository:
         except OSError as os_error:
             logger.warning('Failed to check free space before committing: ' + str(os_error))
             return
+        except AttributeError:
+            # TODO move the call to statvfs to platform
+            logger.warning('Failed to check free space before committing: no statvfs method available' ) 
+            return
         # f_bavail: even as root - don't touch the Federal Block Reserve!
         free_space = st_vfs.f_bavail * st_vfs.f_bsize
         logger.debug('check_free_space: required bytes {}, free bytes {}'.format(required_free_space, free_space))

+ 14 - 3
src/borg/testsuite/__init__.py

@@ -2,7 +2,11 @@ from contextlib import contextmanager
 import filecmp
 import functools
 import os
-import posix
+try:
+    import posix # buildin but not everywhere
+except:
+    posix = None
+
 import stat
 import sys
 import sysconfig
@@ -44,7 +48,7 @@ except ImportError:
     has_llfuse = False
 
 # The mtime get/set precision varies on different OS and Python versions
-if 'HAVE_FUTIMENS' in getattr(posix, '_have_functions', []):
+if posix != None and 'HAVE_FUTIMENS' in getattr(posix, '_have_functions', []):
     st_mtime_ns_round = 0
 elif 'HAVE_UTIMES' in sysconfig.get_config_vars():
     st_mtime_ns_round = -6
@@ -95,7 +99,10 @@ def are_fifos_supported():
             os.mkfifo(filepath)
             return True
         except OSError:
-            return False
+            pass
+        except NotImplementedError:
+            pass
+        return False
 
 
 @functools.lru_cache()
@@ -113,6 +120,8 @@ def is_utime_fully_supported():
                 return True
         except OSError:
             pass
+        except NotImplementedError:
+            pass
         return False
 
 
@@ -135,6 +144,8 @@ def is_birthtime_fully_supported():
                 return True
         except OSError:
             pass
+        except NotImplementedError:
+            pass
         return False
 
 

+ 31 - 30
src/borg/testsuite/hashindex.py

@@ -8,7 +8,7 @@ import zlib
 from ..hashindex import NSIndex, ChunkIndex, ChunkIndexEntry
 from .. import hashindex
 from ..crypto.file_integrity import IntegrityCheckedFile, FileIntegrityError
-from . import BaseTestCase
+from . import BaseTestCase, unopened_tempfile
 
 # Note: these tests are part of the self test, do not use or import py.test functionality here.
 #       See borg.selftest for details. If you add/remove test methods, update SELFTEST_COUNT
@@ -55,21 +55,22 @@ class HashIndexTestCase(BaseTestCase):
             self.assert_raises(KeyError, idx.__delitem__, H(x))
         self.assert_equal(len(idx), 50)
         idx_name = tempfile.NamedTemporaryFile()
-        idx.write(idx_name.name)
-        del idx
-        # Verify file contents
-        with open(idx_name.name, 'rb') as fd:
-            self.assert_equal(hashlib.sha256(fd.read()).hexdigest(), sha)
-        # Make sure we can open the file
-        idx = cls.read(idx_name.name)
-        self.assert_equal(len(idx), 50)
-        for x in range(50, 100):
-            self.assert_equal(idx[H(x)], make_value(x * 2))
-        idx.clear()
-        self.assert_equal(len(idx), 0)
-        idx.write(idx_name.name)
-        del idx
-        self.assert_equal(len(cls.read(idx_name.name)), 0)
+        with unopened_tempfile() as filepath:
+            idx.write(filepath)
+            del idx
+            # Verify file contents
+            with open(filepath, 'rb') as fd:
+                self.assert_equal(hashlib.sha256(fd.read()).hexdigest(), sha)
+            # Make sure we can open the file
+            idx = cls.read(filepath)
+            self.assert_equal(len(idx), 50)
+            for x in range(50, 100):
+                self.assert_equal(idx[H(x)], make_value(x * 2))
+            idx.clear()
+            self.assert_equal(len(idx), 0)
+            idx.write(filepath)
+            del idx
+            self.assert_equal(len(cls.read(filepath)), 0)
 
     def test_nsindex(self):
         self._generic_test(NSIndex, lambda x: (x, x),
@@ -81,20 +82,20 @@ class HashIndexTestCase(BaseTestCase):
 
     def test_resize(self):
         n = 2000  # Must be >= MIN_BUCKETS
-        idx_name = tempfile.NamedTemporaryFile()
-        idx = NSIndex()
-        idx.write(idx_name.name)
-        initial_size = os.path.getsize(idx_name.name)
-        self.assert_equal(len(idx), 0)
-        for x in range(n):
-            idx[H(x)] = x, x
-        idx.write(idx_name.name)
-        self.assert_true(initial_size < os.path.getsize(idx_name.name))
-        for x in range(n):
-            del idx[H(x)]
-        self.assert_equal(len(idx), 0)
-        idx.write(idx_name.name)
-        self.assert_equal(initial_size, os.path.getsize(idx_name.name))
+        with unopened_tempfile() as filepath:
+            idx = NSIndex()
+            idx.write(filepath)
+            initial_size = os.path.getsize(filepath)
+            self.assert_equal(len(idx), 0)
+            for x in range(n):
+                idx[H(x)] = x, x
+            idx.write(filepath)
+            self.assert_true(initial_size < os.path.getsize(filepath))
+            for x in range(n):
+                del idx[H(x)]
+            self.assert_equal(len(idx), 0)
+            idx.write(filepath)
+            self.assert_equal(initial_size, os.path.getsize(filepath))
 
     def test_iteritems(self):
         idx = NSIndex()

+ 1 - 1
src/borg/testsuite/platform.py

@@ -4,7 +4,6 @@ import random
 import shutil
 import sys
 import tempfile
-import pwd
 import unittest
 
 from ..platform import acl_get, acl_set, swidth
@@ -44,6 +43,7 @@ def fakeroot_detected():
 
 def user_exists(username):
     try:
+        import pwd # buildin but not on all OS
         pwd.getpwnam(username)
         return True
     except (KeyError, ValueError):