2
0
Antti Aalto 9 жил өмнө
parent
commit
bbd7bd85ac

+ 1 - 1
src/borg/archive.py

@@ -389,7 +389,7 @@ Number of files: {0.stats.nfiles}'''.format(
 
 
         original_path = original_path or item[b'path']
         original_path = original_path or item[b'path']
         dest = self.cwd
         dest = self.cwd
-        if item[b'path'].startswith('/') or item[b'path'].startswith('..') or (sys.platform == 'win32' and item[b'path'][1] == ':'):
+        if item[b'path'].startswith('/') or item[b'path'].startswith('..') or (sys.platform == 'win32' and len(item[b'path']) > 1 and item[b'path'][1] == ':'):
             raise Exception('Path should be relative and local')
             raise Exception('Path should be relative and local')
         path = os.path.join(dest, item[b'path'])
         path = os.path.join(dest, item[b'path'])
         # Attempt to remove existing files, ignore errors on failure
         # Attempt to remove existing files, ignore errors on failure

+ 15 - 6
src/borg/helpers.py

@@ -369,11 +369,17 @@ class FnmatchPattern(PatternBase):
     PREFIX = "fm"
     PREFIX = "fm"
 
 
     def _prepare(self, pattern):
     def _prepare(self, pattern):
-        if pattern.endswith(os.path.sep):
-            pattern = os.path.normpath(pattern).rstrip(os.path.sep) + os.path.sep + '*' + os.path.sep
+        if sys.platform != 'win32':
+            if pattern.endswith(os.path.sep):
+                pattern = os.path.normpath(pattern).rstrip(os.path.sep) + os.path.sep + '*' + os.path.sep
+            else:
+                pattern = os.path.normpath(pattern) + os.path.sep + '*'
         else:
         else:
-            pattern = os.path.normpath(pattern) + os.path.sep + '*'
-
+            if pattern.endswith(os.path.sep) or pattern.endswith(posixpath.sep):
+                pattern = posixpath.normpath(pattern).rstrip(posixpath.sep) + posixpath.sep + '*' + posixpath.sep
+            else:
+                pattern = posixpath.normpath(pattern) + posixpath.sep + '*'
+        
         self.pattern = pattern
         self.pattern = pattern
 
 
         # fnmatch and re.match both cache compiled regular expressions.
         # fnmatch and re.match both cache compiled regular expressions.
@@ -381,7 +387,10 @@ class FnmatchPattern(PatternBase):
         self.regex = re.compile(translate(self.pattern))
         self.regex = re.compile(translate(self.pattern))
 
 
     def _match(self, path):
     def _match(self, path):
-        return (self.regex.match(path + os.path.sep) is not None)
+        if sys.platform != 'win32':
+            return (self.regex.match(path + os.path.sep) is not None)
+        else:
+            return (self.regex.match(path.replace('\\', '/') + posixpath.sep) is not None)
 
 
 
 
 class ShellPattern(PatternBase):
 class ShellPattern(PatternBase):
@@ -802,7 +811,7 @@ class Location:
         if sys.platform == 'win32':
         if sys.platform == 'win32':
             m = self.file_re.match(text)
             m = self.file_re.match(text)
             if m:
             if m:
-                self.proto = m.group('proto')
+                self.proto = 'file'
                 self.path = posixpath.normpath(m.group('drive') + ":\\" + m.group('path'))
                 self.path = posixpath.normpath(m.group('drive') + ":\\" + m.group('path'))
                 self.archive = m.group('archive')
                 self.archive = m.group('archive')
                 return True
                 return True

+ 1 - 2
src/borg/platform/windows.pyx

@@ -192,8 +192,7 @@ cdef sid2string(PSID sid):
 
 
 
 
 def get_owner(path):
 def get_owner(path):
-    cdef int request = OWNER_SECURITY_INFORMATION
-    cdef BYTE* sd = _get_file_security(path, request)
+    cdef BYTE* sd = _get_file_security(path, OWNER_SECURITY_INFORMATION)
     if sd == NULL:
     if sd == NULL:
         return 'unknown', 'S-1-0-0'
         return 'unknown', 'S-1-0-0'
     cdef PSID sid = _get_security_descriptor_owner(sd)
     cdef PSID sid = _get_security_descriptor_owner(sd)

+ 44 - 20
src/borg/testsuite/archiver.py

@@ -205,6 +205,8 @@ class ArchiverTestCaseBase(BaseTestCase):
         self.tmpdir = tempfile.mkdtemp()
         self.tmpdir = tempfile.mkdtemp()
         self.repository_path = os.path.join(self.tmpdir, 'repository')
         self.repository_path = os.path.join(self.tmpdir, 'repository')
         self.repository_location = self.prefix + self.repository_path
         self.repository_location = self.prefix + self.repository_path
+        if sys.platform == 'win32':
+            self.repository_location = self.repository_path
         self.input_path = os.path.join(self.tmpdir, 'input')
         self.input_path = os.path.join(self.tmpdir, 'input')
         self.output_path = os.path.join(self.tmpdir, 'output')
         self.output_path = os.path.join(self.tmpdir, 'output')
         self.keys_path = os.path.join(self.tmpdir, 'keys')
         self.keys_path = os.path.join(self.tmpdir, 'keys')
@@ -269,7 +271,8 @@ class ArchiverTestCaseBase(BaseTestCase):
         os.link(os.path.join(self.input_path, 'file1'),
         os.link(os.path.join(self.input_path, 'file1'),
                 os.path.join(self.input_path, 'hardlink'))
                 os.path.join(self.input_path, 'hardlink'))
         # Symlink
         # Symlink
-        os.symlink('somewhere', os.path.join(self.input_path, 'link1'))
+        if sys.platform != 'win32':
+            os.symlink('somewhere', os.path.join(self.input_path, 'link1'))
         if xattr.is_enabled(self.input_path):
         if xattr.is_enabled(self.input_path):
             xattr.setxattr(os.path.join(self.input_path, 'file1'), 'user.foo', b'bar')
             xattr.setxattr(os.path.join(self.input_path, 'file1'), 'user.foo', b'bar')
             # XXX this always fails for me
             # XXX this always fails for me
@@ -279,22 +282,25 @@ class ArchiverTestCaseBase(BaseTestCase):
             # so that the test setup for all tests using it does not fail here always for others.
             # so that the test setup for all tests using it does not fail here always for others.
             # xattr.setxattr(os.path.join(self.input_path, 'link1'), 'user.foo_symlink', b'bar_symlink', follow_symlinks=False)
             # xattr.setxattr(os.path.join(self.input_path, 'link1'), 'user.foo_symlink', b'bar_symlink', follow_symlinks=False)
         # FIFO node
         # FIFO node
-        os.mkfifo(os.path.join(self.input_path, 'fifo1'))
-        if has_lchflags:
-            platform.set_flags(os.path.join(self.input_path, 'flagfile'), stat.UF_NODUMP)
-        try:
-            # Block device
-            os.mknod('input/bdev', 0o600 | stat.S_IFBLK, os.makedev(10, 20))
-            # Char device
-            os.mknod('input/cdev', 0o600 | stat.S_IFCHR, os.makedev(30, 40))
-            # File mode
-            os.chmod('input/dir2', 0o555)  # if we take away write perms, we need root to remove contents
-            # File owner
-            os.chown('input/file1', 100, 200)
-            have_root = True  # we have (fake)root
-        except PermissionError:
-            have_root = False
-        return have_root
+        if sys.platform != 'win32':
+            os.mkfifo(os.path.join(self.input_path, 'fifo1'))
+            if has_lchflags:
+                platform.set_flags(os.path.join(self.input_path, 'flagfile'), stat.UF_NODUMP)
+            try:
+                # Block device
+                os.mknod('input/bdev', 0o600 | stat.S_IFBLK, os.makedev(10, 20))
+                # Char device
+                os.mknod('input/cdev', 0o600 | stat.S_IFCHR, os.makedev(30, 40))
+                # File mode
+                os.chmod('input/dir2', 0o555)  # if we take away write perms, we need root to remove contents
+                # File owner
+                os.chown('input/file1', 100, 200)
+                have_root = True  # we have (fake)root
+            except PermissionError:
+                have_root = False
+            return have_root
+        else:
+            return False
 
 
 
 
 class ArchiverTestCase(ArchiverTestCaseBase):
 class ArchiverTestCase(ArchiverTestCaseBase):
@@ -330,6 +336,9 @@ class ArchiverTestCase(ArchiverTestCaseBase):
             # we could not create these device files without (fake)root
             # we could not create these device files without (fake)root
             expected.remove('input/bdev')
             expected.remove('input/bdev')
             expected.remove('input/cdev')
             expected.remove('input/cdev')
+        if sys.platform == 'win32':
+            expected.remove('input/link1')
+            expected.remove('input/fifo1')
         if has_lchflags:
         if has_lchflags:
             # remove the file we did not backup, so input and output become equal
             # remove the file we did not backup, so input and output become equal
             expected.remove('input/flagfile')  # this file is UF_NODUMP
             expected.remove('input/flagfile')  # this file is UF_NODUMP
@@ -359,6 +368,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         # the interesting parts of info_output2 and info_output should be same
         # the interesting parts of info_output2 and info_output should be same
         self.assert_equal(filter(info_output), filter(info_output2))
         self.assert_equal(filter(info_output), filter(info_output2))
 
 
+    @pytest.mark.skipif(sys.platform == 'win32', reason='Can not test on Windows.')
     def test_unix_socket(self):
     def test_unix_socket(self):
         self.cmd('init', self.repository_location)
         self.cmd('init', self.repository_location)
         sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
         sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
@@ -369,6 +379,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
             self.cmd('extract', self.repository_location + '::test')
             self.cmd('extract', self.repository_location + '::test')
             assert not os.path.exists('input/unix-socket')
             assert not os.path.exists('input/unix-socket')
 
 
+    @pytest.mark.skipif(sys.platform == 'win32', reason='Can not test on Windows.')
     def test_symlink_extract(self):
     def test_symlink_extract(self):
         self.create_test_files()
         self.create_test_files()
         self.cmd('init', self.repository_location)
         self.cmd('init', self.repository_location)
@@ -947,6 +958,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
             # Restore permissions so shutil.rmtree is able to delete it
             # Restore permissions so shutil.rmtree is able to delete it
             os.system('chmod -R u+w ' + self.repository_path)
             os.system('chmod -R u+w ' + self.repository_path)
 
 
+    @pytest.mark.skipif(sys.platform == 'win32', reason='Meaningless and fails on windows.')
     def test_umask(self):
     def test_umask(self):
         self.create_regular_file('file1', size=1024 * 80)
         self.create_regular_file('file1', size=1024 * 80)
         self.cmd('init', self.repository_location)
         self.cmd('init', self.repository_location)
@@ -982,10 +994,14 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         self.create_regular_file('file2', size=1024 * 80)
         self.create_regular_file('file2', size=1024 * 80)
         self.cmd('init', self.repository_location)
         self.cmd('init', self.repository_location)
         output = self.cmd('create', '--list', self.repository_location + '::test', 'input')
         output = self.cmd('create', '--list', self.repository_location + '::test', 'input')
+        if sys.platform == 'win32':
+            output = output.replace('\\', '/')
         self.assert_in("A input/file1", output)
         self.assert_in("A input/file1", output)
         self.assert_in("A input/file2", output)
         self.assert_in("A input/file2", output)
         # should find first file as unmodified
         # should find first file as unmodified
         output = self.cmd('create', '--list', self.repository_location + '::test1', 'input')
         output = self.cmd('create', '--list', self.repository_location + '::test1', 'input')
+        if sys.platform == 'win32':
+            output = output.replace('\\', '/')
         self.assert_in("U input/file1", output)
         self.assert_in("U input/file1", output)
         # this is expected, although surprising, for why, see:
         # this is expected, although surprising, for why, see:
         # https://borgbackup.readthedocs.org/en/latest/faq.html#i-am-seeing-a-added-status-for-a-unchanged-file
         # https://borgbackup.readthedocs.org/en/latest/faq.html#i-am-seeing-a-added-status-for-a-unchanged-file
@@ -1003,12 +1019,16 @@ class ArchiverTestCase(ArchiverTestCaseBase):
             platform.set_flags(os.path.join(self.input_path, 'file3'), stat.UF_NODUMP)
             platform.set_flags(os.path.join(self.input_path, 'file3'), stat.UF_NODUMP)
         self.cmd('init', self.repository_location)
         self.cmd('init', self.repository_location)
         output = self.cmd('create', '--list', self.repository_location + '::test', 'input')
         output = self.cmd('create', '--list', self.repository_location + '::test', 'input')
+        if sys.platform == 'win32':
+            output = output.replace('\\', '/')
         self.assert_in("A input/file1", output)
         self.assert_in("A input/file1", output)
         self.assert_in("A input/file2", output)
         self.assert_in("A input/file2", output)
         if has_lchflags:
         if has_lchflags:
             self.assert_in("x input/file3", output)
             self.assert_in("x input/file3", output)
         # should find second file as excluded
         # should find second file as excluded
         output = self.cmd('create', '--list', self.repository_location + '::test1', 'input', '--exclude', '*/file2')
         output = self.cmd('create', '--list', self.repository_location + '::test1', 'input', '--exclude', '*/file2')
+        if sys.platform == 'win32':
+            output = output.replace('\\', '/')
         self.assert_in("U input/file1", output)
         self.assert_in("U input/file1", output)
         self.assert_in("x input/file2", output)
         self.assert_in("x input/file2", output)
         if has_lchflags:
         if has_lchflags:
@@ -1138,7 +1158,11 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         self.cmd('list', '--list-format', '-', test_archive, exit_code=1)
         self.cmd('list', '--list-format', '-', test_archive, exit_code=1)
         self.archiver.exit_code = 0  # reset exit code for following tests
         self.archiver.exit_code = 0  # reset exit code for following tests
         output_1 = self.cmd('list', test_archive)
         output_1 = self.cmd('list', test_archive)
-        output_2 = self.cmd('list', '--format', '{mode} {user:6} {group:6} {size:8d} {isomtime} {path}{extra}{NEWLINE}', test_archive)
+        output_2 = ''
+        if sys.platform == 'win32':
+            output_2 = self.cmd('list', '--format', '{user:15} {size:8} {isomtime} {path}{extra}{NL}', test_archive)
+        else:
+            output_2 = self.cmd('list', '--format', '{mode} {user:6} {group:6} {size:8d} {isomtime} {path}{extra}{NL}', test_archive)
         output_3 = self.cmd('list', '--format', '{mtime:%s} {path}{NL}', test_archive)
         output_3 = self.cmd('list', '--format', '{mtime:%s} {path}{NL}', test_archive)
         self.assertEqual(output_1, output_2)
         self.assertEqual(output_1, output_2)
         self.assertNotEqual(output_1, output_3)
         self.assertNotEqual(output_1, output_3)
@@ -1252,7 +1276,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
         assert 'positional arguments' not in self.cmd('help', 'init', '--epilog-only')
         assert 'positional arguments' not in self.cmd('help', 'init', '--epilog-only')
         assert 'This command initializes' not in self.cmd('help', 'init', '--usage-only')
         assert 'This command initializes' not in self.cmd('help', 'init', '--usage-only')
 
 
-    @unittest.skipUnless(has_llfuse, 'llfuse not installed')
+    @unittest.skipUnless(has_llfuse and sys.platform != 'win32', 'llfuse not installed')
     def test_fuse_mount_repository(self):
     def test_fuse_mount_repository(self):
         mountpoint = os.path.join(self.tmpdir, 'mountpoint')
         mountpoint = os.path.join(self.tmpdir, 'mountpoint')
         os.mkdir(mountpoint)
         os.mkdir(mountpoint)
@@ -1277,7 +1301,7 @@ class ArchiverTestCase(ArchiverTestCaseBase):
             # Give the daemon some time to exit
             # Give the daemon some time to exit
             time.sleep(.2)
             time.sleep(.2)
 
 
-    @unittest.skipUnless(has_llfuse, 'llfuse not installed')
+    @unittest.skipUnless(has_llfuse and sys.platform != 'win32', 'llfuse not installed')
     def test_fuse_mount_archive(self):
     def test_fuse_mount_archive(self):
         mountpoint = os.path.join(self.tmpdir, 'mountpoint')
         mountpoint = os.path.join(self.tmpdir, 'mountpoint')
         os.mkdir(mountpoint)
         os.mkdir(mountpoint)

+ 32 - 11
src/borg/testsuite/helpers.py

@@ -24,6 +24,9 @@ from ..helpers import CompressionSpec, CompressionDecider1, CompressionDecider2
 from ..helpers import parse_pattern, PatternMatcher, RegexPattern, PathPrefixPattern, FnmatchPattern, ShellPattern
 from ..helpers import parse_pattern, PatternMatcher, RegexPattern, PathPrefixPattern, FnmatchPattern, ShellPattern
 from . import BaseTestCase, environment_variable, FakeInputs
 from . import BaseTestCase, environment_variable, FakeInputs
 
 
+if sys.platform == 'win32':
+    import posixpath
+
 
 
 class BigIntTestCase(BaseTestCase):
 class BigIntTestCase(BaseTestCase):
 
 
@@ -52,10 +55,16 @@ class TestLocationWithoutEnv:
 
 
     def test_file(self, monkeypatch):
     def test_file(self, monkeypatch):
         monkeypatch.delenv('BORG_REPO', raising=False)
         monkeypatch.delenv('BORG_REPO', raising=False)
-        assert repr(Location('file:///some/path::archive')) == \
-            "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive')"
-        assert repr(Location('file:///some/path')) == \
-            "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive=None)"
+        if sys.platform != 'win32':
+            assert repr(Location('file:///some/path::archive')) == \
+                "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive')"
+            assert repr(Location('file:///some/path')) == \
+                "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive=None)"
+        else:
+            assert repr(Location('file://C:/some/path::archive')).replace('\\\\', '/') == \
+                "Location(proto='file', user=None, host=None, port=None, path='C:/some/path', archive='archive')"
+            assert repr(Location('file://C:/some/path')).replace('\\\\', '/') == \
+                "Location(proto='file', user=None, host=None, port=None, path='C:/some/path', archive=None)"
 
 
     def test_scp(self, monkeypatch):
     def test_scp(self, monkeypatch):
         monkeypatch.delenv('BORG_REPO', raising=False)
         monkeypatch.delenv('BORG_REPO', raising=False)
@@ -118,9 +127,9 @@ class TestLocationWithoutEnv:
         test_pid = os.getpid()
         test_pid = os.getpid()
         assert repr(Location('/some/path::archive{pid}')) == \
         assert repr(Location('/some/path::archive{pid}')) == \
             "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive{}')".format(test_pid)
             "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive{}')".format(test_pid)
-        location_time1 = Location('/some/path::archive{now:%s}')
+        location_time1 = Location('/some/path::archive{now}')
         sleep(1.1)
         sleep(1.1)
-        location_time2 = Location('/some/path::archive{now:%s}')
+        location_time2 = Location('/some/path::archive{now}')
         assert location_time1.archive != location_time2.archive
         assert location_time1.archive != location_time2.archive
 
 
 
 
@@ -133,11 +142,18 @@ class TestLocationWithEnv:
             "Location(proto='ssh', user='user', host='host', port=1234, path='/some/path', archive=None)"
             "Location(proto='ssh', user='user', host='host', port=1234, path='/some/path', archive=None)"
 
 
     def test_file(self, monkeypatch):
     def test_file(self, monkeypatch):
-        monkeypatch.setenv('BORG_REPO', 'file:///some/path')
-        assert repr(Location('::archive')) == \
-            "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive')"
-        assert repr(Location()) == \
-            "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive=None)"
+        if sys.platform != 'win32':
+            monkeypatch.setenv('BORG_REPO', 'file:///some/path')
+            assert repr(Location('::archive')) == \
+                "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive='archive')"
+            assert repr(Location()) == \
+                "Location(proto='file', user=None, host=None, port=None, path='/some/path', archive=None)"
+        else:
+            monkeypatch.setenv('BORG_REPO', 'file://C:/some/path')
+            assert repr(Location('::archive')).replace('\\\\', '/') == \
+                "Location(proto='file', user=None, host=None, port=None, path='C:/some/path', archive='archive')"
+            assert repr(Location()).replace('\\\\', '/') == \
+                "Location(proto='file', user=None, host=None, port=None, path='C:/some/path', archive=None)"
 
 
     def test_scp(self, monkeypatch):
     def test_scp(self, monkeypatch):
         monkeypatch.setenv('BORG_REPO', 'user@host:/some/path')
         monkeypatch.setenv('BORG_REPO', 'user@host:/some/path')
@@ -206,6 +222,7 @@ def check_patterns(files, pattern, expected):
     ("/./home//..//home/user2", ["/home/user2/.profile", "/home/user2/public_html/index.html"]),
     ("/./home//..//home/user2", ["/home/user2/.profile", "/home/user2/public_html/index.html"]),
     ("/srv", ["/srv/messages", "/srv/dmesg"]),
     ("/srv", ["/srv/messages", "/srv/dmesg"]),
     ])
     ])
+@pytest.mark.skipif(sys.platform == 'win32', reason='Need some windows path tests')
 def test_patterns_prefix(pattern, expected):
 def test_patterns_prefix(pattern, expected):
     files = [
     files = [
         "/etc/server/config", "/etc/server/hosts", "/home", "/home/user/.profile", "/home/user/.bashrc",
         "/etc/server/config", "/etc/server/hosts", "/home", "/home/user/.profile", "/home/user/.bashrc",
@@ -222,6 +239,7 @@ def test_patterns_prefix(pattern, expected):
     ("relative", ["relative/path1", "relative/two"]),
     ("relative", ["relative/path1", "relative/two"]),
     ("more", ["more/relative"]),
     ("more", ["more/relative"]),
     ])
     ])
+@pytest.mark.skipif(sys.platform == 'win32', reason='Need some windows path tests')
 def test_patterns_prefix_relative(pattern, expected):
 def test_patterns_prefix_relative(pattern, expected):
     files = ["relative/path1", "relative/two", "more/relative"]
     files = ["relative/path1", "relative/two", "more/relative"]
 
 
@@ -247,6 +265,7 @@ def test_patterns_prefix_relative(pattern, expected):
     ("/srv*", ["/srv/messages", "/srv/dmesg"]),
     ("/srv*", ["/srv/messages", "/srv/dmesg"]),
     ("/home/*/.thumbnails", ["/home/foo/.thumbnails", "/home/foo/bar/.thumbnails"]),
     ("/home/*/.thumbnails", ["/home/foo/.thumbnails", "/home/foo/bar/.thumbnails"]),
     ])
     ])
+@pytest.mark.skipif(sys.platform == 'win32', reason='Need some windows path tests')
 def test_patterns_fnmatch(pattern, expected):
 def test_patterns_fnmatch(pattern, expected):
     files = [
     files = [
         "/etc/server/config", "/etc/server/hosts", "/home", "/home/user/.profile", "/home/user/.bashrc",
         "/etc/server/config", "/etc/server/hosts", "/home", "/home/user/.profile", "/home/user/.bashrc",
@@ -286,6 +305,7 @@ def test_patterns_fnmatch(pattern, expected):
     ("/home/*/.thumbnails", ["/home/foo/.thumbnails"]),
     ("/home/*/.thumbnails", ["/home/foo/.thumbnails"]),
     ("/home/*/*/.thumbnails", ["/home/foo/bar/.thumbnails"]),
     ("/home/*/*/.thumbnails", ["/home/foo/bar/.thumbnails"]),
     ])
     ])
+@pytest.mark.skipif(sys.platform == 'win32', reason='Need some windows path tests')
 def test_patterns_shell(pattern, expected):
 def test_patterns_shell(pattern, expected):
     files = [
     files = [
         "/etc/server/config", "/etc/server/hosts", "/home", "/home/user/.profile", "/home/user/.bashrc",
         "/etc/server/config", "/etc/server/hosts", "/home", "/home/user/.profile", "/home/user/.bashrc",
@@ -307,6 +327,7 @@ def test_patterns_shell(pattern, expected):
      ["/home", "/home/user/.profile", "/home/user/.bashrc", "/home/user2/.profile",
      ["/home", "/home/user/.profile", "/home/user/.bashrc", "/home/user2/.profile",
       "/home/user2/public_html/index.html", "/home/foo/.thumbnails", "/home/foo/bar/.thumbnails", ]),
       "/home/user2/public_html/index.html", "/home/foo/.thumbnails", "/home/foo/bar/.thumbnails", ]),
     ])
     ])
+@pytest.mark.skipif(sys.platform == 'win32', reason='Need some windows path tests')
 def test_patterns_regex(pattern, expected):
 def test_patterns_regex(pattern, expected):
     files = [
     files = [
         '/srv/data', '/foo/bar', '/home',
         '/srv/data', '/foo/bar', '/home',

+ 8 - 2
src/borg/testsuite/repository.py

@@ -456,7 +456,10 @@ class RepositoryCheckTestCase(RepositoryTestCaseBase):
 class RemoteRepositoryTestCase(RepositoryTestCase):
 class RemoteRepositoryTestCase(RepositoryTestCase):
 
 
     def open(self, create=False):
     def open(self, create=False):
-        return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')), create=create)
+        if sys.platform != 'win32':
+            return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')), create=create)
+        else:
+            return RemoteRepository(Location(os.path.join(self.tmppath, 'repository')), create=create)
 
 
     def test_invalid_rpc(self):
     def test_invalid_rpc(self):
         self.assert_raises(InvalidRPCMethod, lambda: self.repository.call('__init__', None))
         self.assert_raises(InvalidRPCMethod, lambda: self.repository.call('__init__', None))
@@ -485,7 +488,10 @@ class RemoteRepositoryTestCase(RepositoryTestCase):
 class RemoteRepositoryCheckTestCase(RepositoryCheckTestCase):
 class RemoteRepositoryCheckTestCase(RepositoryCheckTestCase):
 
 
     def open(self, create=False):
     def open(self, create=False):
-        return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')), create=create)
+        if sys.platform != 'win32':
+            return RemoteRepository(Location('__testsuite__:' + os.path.join(self.tmppath, 'repository')), create=create)
+        else:
+            return RemoteRepository(Location(os.path.join(self.tmppath, 'repository')), create=create)
 
 
     def test_crash_before_compact(self):
     def test_crash_before_compact(self):
         # skip this test, we can't mock-patch a Repository class in another process!
         # skip this test, we can't mock-patch a Repository class in another process!