mirror of
https://github.com/facebook/sapling.git
synced 2024-10-11 01:07:15 +03:00
7a61371a9d
Summary: This moves `checkwinfilename()` from util.py to a new winutil.py module. This allows the windows.py module to import winutil.py and re-expose `checkwinfilename()` as `checkosfliename()`. This makes pyre happier, since all platform modules now contain a `checkosfilename` method. This also adds type hints to `checkwinfilename()`, and updates several parts of the code that were still incorrectly assuming the input was bytes in Python 3. However, note that I haven't done much testing of this on Windows. Reviewed By: quark-zju Differential Revision: D19672077 fbshipit-source-id: d78ed5b344a2e24c2a361b56465dedc516171d28
90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
# Portions Copyright (c) Facebook, Inc. and its affiliates.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2.
|
|
|
|
# Copyright (c) Mercurial Contributors.
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2 or any later version.
|
|
|
|
"""Utility functions related to Windows support, but which must be callable
|
|
on all platforms.
|
|
"""
|
|
|
|
from typing import Optional
|
|
|
|
from . import i18n
|
|
|
|
|
|
_ = i18n._
|
|
_winreservedchars = ':*?"<>|'
|
|
_winreservednames = {
|
|
"con",
|
|
"prn",
|
|
"aux",
|
|
"nul",
|
|
"com1",
|
|
"com2",
|
|
"com3",
|
|
"com4",
|
|
"com5",
|
|
"com6",
|
|
"com7",
|
|
"com8",
|
|
"com9",
|
|
"lpt1",
|
|
"lpt2",
|
|
"lpt3",
|
|
"lpt4",
|
|
"lpt5",
|
|
"lpt6",
|
|
"lpt7",
|
|
"lpt8",
|
|
"lpt9",
|
|
}
|
|
|
|
|
|
def checkwinfilename(path):
|
|
# type: (str) -> Optional[str]
|
|
r"""Check that the base-relative path is a valid filename on Windows.
|
|
Returns None if the path is ok, or a UI string describing the problem.
|
|
|
|
>>> checkwinfilename("just/a/normal/path")
|
|
>>> checkwinfilename("foo/bar/con.xml")
|
|
"filename contains 'con', which is reserved on Windows"
|
|
>>> checkwinfilename("foo/con.xml/bar")
|
|
"filename contains 'con', which is reserved on Windows"
|
|
>>> checkwinfilename("foo/bar/xml.con")
|
|
>>> checkwinfilename("foo/bar/AUX/bla.txt")
|
|
"filename contains 'AUX', which is reserved on Windows"
|
|
>>> checkwinfilename("foo/bar/bla:.txt")
|
|
"filename contains ':', which is reserved on Windows"
|
|
>>> checkwinfilename("foo/bar/b\07la.txt")
|
|
"filename contains '\\x07', which is invalid on Windows"
|
|
>>> checkwinfilename("foo/bar/bla ")
|
|
"filename ends with ' ', which is not allowed on Windows"
|
|
>>> checkwinfilename("../bar")
|
|
>>> checkwinfilename("foo\\")
|
|
"filename ends with '\\', which is invalid on Windows"
|
|
>>> checkwinfilename("foo\\/bar")
|
|
"directory name ends with '\\', which is invalid on Windows"
|
|
"""
|
|
if path.endswith("\\"):
|
|
return _("filename ends with '\\', which is invalid on Windows")
|
|
if "\\/" in path:
|
|
return _("directory name ends with '\\', which is invalid on Windows")
|
|
for n in path.replace("\\", "/").split("/"):
|
|
if not n:
|
|
continue
|
|
for c in n:
|
|
if c in _winreservedchars:
|
|
return _("filename contains '%s', which is reserved " "on Windows") % c
|
|
if ord(c) <= 31:
|
|
return _("filename contains %r, which is invalid " "on Windows") % c
|
|
base = n.split(".")[0]
|
|
if base and base.lower() in _winreservednames:
|
|
return _("filename contains '%s', which is reserved " "on Windows") % base
|
|
t = n[-1:]
|
|
if t in ". " and n not in "..":
|
|
return _("filename ends with '%s', which is not allowed " "on Windows") % t
|