Skip to content

Commit 4677903

Browse files
committed
Reorganize case sensitivity check function
Just a little readability enhancement.
1 parent 9e5e9a2 commit 4677903

File tree

2 files changed

+51
-46
lines changed

2 files changed

+51
-46
lines changed

beets/library.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def __init__(self, field, pattern, fast=True, case_sensitive=None):
6464
# By default, the case sensitivity depends on the filesystem
6565
# that the query path is located on.
6666
if case_sensitive is None:
67-
case_sensitive = beets.util.is_filesystem_case_sensitive(pattern)
67+
case_sensitive = beets.util.case_sensitive(pattern)
6868
self.case_sensitive = case_sensitive
6969

7070
# Use a normalized-case pattern for case-insensitive matches.

beets/util/__init__.py

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -763,50 +763,55 @@ def interactive_open(targets, command=None):
763763
return os.execlp(*command)
764764

765765

766-
def is_filesystem_case_sensitive(path):
767-
"""Checks if the filesystem at the given path is case sensitive.
768-
If the path does not exist, a case sensitive file system is
769-
assumed if the system is not windows.
766+
def _windows_long_path_name(short_path):
767+
"""Use Windows' `GetLongPathNameW` via ctypes to get the canonical,
768+
long path given a short filename.
769+
"""
770+
if not isinstance(short_path, unicode):
771+
short_path = unicode(short_path)
772+
buf = ctypes.create_unicode_buffer(260)
773+
get_long_path_name_w = ctypes.windll.kernel32.GetLongPathNameW
774+
return_value = get_long_path_name_w(short_path, buf, 260)
775+
if return_value == 0 or return_value > 260:
776+
# An error occurred
777+
return short_path
778+
else:
779+
long_path = buf.value
780+
# GetLongPathNameW does not change the case of the drive
781+
# letter.
782+
if len(long_path) > 1 and long_path[1] == ':':
783+
long_path = long_path[0].upper() + long_path[1:]
784+
return long_path
785+
770786

771-
:param path: The path to check for case sensitivity.
772-
:return: True if the file system is case sensitive, False else.
787+
def case_sensitive(path):
788+
"""Check whether the filesystem at the given path is case sensitive.
789+
790+
To work best, the path should point to a file or a directory. If the path
791+
does not exist, assume a case sensitive file system on every platform
792+
except Windows.
773793
"""
774-
if os.path.exists(path):
775-
# Check if the path to the library exists in lower and upper case
776-
if os.path.exists(path.lower()) and \
777-
os.path.exists(path.upper()):
778-
# All the paths may exist on the file system. Check if they
779-
# refer to different files
780-
if platform.system() != 'Windows':
781-
# os.path.samefile is only available on Unix systems for
782-
# python < 3.0
783-
return not os.path.samefile(path.lower(),
784-
path.upper())
785-
786-
# On windows we use GetLongPathNameW to determine the real path
787-
# using the actual case.
788-
def get_long_path_name(short_path):
789-
if not isinstance(short_path, unicode):
790-
short_path = unicode(short_path)
791-
buf = ctypes.create_unicode_buffer(260)
792-
get_long_path_name_w = ctypes.windll.kernel32.GetLongPathNameW
793-
return_value = get_long_path_name_w(short_path, buf, 260)
794-
if return_value == 0 or return_value > 260:
795-
# An error occurred
796-
return short_path
797-
else:
798-
long_path = buf.value
799-
# GetLongPathNameW does not change the case of the drive
800-
# letter.
801-
if len(long_path) > 1 and long_path[1] == ':':
802-
long_path = long_path[0].upper() + long_path[1:]
803-
return long_path
804-
805-
lower = get_long_path_name(path.lower())
806-
upper = get_long_path_name(path.upper())
807-
808-
return lower != upper
809-
else:
810-
return True
811-
# By default, the case sensitivity depends on the platform.
812-
return platform.system() != 'Windows'
794+
# A fallback in case the path does not exist.
795+
if not os.path.exists(path):
796+
# By default, the case sensitivity depends on the platform.
797+
return platform.system() != 'Windows'
798+
799+
# If an upper-case version of the path exists but a lower-case
800+
# version does not, then the filesystem must be case-sensitive.
801+
# (Otherwise, we have more work to do.)
802+
if not (os.path.exists(path.lower()) and
803+
os.path.exists(path.upper())):
804+
return True
805+
806+
# Both versions of the path exist on the file system. Check whether
807+
# they refer to different files by their inodes. Alas,
808+
# `os.path.samefile` is only available on Unix systems on Python 2.
809+
if platform.system() != 'Windows':
810+
return not os.path.samefile(path.lower(),
811+
path.upper())
812+
813+
# On Windows, we check whether the canonical, long filenames for the
814+
# files are the same.
815+
lower = _windows_long_path_name(path.lower())
816+
upper = _windows_long_path_name(path.upper())
817+
return lower != upper

0 commit comments

Comments
 (0)