39
39
import shutil
40
40
import json
41
41
42
+ from collections import deque
43
+
42
44
import tuf
43
45
import tuf .formats
44
46
import tuf .roledb
@@ -3100,29 +3102,44 @@ def load_repository(repository_directory, repository_name='default',
3100
3102
repository , consistent_snapshot = repo_lib ._load_top_level_metadata (repository ,
3101
3103
filenames , repository_name )
3102
3104
3103
- # Load the delegated targets metadata and generate their fileinfo. The
3104
- # extracted fileinfo is stored in the 'meta' field of the snapshot metadata
3105
- # object.
3105
+ delegated_roles_filenames = repo_lib .get_delegations_filenames (
3106
+ metadata_directory , consistent_snapshot , storage_backend )
3107
+
3108
+ # Load the delegated targets metadata and their fileinfo.
3109
+ # The delegated targets roles form a tree/graph which is traversed in a
3110
+ # breadth-first-search manner starting from 'targets' in order to correctly
3111
+ # load the delegations hierarchy.
3106
3112
targets_objects = {}
3107
3113
targets_objects ['targets' ] = repository .targets
3108
- # A list of delegated-delegating role pairs
3109
- delegations = []
3110
3114
3111
- delegations_filenames = repo_lib .get_delegations_filenames (metadata_directory ,
3112
- consistent_snapshot , storage_backend )
3115
+ # A deque used to keep the next delegation to be loaded
3116
+ delegations = deque ()
3117
+ # A set used to keep the already loaded delegations and avoid an infinite
3118
+ # loop in case of cycles in the graph
3119
+ loaded_delegations = set ()
3113
3120
3114
3121
# Top-level roles are already loaded, fetch targets and get its delegations.
3115
- # Collect a list of delegated-delegating role pairs, starting from the
3116
- # top-level targets: [('role1', 'targets'), ('role2', 'targets'), ... ]
3122
+ # Store the delegations in the form of delegated-delegating role tuples,
3123
+ # starting from the top-level targets:
3124
+ # [('role1', 'targets'), ('role2', 'targets'), ... ]
3117
3125
roleinfo = tuf .roledb .get_roleinfo ('targets' , repository_name )
3118
3126
for role in roleinfo ['delegations' ]['roles' ]:
3119
- delegations .append ([ role ['name' ], 'targets' ] )
3127
+ delegations .append (( role ['name' ], 'targets' ) )
3120
3128
3121
- # Load the delegated roles by starting from 'targets' and continuously
3122
- # appending the next level delegations to the list
3123
- for rolename , delegating_role in delegations :
3124
- metadata_path = delegations_filenames [rolename ]
3129
+ # Traverse the graph by appending the next delegation to the deque and
3130
+ # 'pop'-ing and loading the left-most element.
3131
+ while delegations :
3132
+ rolename , delegating_role = delegations .popleft ()
3133
+ if (rolename , delegating_role ) in loaded_delegations :
3134
+ continue
3125
3135
3136
+ # Instead of adding only rolename to the set, store the already loaded
3137
+ # delegated-delegating role tuples. This way a delegated role is added
3138
+ # to each of its delegating roles but when the role is reached twice
3139
+ # from the same delegating role an infinite loop is avoided.
3140
+ loaded_delegations .add ((rolename , delegating_role ))
3141
+
3142
+ metadata_path = delegated_roles_filenames [rolename ]
3126
3143
signable = None
3127
3144
3128
3145
try :
@@ -3149,8 +3166,6 @@ def load_repository(repository_directory, repository_name='default',
3149
3166
roleinfo ['paths' ] = metadata_object ['targets' ]
3150
3167
roleinfo ['delegations' ] = metadata_object ['delegations' ]
3151
3168
3152
- tuf .roledb .add_role (rolename , roleinfo , repository_name )
3153
-
3154
3169
# Generate the Targets object of the delegated role,
3155
3170
# add it to the top-level 'targets' object and to its
3156
3171
# direct delegating role object.
@@ -3165,10 +3180,10 @@ def load_repository(repository_directory, repository_name='default',
3165
3180
targets_objects [delegating_role ].add_delegated_role (rolename ,
3166
3181
new_targets_object )
3167
3182
3168
- # Append the next level delegations to the list :
3183
+ # Append the next level delegations to the deque :
3169
3184
# the 'delegated' role becomes the 'delegating'
3170
3185
for delegation in metadata_object ['delegations' ]['roles' ]:
3171
- delegations .append ([ delegation ['name' ], rolename ] )
3186
+ delegations .append (( delegation ['name' ], rolename ) )
3172
3187
3173
3188
# Extract the keys specified in the delegations field of the Targets
3174
3189
# role. Add 'key_object' to the list of recognized keys. Keys may be
0 commit comments