fn load_delegations()

in tough/src/lib.rs [1145:1232]


fn load_delegations(
    transport: &dyn Transport,
    snapshot: &Signed<Snapshot>,
    consistent_snapshot: bool,
    metadata_base_url: &Url,
    max_targets_size: u64,
    delegation: &mut Delegations,
    datastore: &Datastore,
) -> Result<()> {
    let mut delegated_roles: HashMap<String, Option<Signed<crate::schema::Targets>>> =
        HashMap::new();
    for delegated_role in &delegation.roles {
        // find the role file metadata
        let role_meta = snapshot
            .signed
            .meta
            .get(&format!("{}.json", &delegated_role.name))
            .context(error::RoleNotInMetaSnafu {
                name: delegated_role.name.clone(),
            })?;

        let path = if consistent_snapshot {
            format!(
                "{}.{}.json",
                &role_meta.version,
                encode_filename(&delegated_role.name)
            )
        } else {
            format!("{}.json", encode_filename(&delegated_role.name))
        };
        let role_url = metadata_base_url.join(&path).context(error::JoinUrlSnafu {
            path: path.clone(),
            url: metadata_base_url.clone(),
        })?;
        let specifier = "max_targets_size parameter";
        // load the role json file
        let reader = Box::new(fetch_max_size(
            transport,
            role_url,
            max_targets_size,
            specifier,
        )?);
        // since each role is a targets, we load them as such
        let role: Signed<crate::schema::Targets> =
            serde_json::from_reader(reader).context(error::ParseMetadataSnafu {
                role: RoleType::Targets,
            })?;
        // verify each role with the delegation
        delegation
            .verify_role(&role, &delegated_role.name)
            .context(error::VerifyMetadataSnafu {
                role: RoleType::Targets,
            })?;
        ensure!(
            role.signed.version == role_meta.version,
            error::VersionMismatchSnafu {
                role: RoleType::Targets,
                fetched: role.signed.version,
                expected: role_meta.version
            }
        );

        datastore.create(&path, &role)?;
        delegated_roles.insert(delegated_role.name.clone(), Some(role));
    }
    // load all roles delegated by this role
    for delegated_role in &mut delegation.roles {
        delegated_role.targets = delegated_roles.remove(&delegated_role.name).context(
            error::DelegatedRolesNotConsistentSnafu {
                name: delegated_role.name.clone(),
            },
        )?;
        if let Some(targets) = &mut delegated_role.targets {
            if let Some(delegations) = &mut targets.signed.delegations {
                load_delegations(
                    transport,
                    snapshot,
                    consistent_snapshot,
                    metadata_base_url,
                    max_targets_size,
                    delegations,
                    datastore,
                )?;
            }
        }
    }
    Ok(())
}