# HG changeset patch # User David Barts # Date 1559362822 25200 # Node ID 60907204a265c8a90e898b6268a5cca1738e0001 # Parent e08e24707da19d104960436357f9618fc8de8073 Support case-insensitive filesystems properly. diff -r e08e24707da1 -r 60907204a265 install-static --- a/install-static Fri May 31 20:42:57 2019 -0700 +++ b/install-static Fri May 31 21:20:22 2019 -0700 @@ -8,6 +8,7 @@ from argparse import ArgumentParser import shutil from stat import S_ISDIR, S_ISREG +from tincan import _casef # V a r i a b l e s @@ -26,9 +27,9 @@ def copydir(source, target, exclude=True): for entry in os.listdir(source): - if exclude and entry == WINF: + if exclude and _casef(entry, "upper") == WINF: continue - if entry.startswith(".") or os.path.splitext(entry)[1] in NOT_STATIC: + if entry.startswith(".") or _casef(os.path.splitext(entry)[1]) in NOT_STATIC: continue spath = os.path.join(source, entry) tpath = os.path.join(target, entry) diff -r e08e24707da1 -r 60907204a265 tincan.py --- a/tincan.py Fri May 31 20:42:57 2019 -0700 +++ b/tincan.py Fri May 31 21:20:22 2019 -0700 @@ -252,6 +252,15 @@ first = False return ''.join(ret) +_FOLDS_CASE = sys.platform in ['darwin', 'win32'] + +def _casef(string, case="lower"): + """ + If we're on an OS with case-insensitive file names, fold case. + Else leave things alone. + """ + return getattr(string, case)() if _FOLDS_CASE else string + # The TinCan class. Simply a Bottle webapp that contains a forward method, so # the code-behind can call request.app.forward(). @@ -353,7 +362,7 @@ raise ValueError("empty variable name") if self.fname == "": raise ValueError("empty file name") - if not self.fname.endswith(_IEXTEN): + if not _casef(self.fname).endswith(_IEXTEN): raise ValueError("file does not end in {0}".format(_IEXTEN)) # Using a cache is likely to help efficiency a lot, since many pages @@ -444,7 +453,7 @@ self.logger.info("adding static route: %s", self._urlpath) self._app.route(self._urlpath, 'GET', self) for i in _INDICES: - if self._urlpath.endswith(i): + if _casef(self._urlpath).endswith(i): li = len(i) for j in [ self._urlpath[:1-li], self._urlpath[:-li] ]: if j: @@ -582,7 +591,7 @@ if self._header.python is None: self._python_specified = False else: - if not self._header.python.endswith(_PEXTEN): + if not _casef(self._header.python).endswith(_PEXTEN): raise TinCanError("{0}: #python files must end in {1}".format(self._urlpath, _PEXTEN)) self._python = self._header.python self._python_specified = True @@ -590,7 +599,7 @@ self._getclass() # Build body object (#template) and obtain #loads. if self._header.template is not None: - if not self._header.template.endswith(_TEXTEN): + if not _casef(self._header.template).endswith(_TEXTEN): raise TinCanError("{0}: #template files must end in {1}".format(self._urlpath, _TEXTEN)) try: rtpath = self._splitpath(self._header.template) @@ -635,7 +644,7 @@ mtxt = ','.join(methods) self.logger.info("adding route: %s (%s)", self._origin, mtxt) self._app.route(self._origin, methods, self) - if self._origin.endswith(_INDEX): + if _casef(self._origin).endswith(_INDEX): for i in [ self._origin[:1-_LINDEX], self._origin[:-_LINDEX] ]: if i: self.logger.info("adding route: %s (%s)", i, mtxt) @@ -751,7 +760,7 @@ except IndexError as e: raise TinCanError("{0}: invalid #forward".format(self._urlpath)) from e name, ext = os.path.splitext(rname) - if ext != _TEXTEN: + if _casef(ext) != _TEXTEN: raise TinCanError("{0}: invalid #forward".format(self._urlpath)) self._subdir = rlist self._python = name + _PEXTEN @@ -820,7 +829,6 @@ # L a u n c h e r _WINF = "WEB-INF" -_BANNED = set([_WINF]) _EBANNED = set([_IEXTEN, _TEXTEN, _PEXTEN, _PEXTEN+"c"]) ENCODING = "utf-8" _BITBUCKET = logging.getLogger(__name__) @@ -886,11 +894,12 @@ for entry in os.listdir(os.path.join(self.fsroot, *subdir)): if entry.startswith("."): continue # hidden file - if not subdir and entry in _BANNED: + if not subdir and _casef(entry, "upper") == _WINF: continue etype = os.stat(os.path.join(self.fsroot, *subdir, entry)).st_mode if S_ISREG(etype): ename, eext = os.path.splitext(entry) + eext = _casef(eext) if eext == _TEXTEN: route = _TinCanRoute(self, ename, subdir) else: