download all delegated roles when doing downloadTargets

Signed-off-by: David Lawrence <david.lawrence@docker.com> (github: endophage)
This commit is contained in:
David Lawrence 2015-12-15 15:15:37 -08:00
parent 90e22ff5ff
commit 33d39afdf5
2 changed files with 96 additions and 26 deletions

View File

@ -369,9 +369,17 @@ func (c *Client) downloadSnapshot() error {
return nil return nil
} }
// downloadTargets is responsible for downloading any targets file // downloadTargets downloads all targets and delegated targets for the repository.
// including delegates roles. // It uses a pre-order tree traversal as it's necessary to download parents first
// to obtain the keys to validate children.
func (c *Client) downloadTargets(role string) error { func (c *Client) downloadTargets(role string) error {
stack := utils.NewStack()
stack.Push(role)
for !stack.Empty() {
role, err := stack.PopString()
if err != nil {
return err
}
role = data.RoleName(role) // this will really only do something for base targets role role = data.RoleName(role) // this will really only do something for base targets role
if c.local.Snapshot == nil { if c.local.Snapshot == nil {
return ErrMissingMeta{role: role} return ErrMissingMeta{role: role}
@ -397,6 +405,11 @@ func (c *Client) downloadTargets(role string) error {
return err return err
} }
// push delegated roles contained in the targets file onto the stack
for _, r := range t.Signed.Delegations.Roles {
stack.Push(r.Name)
}
}
return nil return nil
} }

57
tuf/utils/stack.go Normal file
View File

@ -0,0 +1,57 @@
package utils
import (
"fmt"
)
type ErrEmptyStack struct {
action string
}
func (err ErrEmptyStack) Error() string {
return fmt.Sprintf("attempted to %s with empty stack", err.action)
}
type ErrBadTypeCast struct{}
func (err ErrBadTypeCast) Error() string {
return "attempted to do a typed pop and item was not of type"
}
type Stack []interface{}
func NewStack() *Stack {
s := make(Stack, 0)
return &s
}
func (s *Stack) Push(item interface{}) {
*s = append(*s, item)
}
func (s *Stack) Pop() (interface{}, error) {
l := len(*s)
if l > 0 {
item := (*s)[l-1]
*s = (*s)[:l-1]
return item, nil
}
return nil, ErrEmptyStack{action: "pop"}
}
func (s *Stack) PopString() (string, error) {
l := len(*s)
if l > 0 {
item := (*s)[l-1]
if item, ok := item.(string); ok {
*s = (*s)[:l-1]
return item, nil
}
return "", ErrBadTypeCast{}
}
return "", ErrEmptyStack{action: "pop"}
}
func (s Stack) Empty() bool {
return len(s) == 0
}