diff --git a/manifest/example_test.go b/manifest/example_test.go index 5dc0b97..c98dd71 100644 --- a/manifest/example_test.go +++ b/manifest/example_test.go @@ -19,7 +19,7 @@ GitFetch: refs/heads/master GitRepo: https://github.com/docker-library/golang.git SharedTags: latest arm64v8-GitRepo: https://github.com/docker-library/golang.git -Architectures: amd64 +Architectures: amd64, amd64 # hi @@ -57,7 +57,7 @@ ppc64le-Directory: 1.5/ppc64le SharedTags: raspbian GitCommit: deadbeefdeadbeefdeadbeefdeadbeefdeadbeef Tags: raspbian-s390x -Architectures: s390x +Architectures: s390x, i386 `))) @@ -115,7 +115,7 @@ i: g@h j // // Tags: raspbian-s390x // SharedTags: raspbian - // Architectures: s390x + // Architectures: i386, s390x // GitCommit: deadbeefdeadbeefdeadbeefdeadbeefdeadbeef // // Shared Tag Groups: diff --git a/manifest/rfc2822.go b/manifest/rfc2822.go index e09fcf5..9bc2a1a 100644 --- a/manifest/rfc2822.go +++ b/manifest/rfc2822.go @@ -8,6 +8,7 @@ import ( "sort" "strings" + "github.com/docker-library/go-dockerlibrary/architecture" "github.com/docker-library/go-dockerlibrary/pkg/stripper" "pault.ag/go/debian/control" @@ -364,11 +365,15 @@ func (manifest *Manifest2822) AddEntry(entry Manifest2822Entry) error { return fmt.Errorf("Tags %q missing one of GitRepo, GitFetch, or GitCommit", entry.TagsString()) } if invalidMaintainers := entry.InvalidMaintainers(); len(invalidMaintainers) > 0 { - return fmt.Errorf("Tags %q has invalid Maintainers: %q (expected format %q)", strings.Join(invalidMaintainers, ", "), MaintainersFormat) + return fmt.Errorf("Tags %q has invalid Maintainers: %q (expected format %q)", entry.TagsString(), strings.Join(invalidMaintainers, ", "), MaintainersFormat) } entry.DeduplicateSharedTags() + if invalidArchitectures := entry.InvalidArchitectures(); len(invalidArchitectures) > 0 { + return fmt.Errorf("Tags %q has invalid Architectures: %q", entry.TagsString(), strings.Join(invalidArchitectures, ", ")) + } + seenTag := map[string]bool{} for _, tag := range entry.Tags { if otherEntry := manifest.GetTag(tag); otherEntry != nil { @@ -428,6 +433,16 @@ func (entry Manifest2822Entry) InvalidMaintainers() []string { return invalid } +func (entry Manifest2822Entry) InvalidArchitectures() []string { + invalid := []string{} + for _, arch := range entry.Architectures { + if _, ok := architecture.SupportedArches[arch]; !ok { + invalid = append(invalid, arch) + } + } + return invalid +} + // DeduplicateSharedTags will remove duplicate values from entry.SharedTags, preserving order. func (entry *Manifest2822Entry) DeduplicateSharedTags() { aggregate := []string{} @@ -442,6 +457,21 @@ func (entry *Manifest2822Entry) DeduplicateSharedTags() { entry.SharedTags = aggregate } +// DeduplicateArchitectures will remove duplicate values from entry.Architectures and sort the result. +func (entry *Manifest2822Entry) DeduplicateArchitectures() { + aggregate := []string{} + seen := map[string]bool{} + for _, arch := range entry.Architectures { + if seen[arch] { + continue + } + seen[arch] = true + aggregate = append(aggregate, arch) + } + sort.Strings(aggregate) + entry.Architectures = aggregate +} + type decoderWrapper struct { *control.Decoder } @@ -471,6 +501,7 @@ func (decoder *decoderWrapper) Decode(entry *Manifest2822Entry) error { if len(entry.Architectures) == 0 { entry.Architectures = arches } + entry.DeduplicateArchitectures() // pull out any new architecture-specific values from Paragraph.Values entry.SeedArchValues() @@ -504,6 +535,9 @@ func Parse2822(readerIn io.Reader) (*Manifest2822, error) { if len(manifest.Global.Tags) > 0 { return nil, fmt.Errorf("global Tags not permitted") } + if invalidArchitectures := manifest.Global.InvalidArchitectures(); len(invalidArchitectures) > 0 { + return nil, fmt.Errorf("invalid global Architectures: %q", strings.Join(invalidArchitectures, ", ")) + } for { entry := manifest.Global.Clone()