[PATCH] Allow manipulating files with long names on Windows

Aaron Cohen aaron at assonance.org
Mon Jan 17 13:58:26 CST 2011


On Monday, January 17, 2011, Adrian Buehlmann <adrian at cadifra.com> wrote:
> On 2011-01-17 08:59, Aaron Cohen wrote:
>> # HG changeset patch
>> # User Aaron Cohen <aaron at assonance.org>
>> # Date 1295249042 18000
>> # Node ID 8b2e02872bc83f9e537a9754ce4b7bd0d9a5d9aa
>> # Parent  20a54bdf232832d3d6c4e4a43361dc84ec73dca0
>> Allow manipulating files with long names on Windows
>>
>> Windows by default has a PATH_MAX of 260 characters. A while ago the
>
> Windows does not define PATH_MAX. It has a MAX_PATH which is 260.

Will fix, just wrote that from memory.

>> "store" format was added which allows repositories on Windows to
>> contain very long paths.
>
> It was the fncache format which made that possible.
>
> http://mercurial.selenic.com/wiki/fncacheRepoFormat
>
> [big snip]
>
>> diff -r 20a54bdf2328 -r 8b2e02872bc8 tests/test-win32lfn.py
>> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
>> +++ b/tests/test-win32lfn.py  Mon Jan 17 02:24:02 2011 -0500
>> @@ -0,0 +1,99 @@
>> +import os, errno
>> +
>> +from hgext import win32lfn
>> +
>> +win32lfn.uisetup(None)
>> +
>> +# 299 chars, mixed slashes
>> +name = "123456789\\" + 28 * "123456789/" + "123456789"
>> +
>> +uncname = win32lfn.unc(name)
>> +
>> +expectedpath = "\\\\?\\" + os.getcwd() + 30 * "\\123456789"
>> +
>> +assert uncname == expectedpath
>> +
>> +convolutedpath = "C:\\d/d\\d/././.\\..\\\\//."
>> +
>> +canonpath = win32lfn.unc(convolutedpath)
>> +expected = "\\\\?\\C:\\d\\d"
>> +assert canonpath == expected
>> +
>> +normpath = os.path.normpath(convolutedpath)
>> +expected = "C:\\d\\d"
>> +assert normpath == expected
>> +
>> +shortpath = "C:\\"
>> +shortunc = win32lfn.unc(shortpath)
>> +expected = "\\\\?\\C:\\"
>> +assert shortunc == expected
>> +
>> +assert os.path.dirname(shortunc) == shortunc
>> +
>> +head, tail = os.path.split(shortunc)
>> +expected = "\\\\?\\C:\\"
>> +assert head == expected, tail == ""
>> +
>> +# Tempting as it is, make sure we don't touch paths that were already UNC
>> +assert win32lfn.unc("\\\\?\\" + convolutedpath) == "\\\\?\\" + convolutedpath
>> +
>> +# Cleanup previous test runs
>> +if os.path.exists(name):
>> +    for f in os.listdir(name):
>> +        os.remove(os.path.join(name, f))
>> +    os.removedirs(name)
>> +
>> +for d in [name, uncname]:
>> +    f1 = os.path.join(d, "f1")
>> +    f2 = os.path.join(d, "f2")
>> +
>> +    assert os.path.split(f1) == (d, "f1")
>> +    assert os.path.dirname(f2) == d
>> +    assert os.path.basename(f2) == "f2"
>> +
>> +    os.makedirs(d)
>> +    assert os.path.exists(d)
>> +    assert os.path.isdir(d)
>> +
>> +    os.rmdir(d)
>> +    assert not os.path.exists(d)
>> +
>> +    # os.mkdir must return EEXIST if the directory exists
>> +    os.mkdir(d)
>> +    thrown = False
>> +    try:
>> +        os.mkdir(name)
>> +    except OSError, err:
>> +        thrown = True
>> +        assert err.errno == errno.EEXIST
>> +    assert thrown
>> +
>> +    f = open(f1, 'w')
>> +    f.write("Test")
>> +    f.close()
>> +
>> +    f = open(f1, 'r')
>> +    assert f.readline() == "Test"
>> +    f.close()
>> +
>> +    os.stat(f1)
>> +    os.lstat(f1)
>> +    os.chmod(f1, 660)
>> +    assert os.path.isfile(f1)
>> +
>> +    files = os.listdir(name)
>> +    assert len(files) == 1
>> +    assert os.path.basename(f1) in files
>> +
>> +    os.rename(f1, f2)
>> +    os.stat(f2)
>> +    assert not os.path.exists(f1)
>> +
>> +    fd = os.open(f1, os.O_CREAT | os.O_BINARY | os.O_RDWR)
>> +    os.write(fd, "Test2")
>> +    os.close(fd)
>> +
>> +    os.remove(f1)
>> +    os.unlink(f2)
>> +    os.removedirs(name)
>> +    assert not os.path.exists("123456789")
>> \ No newline at end of file
>
> Please end the files with a newline.
>
> I don't see any test cases using util.posixfile here. And I have some
> doubts the extension works with util.posixfile on Windows. Can you prove
> me wrong?
>
> (util.posixfile is pretty heavily used by Mercurial on Windows)

osutil,posixfile and util.posixfile are the same thing on Windows
aren't they? If so it seems to work fine. I'll double check though.

There are two test scripts there, test-win32lfn-util.py has all the
hg-specific tests, the other has tests that test my wrapping of the
python libs.

-- 
-- Aaron


More information about the Mercurial-devel mailing list