// ListTargets lists all targets for the current repository. The list of // roles should be passed in order from highest to lowest priority. // // IMPORTANT: if you pass a set of roles such as [ "targets/a", "targets/x" // "targets/a/b" ], even though "targets/a/b" is part of the "targets/a" subtree // its entries will be strictly shadowed by those in other parts of the "targets/a" // subtree and also the "targets/x" subtree, as we will defer parsing it until // we explicitly reach it in our iteration of the provided list of roles. func (r *NotaryRepository) ListTargets(roles ...string) ([]*TargetWithRole, error) { if err := r.Update(false); err != nil { return nil, err } if len(roles) == 0 { roles = []string{data.CanonicalTargetsRole} } targets := make(map[string]*TargetWithRole) for _, role := range roles { // Define an array of roles to skip for this walk (see IMPORTANT comment above) skipRoles := utils.StrSliceRemove(roles, role) // Define a visitor function to populate the targets map in priority order listVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} { // We found targets so we should try to add them to our targets map for targetName, targetMeta := range tgt.Signed.Targets { // Follow the priority by not overriding previously set targets // and check that this path is valid with this role if _, ok := targets[targetName]; ok || !validRole.CheckPaths(targetName) { continue } targets[targetName] = &TargetWithRole{ Target: Target{ Name: targetName, Hashes: targetMeta.Hashes, Length: targetMeta.Length, }, Role: validRole.Name, } } return nil } r.tufRepo.WalkTargets("", role, listVisitorFunc, skipRoles...) } var targetList []*TargetWithRole for _, v := range targets { targetList = append(targetList, v) } return targetList, nil }
// GetTargetByName returns a target given a name. If no roles are passed // it uses the targets role and does a search of the entire delegation // graph, finding the first entry in a breadth first search of the delegations. // If roles are passed, they should be passed in descending priority and // the target entry found in the subtree of the highest priority role // will be returned // See the IMPORTANT section on ListTargets above. Those roles also apply here. func (r *NotaryRepository) GetTargetByName(name string, roles ...string) (*TargetWithRole, error) { _, err := r.Update(false) if err != nil { return nil, err } if len(roles) == 0 { roles = append(roles, data.CanonicalTargetsRole) } var resultMeta data.FileMeta var resultRoleName string var foundTarget bool for _, role := range roles { // Define an array of roles to skip for this walk (see IMPORTANT comment above) skipRoles := utils.StrSliceRemove(roles, role) // Define a visitor function to find the specified target getTargetVisitorFunc := func(tgt *data.SignedTargets, validRole data.DelegationRole) interface{} { if tgt == nil { return nil } // We found the target and validated path compatibility in our walk, // so we should stop our walk and set the resultMeta and resultRoleName variables if resultMeta, foundTarget = tgt.Signed.Targets[name]; foundTarget { resultRoleName = validRole.Name return tuf.StopWalk{} } return nil } err = r.tufRepo.WalkTargets(name, role, getTargetVisitorFunc, skipRoles...) // Check that we didn't error, and that we assigned to our target if err == nil && foundTarget { return &TargetWithRole{Target: Target{Name: name, Hashes: resultMeta.Hashes, Length: resultMeta.Length}, Role: resultRoleName}, nil } } return nil, fmt.Errorf("No trust data for %s", name) }