mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-04-15 14:46:37 +00:00
Fix user-path-expansion on Windows for non-ASCII home directories. refs #1674
Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
parent
14f783086f
commit
c1d5c4f07a
@ -521,6 +521,20 @@ class FileUtil(ReallyEqualMixin, unittest.TestCase):
|
||||
_cleanup()
|
||||
self.failIf(os.path.exists(long_path))
|
||||
|
||||
def test_windows_expanduser(self):
|
||||
def call_windows_getenv(name):
|
||||
if name == u"HOMEDRIVE": return u"C:"
|
||||
if name == u"HOMEPATH": return u"\\Documents and Settings\\\u0100"
|
||||
self.fail("unexpected argument to call_windows_getenv")
|
||||
self.patch(fileutil, 'windows_getenv', call_windows_getenv)
|
||||
|
||||
self.failUnlessReallyEqual(fileutil.windows_expanduser(u"~"), os.path.join(u"C:", u"\\Documents and Settings\\\u0100"))
|
||||
self.failUnlessReallyEqual(fileutil.windows_expanduser(u"~\\foo"), os.path.join(u"C:", u"\\Documents and Settings\\\u0100", u"foo"))
|
||||
self.failUnlessReallyEqual(fileutil.windows_expanduser(u"~/foo"), os.path.join(u"C:", u"\\Documents and Settings\\\u0100", u"foo"))
|
||||
self.failUnlessReallyEqual(fileutil.windows_expanduser(u"a"), u"a")
|
||||
self.failUnlessReallyEqual(fileutil.windows_expanduser(u"a~"), u"a~")
|
||||
self.failUnlessReallyEqual(fileutil.windows_expanduser(u"a\\~\\foo"), u"a\\~\\foo")
|
||||
|
||||
def test_disk_stats(self):
|
||||
avail = fileutil.get_available_space('.', 2**14)
|
||||
if avail == 0:
|
||||
|
@ -315,7 +315,7 @@ def abspath_expanduser_unicode(path, base=None):
|
||||
if base is not None:
|
||||
precondition_abspath(base)
|
||||
|
||||
path = os.path.expanduser(path)
|
||||
path = expanduser(path)
|
||||
|
||||
if _getfullpathname:
|
||||
# On Windows, os.path.isabs will return True for paths without a drive letter,
|
||||
@ -359,10 +359,17 @@ def to_windows_long_path(path):
|
||||
|
||||
have_GetDiskFreeSpaceExW = False
|
||||
if sys.platform == "win32":
|
||||
try:
|
||||
from ctypes import WINFUNCTYPE, windll, POINTER, byref, c_ulonglong
|
||||
from ctypes.wintypes import BOOL, DWORD, LPCWSTR
|
||||
from ctypes import WINFUNCTYPE, windll, POINTER, byref, c_ulonglong, create_unicode_buffer
|
||||
from ctypes.wintypes import BOOL, DWORD, LPCWSTR, LPWSTR
|
||||
|
||||
# <http://msdn.microsoft.com/en-us/library/ms679360%28v=VS.85%29.aspx>
|
||||
GetLastError = WINFUNCTYPE(DWORD)(("GetLastError", windll.kernel32))
|
||||
|
||||
# <http://msdn.microsoft.com/en-us/library/windows/desktop/ms683188%28v=vs.85%29.aspx>
|
||||
GetEnvironmentVariableW = WINFUNCTYPE(DWORD, LPCWSTR, LPWSTR, DWORD)(
|
||||
("GetEnvironmentVariableW", windll.kernel32))
|
||||
|
||||
try:
|
||||
# <http://msdn.microsoft.com/en-us/library/aa383742%28v=VS.85%29.aspx>
|
||||
PULARGE_INTEGER = POINTER(c_ulonglong)
|
||||
|
||||
@ -370,14 +377,51 @@ if sys.platform == "win32":
|
||||
GetDiskFreeSpaceExW = WINFUNCTYPE(BOOL, LPCWSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)(
|
||||
("GetDiskFreeSpaceExW", windll.kernel32))
|
||||
|
||||
# <http://msdn.microsoft.com/en-us/library/ms679360%28v=VS.85%29.aspx>
|
||||
GetLastError = WINFUNCTYPE(DWORD)(("GetLastError", windll.kernel32))
|
||||
|
||||
have_GetDiskFreeSpaceExW = True
|
||||
except Exception:
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
def expanduser(path):
|
||||
# os.path.expanduser is hopelessly broken for Unicode paths on Windows (ticket #1674).
|
||||
if sys.platform == "win32":
|
||||
return windows_expanduser(path)
|
||||
else:
|
||||
return os.path.expanduser(path)
|
||||
|
||||
def windows_expanduser(path):
|
||||
if not path.startswith('~'):
|
||||
return path
|
||||
home_drive = windows_getenv(u'HOMEDRIVE')
|
||||
home_path = windows_getenv(u'HOMEPATH')
|
||||
if path == '~':
|
||||
return os.path.join(home_drive, home_path)
|
||||
elif path.startswith('~/') or path.startswith('~\\'):
|
||||
return os.path.join(home_drive, home_path, path[2 :])
|
||||
else:
|
||||
return path
|
||||
|
||||
def windows_getenv(name):
|
||||
# Based on <http://stackoverflow.com/questions/2608200/problems-with-umlauts-in-python-appdata-environvent-variable/2608368#2608368>,
|
||||
# with improved error handling.
|
||||
if not isinstance(name, unicode):
|
||||
raise AssertionError("name must be Unicode")
|
||||
|
||||
n = GetEnvironmentVariableW(name, None, 0)
|
||||
if n <= 0:
|
||||
err = GetLastError()
|
||||
raise OSError("Windows error %d attempting to read environment variable %r"
|
||||
% (err, name))
|
||||
|
||||
buf = create_unicode_buffer(u'\0'*n)
|
||||
retval = GetEnvironmentVariableW(name, buf, n)
|
||||
if retval <= 0:
|
||||
err = GetLastError()
|
||||
raise OSError("Windows error %d attempting to read environment variable %r"
|
||||
% (err, name))
|
||||
|
||||
return buf.value
|
||||
|
||||
def get_disk_stats(whichdir, reserved_space=0):
|
||||
"""Return disk statistics for the storage disk, in the form of a dict
|
||||
with the following fields.
|
||||
|
Loading…
x
Reference in New Issue
Block a user