Repository: borgbackup/borg

Issue:
osx: permissionerror in hardlink fuse mount tests
```
    darwin64:     def test_mount_hardlinks(self):
    darwin64:         self._extract_hardlinks_setup()
    darwin64:         mountpoint = os.path.join(self.tmpdir, 'mountpoint')
    darwin64:         with self.fuse_mount(self.repository_location + '::test', mountpoint, '--strip-components=2'), \
    darwin64:              changedir(mountpoint):
    darwin64:             assert os.stat('hardlink').st_nlink == 2
    darwin64: >           assert os.stat('subdir/hardlink').st_nlink == 2
    darwin64: E           PermissionError: [Errno 13] Permission denied: 'subdir/hardlink'
    darwin64: .tox/py34/lib/python3.4/site-packages/borg/testsuite/archiver.py:787: PermissionError
```


Discussion:
likely related to fakeroot, could not reproduce without.

thus removing this from release milestone. still would be good to make the test work not fail on OS X (only).
The initally reported error could be reproduced using following config:

- OS X 10.11.6
- FUSE for macOS 3.8.2
- python==3.6.3
- borgbackup==1.2.0


**Observations**
Running _fakeroot -u tox -e py36 -- -s borg.testsuite.archiver::ArchiverTestCase_
raises the PermissionError for _test_mount_hardlinks_ if other test cases of this class (ArchiverTestCase) are run before.

In this case the PermissionError is caused by the fact that 'subdir' is owned by root (permissions: "rwx"); groups and others have no permissions.

It seemed that calling _self.cmd_ in a previous test case influences the result of _test_mount_hardlinks_ 

**Note**
Running _tox -e py36 -- -s borg.testsuite.archiver::ArchiverTestCase_ was fine without any errors.
looks like yet another fakeroot issue.

maybe i should get rid of fakeroot in the vagrant machines also (as i already did on travis-ci).
doesn't help for normal use-fakeroot-not-real-root testing on a development machine though.
as these failures now also showed up on linux, after adding "default_permissions" to the enforced mount options, it became clear how to work around these issues caused by fakeroot: by ignoring permissions.

Resolving patch:
diff --git a/src/borg/testsuite/archiver.py b/src/borg/testsuite/archiver.py
--- a/src/borg/testsuite/archiver.py
+++ b/src/borg/testsuite/archiver.py
@@ -793,21 +793,28 @@ def _extract_hardlinks_setup(self):
     def test_mount_hardlinks(self):
         self._extract_hardlinks_setup()
         mountpoint = os.path.join(self.tmpdir, 'mountpoint')
-        with self.fuse_mount(self.repository_location + '::test', mountpoint, '--strip-components=2'), \
+        # we need to get rid of permissions checking because fakeroot causes issues with it.
+        # On all platforms, borg defaults to "default_permissions" and we need to get rid of it via "ignore_permissions".
+        # On macOS (darwin), we additionally need "defer_permissions" to switch off the checks in osxfuse.
+        if sys.platform == 'darwin':
+            ignore_perms = ['-o', 'ignore_permissions,defer_permissions']
+        else:
+            ignore_perms = ['-o', 'ignore_permissions']
+        with self.fuse_mount(self.repository_location + '::test', mountpoint, '--strip-components=2', *ignore_perms), \
              changedir(mountpoint):
             assert os.stat('hardlink').st_nlink == 2
             assert os.stat('subdir/hardlink').st_nlink == 2
             assert open('subdir/hardlink', 'rb').read() == b'123456'
             assert os.stat('aaaa').st_nlink == 2
             assert os.stat('source2').st_nlink == 2
-        with self.fuse_mount(self.repository_location + '::test', mountpoint, 'input/dir1'), \
+        with self.fuse_mount(self.repository_location + '::test', mountpoint, 'input/dir1', *ignore_perms), \
              changedir(mountpoint):
             assert os.stat('input/dir1/hardlink').st_nlink == 2
             assert os.stat('input/dir1/subdir/hardlink').st_nlink == 2
             assert open('input/dir1/subdir/hardlink', 'rb').read() == b'123456'
             assert os.stat('input/dir1/aaaa').st_nlink == 2
             assert os.stat('input/dir1/source2').st_nlink == 2
-        with self.fuse_mount(self.repository_location + '::test', mountpoint), \
+        with self.fuse_mount(self.repository_location + '::test', mountpoint, *ignore_perms), \
              changedir(mountpoint):
             assert os.stat('input/source').st_nlink == 4
             assert os.stat('input/abba').st_nlink == 4


Test patch: