Backed out changeset d917152c263d (bug 920938) for build warning/failures

This commit is contained in:
Carsten "Tomcat" Book 2014-11-21 11:05:45 +01:00
parent aa726f5c98
commit a773a5c6bc
2 changed files with 104 additions and 86 deletions

View File

@ -877,68 +877,108 @@ class ManifestParser(object):
### directory importers
@classmethod
def _walk_directories(cls, directories, callback, pattern=None, ignore=()):
def _walk_directories(cls, directories, function, pattern=None, ignore=()):
"""
internal function to import directories
"""
if isinstance(pattern, basestring):
patterns = [pattern]
else:
patterns = pattern
ignore = set(ignore)
class FilteredDirectoryContents(object):
"""class to filter directory contents"""
if not patterns:
accept_filename = lambda filename: True
else:
def accept_filename(filename):
for pattern in patterns:
if fnmatch.fnmatch(filename, pattern):
return True
sort = sorted
if not ignore:
accept_dirname = lambda dirname: True
else:
accept_dirname = lambda dirname: dirname not in ignore
def __init__(self, pattern=pattern, ignore=ignore, cache=None):
if pattern is None:
pattern = set()
if isinstance(pattern, basestring):
pattern = [pattern]
self.patterns = pattern
self.ignore = set(ignore)
rootdirectories = directories[:]
seen_directories = set()
for rootdirectory in rootdirectories:
# let's recurse directories using list
directories = [os.path.realpath(rootdirectory)]
while directories:
directory = directories.pop(0)
if directory in seen_directories:
# eliminate possible infinite recursion due to
# symbolic links
continue
seen_directories.add(directory)
# cache of (dirnames, filenames) keyed on directory real path
# assumes volume is frozen throughout scope
self._cache = cache or {}
files = []
subdirs = []
for name in sorted(os.listdir(directory)):
path = os.path.join(directory, name)
if os.path.isfile(path):
# os.path.isfile follow symbolic links, we don't
# need to handle them here.
if accept_filename(name):
files.append(name)
continue
elif os.path.islink(path):
# eliminate symbolic links
path = os.path.realpath(path)
def __call__(self, directory):
"""returns 2-tuple: dirnames, filenames"""
directory = os.path.realpath(directory)
if directory not in self._cache:
dirnames, filenames = self.contents(directory)
# we must have a directory here
if accept_dirname(name):
subdirs.append(name)
# this subdir is added for recursion
directories.insert(0, path)
# filter out directories without progeny
# XXX recursive: should keep track of seen directories
dirnames = [ dirname for dirname in dirnames
if not self.empty(os.path.join(directory, dirname)) ]
# here we got all subdirs and files filtered, we can
# call the callback function if directory is not empty
if subdirs or files:
callback(rootdirectory, directory, subdirs, files)
self._cache[directory] = (tuple(dirnames), filenames)
# return cached values
return self._cache[directory]
def empty(self, directory):
"""
returns if a directory and its descendents are empty
"""
return self(directory) == ((), ())
def contents(self, directory, sort=None):
"""
return directory contents as (dirnames, filenames)
with `ignore` and `pattern` applied
"""
if sort is None:
sort = self.sort
# split directories and files
dirnames = []
filenames = []
for item in os.listdir(directory):
path = os.path.join(directory, item)
if os.path.isdir(path):
dirnames.append(item)
else:
# XXX not sure what to do if neither a file or directory
# (if anything)
assert os.path.isfile(path)
filenames.append(item)
# filter contents;
# this could be done in situ re the above for loop
# but it is really disparate in intent
# and could conceivably go to a separate method
dirnames = [dirname for dirname in dirnames
if dirname not in self.ignore]
filenames = set(filenames)
# we use set functionality to filter filenames
if self.patterns:
matches = set()
matches.update(*[fnmatch.filter(filenames, pattern)
for pattern in self.patterns])
filenames = matches
if sort is not None:
# sort dirnames, filenames
dirnames = sort(dirnames)
filenames = sort(filenames)
return (tuple(dirnames), tuple(filenames))
# make a filtered directory object
directory_contents = FilteredDirectoryContents(pattern=pattern, ignore=ignore)
# walk the directories, generating manifests
for index, directory in enumerate(directories):
for dirpath, dirnames, filenames in os.walk(directory):
# get the directory contents from the caching object
_dirnames, filenames = directory_contents(dirpath)
# filter out directory names
dirnames[:] = _dirnames
# call callback function
function(directory, dirpath, dirnames, filenames)
@classmethod
def populate_directory_manifests(cls, directories, filename, pattern=None, ignore=(), overwrite=False):

View File

@ -9,13 +9,17 @@ import shutil
import tempfile
import unittest
from manifestparser import convert, ManifestParser
from manifestparser import convert
class TestSymlinkConversion(unittest.TestCase):
"""
test conversion of a directory tree with symlinks to a manifest structure
"""
# Currently broken: see
# https://bugzilla.mozilla.org/show_bug.cgi?id=902610
# https://bugzilla.mozilla.org/show_bug.cgi?id=920938
def create_stub(self, directory=None):
"""stub out a directory with files in it"""
@ -48,21 +52,23 @@ class TestSymlinkConversion(unittest.TestCase):
shutil.rmtree(stub)
os.chdir(oldcwd)
@unittest.skipIf(not hasattr(os, 'symlink'),
"symlinks unavailable on this platform")
def test_relpath_symlink(self):
"""
Ensure `relative_to` works in a symlink.
Not available on windows.
"""
symlink = getattr(os, 'symlink', None)
if symlink is None:
return # symlinks unavailable on this platform
oldcwd = os.getcwd()
workspace = tempfile.mkdtemp()
try:
tmpdir = os.path.join(workspace, 'directory')
os.makedirs(tmpdir)
linkdir = os.path.join(workspace, 'link')
os.symlink(tmpdir, linkdir)
symlink(tmpdir, linkdir)
self.create_stub(tmpdir)
# subdir with in-memory manifest
@ -84,7 +90,7 @@ class TestSymlinkConversion(unittest.TestCase):
tmpdir = os.path.join(workspace, 'directory')
os.makedirs(tmpdir)
linkdir = os.path.join(workspace, 'link')
os.symlink(tmpdir, linkdir)
symlink(tmpdir, linkdir)
self.create_stub(tmpdir)
files = ['../bar', '../fleem', '../foo', 'subfile']
subdir = os.path.join(linkdir, 'subdir')
@ -92,8 +98,8 @@ class TestSymlinkConversion(unittest.TestCase):
os.makedirs(subsubdir)
linksubdir = os.path.join(linkdir, 'linky')
linksubsubdir = os.path.join(subsubdir, 'linky')
os.symlink(subdir, linksubdir)
os.symlink(subdir, linksubsubdir)
symlink(subdir, linksubdir)
symlink(subdir, linksubsubdir)
for dest in (subdir,):
os.chdir(dest)
for directory in (tmpdir, linkdir):
@ -104,34 +110,6 @@ class TestSymlinkConversion(unittest.TestCase):
shutil.rmtree(workspace)
os.chdir(oldcwd)
@unittest.skipIf(not hasattr(os, 'symlink'),
"symlinks unavailable on this platform")
def test_recursion_symlinks(self):
workspace = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, workspace)
# create two dirs
os.makedirs(os.path.join(workspace, 'dir1'))
os.makedirs(os.path.join(workspace, 'dir2'))
# create cyclical symlinks
os.symlink(os.path.join('..', 'dir1'),
os.path.join(workspace, 'dir2', 'ldir1'))
os.symlink(os.path.join('..', 'dir2'),
os.path.join(workspace, 'dir1', 'ldir2'))
# create one file in each dir
open(os.path.join(workspace, 'dir1', 'f1.txt'), 'a').close()
open(os.path.join(workspace, 'dir1', 'ldir2', 'f2.txt'), 'a').close()
data = []
def callback(rootdirectory, directory, subdirs, files):
for f in files:
data.append(f)
ManifestParser._walk_directories([workspace], callback)
self.assertEqual(sorted(data), ['f1.txt', 'f2.txt'])
if __name__ == '__main__':
unittest.main()