Repository: facelessuser/wcmatch

Issue:
Fix glob `/*` behavior on Windows
While addressing #196  it seems I've discovered a small tangential issue.

On Windows,  `r'\\*'` should assume the current working drive, which it does, but so should `'/*'`. The latter seems to not be working. It is likely that this broke somewhere along the way and we did not notice.

This shouldn't be difficult to fix either, just something I don't think we are properly testing for. We do have a test, but it is not explicit enough. It checks that we return something, it is just, unfortunately, returning `['\\']` which is not correct.  `r'\\*'`, on the other hand, returns all the files under the root of the current Windows drive. The test should check that we are getting non `\\` results instead of just verifying it matches something. We can't predict what files they are as we can be testing on any system, but whatever system we test on should return something other than `\\`.

Comments:

Patch:
diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index df2082d..2ef5859 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -1,5 +1,10 @@
 # Changelog
 
+## 8.4.1
+
+- **FIX**: Windows drive path separators should normalize like other path separators.
+- **FIX**: Fix a Windows pattern parsing issue that caused absolute paths with ambiguous drives to not parse correctly.
+
 ## 8.4
 
 - **NEW**: Drop support for Python 3.6.
diff --git a/wcmatch/__meta__.py b/wcmatch/__meta__.py
index 939221b..c273b6e 100644
--- a/wcmatch/__meta__.py
+++ b/wcmatch/__meta__.py
@@ -193,5 +193,5 @@ def parse_version(ver: str) -> Version:
     return Version(major, minor, micro, release, pre, post, dev)
 
 
-__version_info__ = Version(8, 4, 0, "final")
+__version_info__ = Version(8, 4, 1, "final")
 __version__ = __version_info__._get_canonical()
diff --git a/wcmatch/_wcparse.py b/wcmatch/_wcparse.py
index 08aea80..59d6d60 100644
--- a/wcmatch/_wcparse.py
+++ b/wcmatch/_wcparse.py
@@ -362,9 +362,9 @@ def _get_win_drive(
         end = m.end(0)
         if m.group(3) and RE_WIN_DRIVE_LETTER.match(m.group(0)):
             if regex:
-                drive = escape_drive(RE_WIN_DRIVE_UNESCAPE.sub(r'\1', m.group(3)), case_sensitive)
+                drive = escape_drive(RE_WIN_DRIVE_UNESCAPE.sub(r'\1', m.group(3)).replace('/', '\\'), case_sensitive)
             else:
-                drive = RE_WIN_DRIVE_UNESCAPE.sub(r'\1', m.group(0))
+                drive = RE_WIN_DRIVE_UNESCAPE.sub(r'\1', m.group(0)).replace('/', '\\')
             slash = bool(m.group(4))
             root_specified = True
         elif m.group(2):
diff --git a/wcmatch/glob.py b/wcmatch/glob.py
index a8249d6..4560e72 100644
--- a/wcmatch/glob.py
+++ b/wcmatch/glob.py
@@ -314,8 +314,12 @@ class _GlobSplit(Generic[AnyStr]):
                 i.advance(start)
             elif drive is None and root_specified:
                 parts.append(_GlobPart(b'\\' if is_bytes else '\\', False, False, True, True))
-                start = 1
-                i.advance(2)
+                if pattern.startswith('/'):
+                    start = 0
+                    i.advance(1)
+                else:
+                    start = 1
+                    i.advance(2)
         elif not self.win_drive_detect and pattern.startswith('/'):
             parts.append(_GlobPart(b'/' if is_bytes else '/', False, False, True, True))
             start = 0


Test patch:
diff --git a/tests/test_glob.py b/tests/test_glob.py
index 9d626be..57331f2 100644
--- a/tests/test_glob.py
+++ b/tests/test_glob.py
@@ -1591,13 +1591,29 @@ class TestSymlinkLoopGlob(unittest.TestCase):
 class TestGlobPaths(unittest.TestCase):
     """Test `glob` paths."""
 
-    def test_root(self):
+    @unittest.skipUnless(not sys.platform.startswith('win'), "Linux/Unix specific test")
+    def test_root_unix(self):
         """Test that `glob` translates the root properly."""
 
-        # On Windows, this should translate to the current drive.
         # On Linux/Unix, this should translate to the root.
         # Basically, we should not return an empty set.
-        self.assertTrue(len(glob.glob('/*')) > 0)
+        results = glob.glob('/*')
+        self.assertTrue(len(results) > 0)
+        self.assertTrue('/' not in results)
+
+    @unittest.skipUnless(sys.platform.startswith('win'), "Windows specific test")
+    def test_root_win(self):
+        """Test that `glob` translates the root properly."""
+
+        # On Windows, this should translate to the current drive.
+        # Basically, we should not return an empty set.
+        results = glob.glob('/*')
+        self.assertTrue(len(results) > 0)
+        self.assertTrue('\\' not in results)
+
+        results = glob.glob(r'\\*')
+        self.assertTrue(len(results) > 0)
+        self.assertTrue('\\' not in results)
 
     def test_start(self):
         """Test that starting directory/files are handled properly."""