Use "long" paths prefixed with \\?\ on Windows. refs #2235

Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
Daira Hopwood 2015-01-30 00:05:14 +00:00
parent 9a401b760e
commit c20a3525b7
5 changed files with 64 additions and 17 deletions

View File

@ -650,7 +650,7 @@ def find_shares(options):
out = options.stdout
sharedir = storage_index_to_dir(si_a2b(options.si_s))
for d in options.nodedirs:
d = os.path.join(d, "storage/shares", sharedir)
d = os.path.join(d, "storage", "shares", sharedir)
if os.path.exists(d):
for shnum in listdir_unicode(d):
print >>out, os.path.join(d, shnum)
@ -832,7 +832,7 @@ def catalog_shares(options):
err = options.stderr
now = time.time()
for d in options.nodedirs:
d = os.path.join(d, "storage/shares")
d = os.path.join(d, "storage", "shares")
try:
abbrevs = listdir_unicode(d)
except EnvironmentError:

View File

@ -3779,7 +3779,7 @@ class Webopen(GridTestMixin, CLITestMixin, unittest.TestCase):
raise
return d
class Options(unittest.TestCase):
class Options(ReallyEqualMixin, unittest.TestCase):
# this test case only looks at argument-processing and simple stuff.
def parse(self, args, stdout=None):
@ -3861,17 +3861,17 @@ class Options(unittest.TestCase):
# option after, or a basedir argument after, but none in the wrong
# place, and not more than one of the three.
o = self.parse(["start"])
self.failUnlessEqual(o["basedir"], os.path.join(os.path.expanduser("~"),
".tahoe"))
self.failUnlessReallyEqual(o["basedir"], os.path.join(fileutil.abspath_expanduser_unicode(u"~"),
u".tahoe"))
o = self.parse(["start", "here"])
self.failUnlessEqual(o["basedir"], os.path.abspath("here"))
self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"here"))
o = self.parse(["start", "--basedir", "there"])
self.failUnlessEqual(o["basedir"], os.path.abspath("there"))
self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"there"))
o = self.parse(["--node-directory", "there", "start"])
self.failUnlessEqual(o["basedir"], os.path.abspath("there"))
self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"there"))
o = self.parse(["start", "here", "--nodaemon"])
self.failUnlessEqual(o["basedir"], os.path.abspath("here"))
self.failUnlessReallyEqual(o["basedir"], fileutil.abspath_expanduser_unicode(u"here"))
self.failUnlessRaises(usage.UsageError, self.parse,
["--basedir", "there", "start"])

View File

@ -1,4 +1,4 @@
import os
import os, sys
from twisted.trial import unittest
from twisted.application import service
@ -68,10 +68,11 @@ class Basic(testutil.ReallyEqualMixin, unittest.TestCase):
fileutil.write(os.path.join(basedir, "debug_discard_storage"), "")
e = self.failUnlessRaises(OldConfigError, client.Client, basedir)
self.failUnlessIn(os.path.abspath(os.path.join(basedir, "introducer.furl")), e.args[0])
self.failUnlessIn(os.path.abspath(os.path.join(basedir, "no_storage")), e.args[0])
self.failUnlessIn(os.path.abspath(os.path.join(basedir, "readonly_storage")), e.args[0])
self.failUnlessIn(os.path.abspath(os.path.join(basedir, "debug_discard_storage")), e.args[0])
abs_basedir = fileutil.abspath_expanduser_unicode(unicode(basedir)).encode(sys.getfilesystemencoding())
self.failUnlessIn(os.path.join(abs_basedir, "introducer.furl"), e.args[0])
self.failUnlessIn(os.path.join(abs_basedir, "no_storage"), e.args[0])
self.failUnlessIn(os.path.join(abs_basedir, "readonly_storage"), e.args[0])
self.failUnlessIn(os.path.join(abs_basedir, "debug_discard_storage"), e.args[0])
for oldfile in ['introducer.furl', 'no_storage', 'readonly_storage',
'debug_discard_storage']:

View File

@ -15,6 +15,8 @@ from allmydata.util import limiter, time_format, pollmixin, cachedir
from allmydata.util import statistics, dictutil, pipeline
from allmydata.util import log as tahoe_log
from allmydata.util.spans import Spans, overlap, DataSpans
from allmydata.test.common_util import ReallyEqualMixin
class Base32(unittest.TestCase):
def test_b2a_matches_Pythons(self):
@ -370,7 +372,7 @@ class Asserts(unittest.TestCase):
m = self.should_assert(f, False, othermsg="message2")
self.failUnlessEqual("postcondition: othermsg: 'message2' <type 'str'>", m)
class FileUtil(unittest.TestCase):
class FileUtil(ReallyEqualMixin, unittest.TestCase):
def mkdir(self, basedir, path, mode=0777):
fn = os.path.join(basedir, path)
fileutil.make_dirs(fn, mode)
@ -472,7 +474,16 @@ class FileUtil(unittest.TestCase):
abspath_cwd = fileutil.abspath_expanduser_unicode(u".")
self.failUnless(isinstance(saved_cwd, unicode), saved_cwd)
self.failUnless(isinstance(abspath_cwd, unicode), abspath_cwd)
self.failUnlessEqual(abspath_cwd, saved_cwd)
if sys.platform == "win32":
self.failUnlessReallyEqual(abspath_cwd, fileutil.to_windows_long_path(saved_cwd))
else:
self.failUnlessReallyEqual(abspath_cwd, saved_cwd)
self.failUnlessReallyEqual(fileutil.to_windows_long_path(u"\\\\?\\foo"), u"\\\\?\\foo")
self.failUnlessReallyEqual(fileutil.to_windows_long_path(u"\\\\.\\foo"), u"\\\\.\\foo")
self.failUnlessReallyEqual(fileutil.to_windows_long_path(u"\\\\server\\foo"), u"\\\\?\\UNC\\server\\foo")
self.failUnlessReallyEqual(fileutil.to_windows_long_path(u"C:\\foo"), u"\\\\?\\C:\\foo")
self.failUnlessReallyEqual(fileutil.to_windows_long_path(u"C:\\foo/bar"), u"\\\\?\\C:\\foo\\bar")
# adapted from <http://svn.python.org/view/python/branches/release26-maint/Lib/test/test_posixpath.py?view=markup&pathrev=78279#test_abspath>
@ -496,6 +507,20 @@ class FileUtil(unittest.TestCase):
finally:
os.chdir(saved_cwd)
def test_create_long_path(self):
workdir = u"test_create_long_path"
fileutil.make_dirs(workdir)
long_path = fileutil.abspath_expanduser_unicode(os.path.join(workdir, u'x'*255))
def _cleanup():
fileutil.remove(long_path)
self.addCleanup(_cleanup)
fileutil.write(long_path, "test")
self.failUnless(os.path.exists(long_path))
self.failUnlessEqual(fileutil.read(long_path), "test")
_cleanup()
self.failIf(os.path.exists(long_path))
def test_disk_stats(self):
avail = fileutil.get_available_space('.', 2**14)
if avail == 0:

View File

@ -305,7 +305,28 @@ def abspath_expanduser_unicode(path):
# We won't hit <http://bugs.python.org/issue5827> because
# there is always at least one Unicode path component.
return os.path.normpath(path)
path = os.path.normpath(path)
if sys.platform == "win32":
path = to_windows_long_path(path)
return path
def to_windows_long_path(path):
# '/' is normally a perfectly valid path component separator in Windows.
# However, when using the "\\?\" syntax it is not recognized, so we
# replace it with '\' here.
path = path.replace(u"/", u"\\")
# Note that other normalizations such as removing '.' and '..' should
# be done outside this function.
if path.startswith(u"\\\\?\\") or path.startswith(u"\\\\.\\"):
return path
elif path.startswith(u"\\\\"):
return u"\\\\?\\UNC\\" + path[2 :]
else:
return u"\\\\?\\" + path
have_GetDiskFreeSpaceExW = False