summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gemato/recursiveloader.py64
-rw-r--r--tests/test_recursiveloader.py42
2 files changed, 87 insertions, 19 deletions
diff --git a/gemato/recursiveloader.py b/gemato/recursiveloader.py
index 52628ad..9008b65 100644
--- a/gemato/recursiveloader.py
+++ b/gemato/recursiveloader.py
@@ -704,7 +704,12 @@ class ManifestRecursiveLoader(object):
entry_dict = self.get_deduplicated_file_entry_dict_for_update(
path)
- dir_manifest_stack = []
+ manifest_stack = []
+ for mpath, mrpath, m in (self
+ ._iter_manifests_for_path(path)):
+ manifest_stack.append(mpath)
+ break
+
it = os.walk(os.path.join(self.root_directory, path),
onerror=gemato.util.throw_exception,
followlinks=True)
@@ -715,6 +720,11 @@ class ManifestRecursiveLoader(object):
if relpath == '.':
relpath = ''
+ # drop Manifest paths until we get to a common directory
+ while not gemato.util.path_starts_with(relpath,
+ os.path.dirname(manifest_stack[-1])):
+ manifest_stack.pop()
+
skip_dirs = []
for d in dirnames:
# skip dotfiles
@@ -766,7 +776,8 @@ class ManifestRecursiveLoader(object):
entry_dict.update(
self.get_deduplicated_file_entry_dict_for_update(
relpath))
- dir_manifest = None
+
+ new_entries = []
for f in filenames:
# skip dotfiles
@@ -778,6 +789,8 @@ class ManifestRecursiveLoader(object):
if fe is not None:
if fe.tag in ('IGNORE', 'OPTIONAL'):
continue
+ if fe.tag == 'MANIFEST':
+ manifest_stack.append(fpath)
else:
# skip top-level Manifest, we obviously can't have
# an entry for it
@@ -785,34 +798,47 @@ class ManifestRecursiveLoader(object):
continue
if f in new_manifests:
cls = gemato.manifest.ManifestEntryMANIFEST
- # new Manifests go into the parent directory
- for mpath, mrpath, m in (self
- ._iter_manifests_for_path(
- os.path.dirname(relpath))):
- break
+ manifest_stack.append(fpath)
else:
cls = gemato.manifest.ManifestEntryDATA
- # find appropriate Manifest for this directory
- if dir_manifest is None:
- for mpath, mrpath, m in (self
- ._iter_manifests_for_path(fpath)):
- dir_manifest = (mpath, mrpath, m)
- break
- else:
- mpath, mrpath, m = dir_manifest
- fe = cls(os.path.relpath(fpath, mrpath), 0, {})
- m.entries.append(fe)
+ # note: .path needs to be corrected below
+ fe = cls(fpath, 0, {})
+ new_entries.append(fe)
- # update the existing entry
changed = gemato.verify.update_entry_for_path(
os.path.join(dirpath, f),
fe,
hashes=hashes,
expected_dev=self.manifest_device)
- if changed:
+ if changed and mpath is not None:
self.updated_manifests.add(mpath)
+ if new_entries:
+ mpath = manifest_stack[-1]
+ m = self.loaded_manifests[mpath]
+ mdirpath = os.path.dirname(mpath)
+ for fe in new_entries:
+ if fe.tag == 'MANIFEST':
+ # Manifest needs to go level up
+ mmpath = mpath
+ mm = m
+ mmdirpath = mdirpath
+ i = -1
+ while gemato.util.path_starts_with(fe.path, mmpath):
+ i -= 1
+ mmpath = manifest_stack[i]
+ mm = self.loaded_manifests[mmpath]
+ mmdirpath = os.path.dirname(mmpath)
+
+ fe.path = os.path.relpath(fe.path, mmdirpath)
+ mm.entries.append(fe)
+ self.updated_manifests.add(mmpath)
+ else:
+ fe.path = os.path.relpath(fe.path, mdirpath)
+ m.entries.append(fe)
+ self.updated_manifests.add(mpath)
+
# check for removed files
for relpath, me in entry_dict.items():
mpath, fe = me
diff --git a/tests/test_recursiveloader.py b/tests/test_recursiveloader.py
index cc4d3b9..c3263db 100644
--- a/tests/test_recursiveloader.py
+++ b/tests/test_recursiveloader.py
@@ -2555,3 +2555,45 @@ class CreateNewCompressedManifestTest(TempDirTestCase):
os.path.join(self.dir, 'Manifest.gz')))
self.assertTrue(os.path.exists(
os.path.join(self.dir, 'Manifest')))
+
+
+class MultipleDeepNestedManifestTest(TempDirTestCase):
+ DIRS = ['a', 'a/x', 'a/y', 'a/z', 'b']
+ FILES = {
+ 'Manifest': u'''
+MANIFEST a/Manifest 119 MD5 6956767cfbb3276adbdce86cca559719
+MANIFEST b/Manifest 0 MD5 d41d8cd98f00b204e9800998ecf8427e
+''',
+ 'test': u'',
+ 'a/Manifest': u'''
+MANIFEST x/Manifest 0 MD5 d41d8cd98f00b204e9800998ecf8427e
+MANIFEST z/Manifest 0 MD5 d41d8cd98f00b204e9800998ecf8427e
+''',
+ 'a/test': u'',
+ 'a/x/Manifest': u'',
+ 'a/x/test': u'',
+ 'a/y/test': u'',
+ 'a/z/Manifest': u'',
+ 'a/z/test': u'',
+ 'b/Manifest': u'',
+ 'b/test': u'',
+ }
+
+ def test_update_entries_for_directory(self):
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'))
+ m.update_entries_for_directory('', hashes=['SHA256', 'SHA512'])
+ m.save_manifests()
+ m.assert_directory_verifies()
+
+ def test_update_entries_for_directory_without_manifests(self):
+ for dirpath, dirs, files in os.walk(self.dir):
+ if 'Manifest' in files:
+ os.unlink(os.path.join(dirpath, 'Manifest'))
+
+ m = gemato.recursiveloader.ManifestRecursiveLoader(
+ os.path.join(self.dir, 'Manifest'),
+ allow_create=True)
+ m.update_entries_for_directory('', hashes=['SHA256', 'SHA512'])
+ m.save_manifests()
+ m.assert_directory_verifies()