Bug 941245 - Allow FileFinder to ignore patterns; r=glandium

--HG--
extra : rebase_source : 0dd3f11dcf97abc57962e820ede241b82d715624
extra : amend_source : ef75cc5f516ecba0062002c7432e7b257bff5209
This commit is contained in:
Gregory Szorc 2013-11-20 13:12:21 -08:00
parent 3325256d97
commit b665837433
2 changed files with 64 additions and 1 deletions

View File

@ -525,15 +525,23 @@ class FileFinder(BaseFinder):
'''
Helper to get appropriate BaseFile instances from the file system.
'''
def __init__(self, base, find_executables=True, **kargs):
def __init__(self, base, find_executables=True, ignore=(), **kargs):
'''
Create a FileFinder for files under the given base directory.
The find_executables argument determines whether the finder needs to
try to guess whether files are executables. Disabling this guessing
when not necessary can speed up the finder significantly.
``ignore`` accepts an iterable of patterns to ignore. Entries are
strings that match paths relative to ``base`` using
``mozpack.path.match()``. This means if an entry corresponds
to a directory, all files under that directory will be ignored. If
an entry corresponds to a file, that particular file will be ignored.
'''
BaseFinder.__init__(self, base, **kargs)
self.find_executables = find_executables
self.ignore = ignore
def _find(self, pattern):
'''
@ -556,6 +564,10 @@ class FileFinder(BaseFinder):
Ignores file names starting with a '.' under the given path. If the
path itself has leafs starting with a '.', they are not ignored.
'''
for p in self.ignore:
if mozpack.path.match(path, p):
return
# The sorted makes the output idempotent. Otherwise, we are
# likely dependent on filesystem implementation details, such as
# inode ordering.
@ -574,6 +586,10 @@ class FileFinder(BaseFinder):
if not os.path.exists(srcpath):
return
for p in self.ignore:
if mozpack.path.match(path, p):
return
if self.find_executables and is_executable(srcpath):
yield path, ExecutableFile(srcpath)
else:
@ -599,6 +615,11 @@ class FileFinder(BaseFinder):
elif '*' in pattern[0]:
if not os.path.exists(os.path.join(self.base, base)):
return
for p in self.ignore:
if mozpack.path.match(base, p):
return
# See above comment w.r.t. sorted() and idempotent behavior.
for p in sorted(os.listdir(os.path.join(self.base, base))):
if p.startswith('.') and not pattern[0].startswith('.'):

View File

@ -724,6 +724,48 @@ class TestFileFinder(MatchTestTemplate, TestWithTmpDir):
self.do_match_test()
self.do_finder_test(self.finder)
def test_ignored_dirs(self):
"""Ignored directories should not have results returned."""
self.prepare_match_test()
self.add('fooz')
# Present to ensure prefix matching doesn't exclude.
self.add('foo/quxz')
self.finder = FileFinder(self.tmpdir, ignore=['foo/qux'])
self.do_check('**', ['bar', 'foo/bar', 'foo/baz', 'foo/quxz', 'fooz'])
self.do_check('foo/*', ['foo/bar', 'foo/baz', 'foo/quxz'])
self.do_check('foo/**', ['foo/bar', 'foo/baz', 'foo/quxz'])
self.do_check('foo/qux/**', [])
self.do_check('foo/qux/*', [])
self.do_check('foo/qux/bar', [])
self.do_check('foo/quxz', ['foo/quxz'])
self.do_check('fooz', ['fooz'])
def test_ignored_files(self):
"""Ignored files should not have results returned."""
self.prepare_match_test()
# Be sure prefix match doesn't get ignored.
self.add('barz')
self.finder = FileFinder(self.tmpdir, ignore=['foo/bar', 'bar'])
self.do_check('**', ['barz', 'foo/baz', 'foo/qux/1', 'foo/qux/2/test',
'foo/qux/2/test2', 'foo/qux/bar'])
self.do_check('foo/**', ['foo/baz', 'foo/qux/1', 'foo/qux/2/test',
'foo/qux/2/test2', 'foo/qux/bar'])
def test_ignored_patterns(self):
"""Ignore entries with patterns should be honored."""
self.prepare_match_test()
self.add('foo/quxz')
self.finder = FileFinder(self.tmpdir, ignore=['foo/qux/*'])
self.do_check('**', ['foo/bar', 'foo/baz', 'foo/quxz', 'bar'])
self.do_check('foo/**', ['foo/bar', 'foo/baz', 'foo/quxz'])
class TestJarFinder(MatchTestTemplate, TestWithTmpDir):
def add(self, path):