summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2017-10-24 22:03:41 +0200
committerMichał Górny <mgorny@gentoo.org>2017-10-24 22:10:20 +0200
commit1336959230029c42c9550ac6c39fa4d3ab62b0aa (patch)
tree802a0421653a85720276df4ed06be5e50ab13952
parent2c462cdb9bfa173900953d7b788d7ac1bbdcbfe7 (diff)
downloadgemato-1336959230029c42c9550ac6c39fa4d3ab62b0aa.tar.gz
recursiveloader: Support verifying a whole directory
-rw-r--r--gemato/recursiveloader.py68
-rw-r--r--tests/test_recursiveloader.py69
2 files changed, 137 insertions, 0 deletions
diff --git a/gemato/recursiveloader.py b/gemato/recursiveloader.py
index 1e2d8db..b007121 100644
--- a/gemato/recursiveloader.py
+++ b/gemato/recursiveloader.py
@@ -22,6 +22,14 @@ class ManifestIncompatibleEntry(Exception):
self.diff = diff
+def throw_exception(e):
+ """
+ Raise the given exception. Needed for onerror= argument
+ to os.walk().
+ """
+ raise e
+
+
class ManifestRecursiveLoader(object):
"""
A class encapsulating a tree covered by multiple Manifests.
@@ -196,3 +204,63 @@ class ManifestRecursiveLoader(object):
e = type(e)(e.path, e.size, new_checksums)
out[fullpath] = e
return out
+
+ def assert_directory_verifies(self, path=''):
+ """
+ Verify the complete directory tree starting at @path (relative
+ to top Manifest directory). Includes testing for stray files.
+ Raises an exception if any of the files does not pass
+ verification.
+ """
+
+ entry_dict = self.get_file_entry_dict(path)
+ it = os.walk(os.path.join(self.root_directory, path),
+ onerror=throw_exception,
+ followlinks=True)
+
+ for dirpath, dirnames, filenames in it:
+ relpath = os.path.relpath(dirpath, self.root_directory)
+ # strip dot to avoid matching problems
+ if relpath == '.':
+ relpath = ''
+
+ skip_dirs = []
+ for d in dirnames:
+ # skip dotfiles
+ if d.startswith('.'):
+ skip_dirs.append(d)
+ continue
+
+ dpath = os.path.join(relpath, d)
+ de = entry_dict.pop(dpath, None)
+ if de is None:
+ continue
+
+ if isinstance(de, gemato.manifest.ManifestEntryIGNORE):
+ skip_dirs.append(d)
+ else:
+ gemato.verify.assert_path_verifies(
+ os.path.join(dirpath, d), de)
+
+ # skip scanning ignored directories
+ for d in skip_dirs:
+ dirnames.remove(d)
+
+ for f in filenames:
+ # skip dotfiles
+ if f.startswith('.'):
+ continue
+
+ fpath = os.path.join(relpath, f)
+ # skip top-level Manifest, we obviously can't have
+ # an entry for it
+ if fpath == 'Manifest':
+ continue
+ fe = entry_dict.pop(fpath, None)
+ gemato.verify.assert_path_verifies(
+ os.path.join(dirpath, f), fe)
+
+ # check for missing files
+ for relpath, e in entry_dict.items():
+ syspath = os.path.join(self.root_directory, relpath)
+ gemato.verify.assert_path_verifies(syspath, e)
diff --git a/tests/test_recursiveloader.py b/tests/test_recursiveloader.py
index 8aa924f..2483030 100644
--- a/tests/test_recursiveloader.py
+++ b/tests/test_recursiveloader.py
@@ -219,6 +219,17 @@ DATA test 0 MD5 d41d8cd98f00b204e9800998ecf8427e
os.path.join(self.dir, 'Manifest'))
self.assertDictEqual(m.get_file_entry_dict('nonexist'), {})
+ def test_assert_directory_verifies(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ m.assert_directory_verifies('other')
+
+ def test_assert_directory_verifies_stray_file(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ self.assertRaises(gemato.verify.ManifestMismatch,
+ m.assert_directory_verifies, 'sub')
+
class MultipleManifestTest(TempDirTestCase):
DIRS = ['sub']
@@ -295,6 +306,7 @@ class DuplicateFileEntryTest(TempDirTestCase):
DATA test 0 MD5 d41d8cd98f00b204e9800998ecf8427e
DATA test 0 MD5 d41d8cd98f00b204e9800998ecf8427e
''',
+ 'test': u'',
}
def test_find_path_entry(self):
@@ -309,6 +321,11 @@ DATA test 0 MD5 d41d8cd98f00b204e9800998ecf8427e
self.assertSetEqual(frozenset(entries), frozenset(('test',)))
self.assertEqual(entries['test'].path, 'test')
+ def test_assert_directory_verifies(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ m.assert_directory_verifies('')
+
class DuplicateManifestFileEntryTest(TempDirTestCase):
"""
@@ -397,6 +414,7 @@ class DuplicateCompatibleTypeFileEntryTest(TempDirTestCase):
DATA test.ebuild 0 MD5 d41d8cd98f00b204e9800998ecf8427e
EBUILD test.ebuild 0 MD5 d41d8cd98f00b204e9800998ecf8427e
''',
+ 'test.ebuild': u'',
}
def test_find_path_entry(self):
@@ -411,6 +429,11 @@ EBUILD test.ebuild 0 MD5 d41d8cd98f00b204e9800998ecf8427e
self.assertSetEqual(frozenset(entries), frozenset(('test.ebuild',)))
self.assertEqual(entries['test.ebuild'].path, 'test.ebuild')
+ def test_assert_directory_verifies(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ m.assert_directory_verifies('')
+
class DuplicateAUXTypeFileEntryTest(TempDirTestCase):
"""
@@ -418,11 +441,13 @@ class DuplicateAUXTypeFileEntryTest(TempDirTestCase):
type (because of path weirdness).
"""
+ DIRS = ['files']
FILES = {
'Manifest': u'''
DATA files/test.patch 0 MD5 d41d8cd98f00b204e9800998ecf8427e
AUX test.patch 0 MD5 d41d8cd98f00b204e9800998ecf8427e
''',
+ 'files/test.patch': u'',
}
def test_find_path_entry(self):
@@ -437,6 +462,11 @@ AUX test.patch 0 MD5 d41d8cd98f00b204e9800998ecf8427e
self.assertSetEqual(frozenset(entries), frozenset(('files/test.patch',)))
self.assertEqual(entries['files/test.patch'].path, 'files/test.patch')
+ def test_assert_directory_verifies(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ m.assert_directory_verifies('')
+
class DuplicateDifferentHashSetFileEntryTest(TempDirTestCase):
"""
@@ -449,6 +479,7 @@ class DuplicateDifferentHashSetFileEntryTest(TempDirTestCase):
DATA test 0 MD5 9e107d9d372bb6826bd81d3542a419d6
DATA test 0 SHA1 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
''',
+ 'test': u'',
}
def test_find_path_entry(self):
@@ -465,6 +496,17 @@ DATA test 0 SHA1 2fd4e1c67a2d28fced849ee1bb76e7391b93eb12
self.assertSetEqual(frozenset(entries['test'].checksums),
frozenset(('MD5', 'SHA1')))
+ def test_assert_directory_verifies(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ with self.assertRaises(gemato.verify.ManifestMismatch) as cm:
+ m.assert_directory_verifies('')
+ self.assertListEqual(cm.exception.diff,
+ [
+ ('MD5', '9e107d9d372bb6826bd81d3542a419d6', 'd41d8cd98f00b204e9800998ecf8427e'),
+ ('SHA1', '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12', 'da39a3ee5e6b4b0d3255bfef95601890afd80709'),
+ ])
+
class DuplicateIncompatibleDataMiscTypeFileEntryTest(TempDirTestCase):
"""
@@ -589,3 +631,30 @@ DATA test.ebuild 0 MD5 9e107d9d372bb6826bd81d3542a419d6
os.path.join(self.dir, 'Manifest'))
self.assertRaises(gemato.recursiveloader.ManifestIncompatibleEntry,
m.get_file_entry_dict, '')
+
+ def test_assert_directory_verifies(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ self.assertRaises(gemato.recursiveloader.ManifestIncompatibleEntry,
+ m.assert_directory_verifies, '')
+
+
+class ManifestIgnoreEntryTest(TempDirTestCase):
+ """
+ Test for a Manifest file with IGNOREs.
+ """
+
+ DIRS = ['bar']
+ FILES = {
+ 'Manifest': u'''
+IGNORE foo
+IGNORE bar
+''',
+ 'foo': u'test',
+ 'bar/baz': u'test',
+ }
+
+ def test_assert_directory_verifies(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ m.assert_directory_verifies('')