[PATCH] Allow manipulating files with long names on Windows

Adrian Buehlmann adrian at cadifra.com
Mon Jan 17 12:31:32 CST 2011


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.

> "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)




More information about the Mercurial-devel mailing list