From 2d69c2f2cd43fea3e4d153b3853a2eacf8aeac67 Mon Sep 17 00:00:00 2001 From: Michał Górny Date: Fri, 27 Oct 2017 20:23:27 +0200 Subject: recursiveloader: Iterate over Manifests from most specific first Ensure that when iterating over Manifests, the more specific paths will come before the less specific. It is important for updates since changes to deeper Manifests will affect their checksums in higher Manifests. --- gemato/recursiveloader.py | 8 +++++++- tests/test_recursiveloader.py | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gemato/recursiveloader.py b/gemato/recursiveloader.py index 659049b..96a5365 100644 --- a/gemato/recursiveloader.py +++ b/gemato/recursiveloader.py @@ -65,8 +65,14 @@ class ManifestRecursiveLoader(object): Iterate over loaded Manifests that can apply to path. If @recursive is True, returns also Manifests for subdirectories of @path. Yields a tuple of (relative_path, manifest). + + The function guarantees that the Manifests for subdirectories + (more specific) will always be returned before the Manifests + for parent directories. The order is otherwise undefined. """ - for k, v in self.loaded_manifests.items(): + for k, v in sorted(self.loaded_manifests.items(), + key=lambda x: len(x[0]), + reverse=True): d = os.path.dirname(k) if gemato.util.path_starts_with(path, d): yield (d, v) diff --git a/tests/test_recursiveloader.py b/tests/test_recursiveloader.py index 8eac573..29bfb0f 100644 --- a/tests/test_recursiveloader.py +++ b/tests/test_recursiveloader.py @@ -75,6 +75,26 @@ DATA test 0 MD5 d41d8cd98f00b204e9800998ecf8427e self.assertIn('sub/deeper/Manifest', m.loaded_manifests) self.assertIn('other/Manifest', m.loaded_manifests) + def test__iter_manifests_for_path_order(self): + m = gemato.recursiveloader.ManifestRecursiveLoader( + os.path.join(self.dir, 'Manifest')) + m.load_manifests_for_path('', recursive=True) + self.assertListEqual([d for d, k + in m._iter_manifests_for_path('sub/deeper')], + ['sub/deeper', 'sub', '']) + self.assertListEqual([d for d, k + in m._iter_manifests_for_path('other')], + ['other', '']) + + def test__iter_manifests_for_path_recursively_order(self): + m = gemato.recursiveloader.ManifestRecursiveLoader( + os.path.join(self.dir, 'Manifest')) + m.load_manifests_for_path('', recursive=True) + self.assertListEqual([d for d, k + in m._iter_manifests_for_path('sub', + recursive=True)], + ['sub/deeper', 'sub', '']) + def test_load_sub_manifest_recursively(self): m = gemato.recursiveloader.ManifestRecursiveLoader( os.path.join(self.dir, 'Manifest')) -- cgit v1.2.3