diff options
Diffstat (limited to 'coverage/files.py')
-rw-r--r-- | coverage/files.py | 54 |
1 files changed, 48 insertions, 6 deletions
diff --git a/coverage/files.py b/coverage/files.py index 632d6e31..40af7bf7 100644 --- a/coverage/files.py +++ b/coverage/files.py @@ -2,14 +2,14 @@ from coverage.backward import to_string from coverage.misc import CoverageException -import fnmatch, os, re, sys +import fnmatch, os, os.path, re, sys class FileLocator(object): """Understand how filenames work.""" def __init__(self): # The absolute path to our current directory. - self.relative_dir = abs_file(os.curdir) + os.sep + self.relative_dir = os.path.normcase(abs_file(os.curdir) + os.sep) # Cache of results of calling the canonical_filename() method, to # avoid duplicating work. @@ -22,8 +22,9 @@ class FileLocator(object): `FileLocator` was constructed. """ - if filename.startswith(self.relative_dir): - filename = filename.replace(self.relative_dir, "", 1) + fnorm = os.path.normcase(filename) + if fnorm.startswith(self.relative_dir): + filename = filename[len(self.relative_dir):] return filename def canonical_filename(self, filename): @@ -74,9 +75,50 @@ class FileLocator(object): return None +if sys.platform == 'win32': + + def actual_path(path): + """Get the actual path of `path`, including the correct case.""" + if path in actual_path.cache: + return actual_path.cache[path] + + head, tail = os.path.split(path) + if not tail: + actpath = head + elif not head: + actpath = tail + else: + head = actual_path(head) + if head in actual_path.list_cache: + files = actual_path.list_cache[head] + else: + try: + files = os.listdir(head) + except OSError: + files = [] + actual_path.list_cache[head] = files + normtail = os.path.normcase(tail) + for f in files: + if os.path.normcase(f) == normtail: + tail = f + break + actpath = os.path.join(head, tail) + actual_path.cache[path] = actpath + return actpath + + actual_path.cache = {} + actual_path.list_cache = {} + +else: + def actual_path(filename): + """The actual path for non-Windows platforms.""" + return filename + def abs_file(filename): """Return the absolute normalized form of `filename`.""" - return os.path.normcase(os.path.abspath(os.path.realpath(filename))) + path = os.path.abspath(os.path.realpath(filename)) + path = actual_path(path) + return path def prep_patterns(patterns): @@ -196,7 +238,7 @@ class PathAliases(object): # either separator. regex_pat = regex_pat.replace(r"\/", r"[\\/]") # We want case-insensitive matching, so add that flag. - regex = re.compile("(?i)" + regex_pat) + regex = re.compile(r"(?i)" + regex_pat) # Normalize the result: it must end with a path separator. result_sep = sep(result) |