Skip to content

Commit 3f6b439

Browse files
committed
Avoid loading targets metadata twice
When traversing the delegations tree looking for targets, avoid re-loading already verified targets metadata. Signed-off-by: Teodora Sechkova <[email protected]>
1 parent fa7990c commit 3f6b439

File tree

2 files changed

+32
-3
lines changed

2 files changed

+32
-3
lines changed

tests/test_updater_with_simulator.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
"""Test ngclient Updater using the repository simulator.
77
"""
88

9+
import builtins
910
import os
1011
import sys
1112
import tempfile
1213
import unittest
1314
from typing import Optional, Tuple
15+
from unittest.mock import MagicMock, Mock, patch
1416

1517
from tests import utils
1618
from tests.repository_simulator import RepositorySimulator
@@ -230,6 +232,32 @@ def test_snapshot_rollback_with_local_snapshot_hash_mismatch(self):
230232
with self.assertRaises(BadVersionNumberError):
231233
self._run_refresh()
232234

235+
@patch.object(builtins, "open", wraps=builtins.open)
236+
def test_not_loading_targets_twice(self, wrapped_open: MagicMock):
237+
# Do not load targets roles more than once when traversing
238+
# the delegations tree
239+
240+
# Add new delegated targets, update the snapshot
241+
spec_version = ".".join(SPECIFICATION_VERSION)
242+
targets = Targets(1, spec_version, self.sim.safe_expiry, {}, None)
243+
self.sim.add_delegation("targets", "role1", targets, False, ["*"], None)
244+
self.sim.update_snapshot()
245+
246+
# Run refresh, top-level roles are loaded
247+
updater = self._run_refresh()
248+
# Clean up calls to open during refresh()
249+
wrapped_open.reset_mock()
250+
251+
# First time looking for "somepath", only 'role1' must be loaded
252+
updater.get_targetinfo("somepath")
253+
wrapped_open.assert_called_once_with(
254+
os.path.join(self.metadata_dir, "role1.json"), "rb"
255+
)
256+
wrapped_open.reset_mock()
257+
# Second call to get_targetinfo, all metadata is already loaded
258+
updater.get_targetinfo("somepath")
259+
wrapped_open.assert_not_called()
260+
233261

234262
if __name__ == "__main__":
235263
if "--dump" in sys.argv:

tuf/ngclient/updater.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,10 @@ def _preorder_depth_first_walk(
415415
logger.debug("Skipping visited current role %s", role_name)
416416
continue
417417

418-
# The metadata for 'role_name' must be downloaded/updated before
419-
# its targets, delegations, and child roles can be inspected.
420-
self._load_targets(role_name, parent_role)
418+
# The metadata for 'role_name' must be loaded
419+
# before its targets and delegations can be inspected.
420+
if not self._trusted_set.get(role_name):
421+
self._load_targets(role_name, parent_role)
421422

422423
role_metadata: Targets = self._trusted_set[role_name].signed
423424
target = role_metadata.targets.get(target_filepath)

0 commit comments

Comments
 (0)