123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- # This Source Code Form is subject to the terms of the Mozilla Public
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
- from __future__ import absolute_import
- import posixpath
- import os
- import re
- '''
- Like os.path, with a reduced set of functions, and with normalized path
- separators (always use forward slashes).
- Also contains a few additional utilities not found in os.path.
- '''
- def normsep(path):
- '''
- Normalize path separators, by using forward slashes instead of whatever
- os.sep is.
- '''
- if os.sep != '/':
- path = path.replace(os.sep, '/')
- if os.altsep and os.altsep != '/':
- path = path.replace(os.altsep, '/')
- return path
- def relpath(path, start):
- rel = normsep(os.path.relpath(path, start))
- return '' if rel == '.' else rel
- def realpath(path):
- return normsep(os.path.realpath(path))
- def abspath(path):
- return normsep(os.path.abspath(path))
- def join(*paths):
- return normsep(os.path.join(*paths))
- def normpath(path):
- return posixpath.normpath(normsep(path))
- def dirname(path):
- return posixpath.dirname(normsep(path))
- def commonprefix(paths):
- return posixpath.commonprefix([normsep(path) for path in paths])
- def basename(path):
- return os.path.basename(path)
- def splitext(path):
- return posixpath.splitext(normsep(path))
- def split(path):
- '''
- Return the normalized path as a list of its components.
- split('foo/bar/baz') returns ['foo', 'bar', 'baz']
- '''
- return normsep(path).split('/')
- def basedir(path, bases):
- '''
- Given a list of directories (bases), return which one contains the given
- path. If several matches are found, the deepest base directory is returned.
- basedir('foo/bar/baz', ['foo', 'baz', 'foo/bar']) returns 'foo/bar'
- ('foo' and 'foo/bar' both match, but 'foo/bar' is the deepest match)
- '''
- path = normsep(path)
- bases = [normsep(b) for b in bases]
- if path in bases:
- return path
- for b in sorted(bases, reverse=True):
- if b == '' or path.startswith(b + '/'):
- return b
- re_cache = {}
- def match(path, pattern):
- '''
- Return whether the given path matches the given pattern.
- An asterisk can be used to match any string, including the null string, in
- one part of the path:
- 'foo' matches '*', 'f*' or 'fo*o'
- However, an asterisk matching a subdirectory may not match the null string:
- 'foo/bar' does *not* match 'foo/*/bar'
- If the pattern matches one of the ancestor directories of the path, the
- patch is considered matching:
- 'foo/bar' matches 'foo'
- Two adjacent asterisks can be used to match files and zero or more
- directories and subdirectories.
- 'foo/bar' matches 'foo/**/bar', or '**/bar'
- '''
- if not pattern:
- return True
- if pattern not in re_cache:
- p = re.escape(pattern)
- p = re.sub(r'(^|\\\/)\\\*\\\*\\\/', r'\1(?:.+/)?', p)
- p = re.sub(r'(^|\\\/)\\\*\\\*$', r'(?:\1.+)?', p)
- p = p.replace(r'\*', '[^/]*') + '(?:/.*)?$'
- re_cache[pattern] = re.compile(p)
- return re_cache[pattern].match(path) is not None
- def rebase(oldbase, base, relativepath):
- '''
- Return relativepath relative to base instead of oldbase.
- '''
- if base == oldbase:
- return relativepath
- if len(base) < len(oldbase):
- assert basedir(oldbase, [base]) == base
- relbase = relpath(oldbase, base)
- result = join(relbase, relativepath)
- else:
- assert basedir(base, [oldbase]) == oldbase
- relbase = relpath(base, oldbase)
- result = relpath(relativepath, relbase)
- result = normpath(result)
- if relativepath.endswith('/') and not result.endswith('/'):
- result += '/'
- return result
|