// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This file contains tests applied to the archives before they are written. package main import ( "bytes" "fmt" "log" "os" "path" "path/filepath" "strings" ) type testRule struct { name string goos string exclude bool } var srcRules = []testRule{ {name: "go/VERSION"}, {name: "go/src/cmd/go/main.go"}, {name: "go/src/bytes/bytes.go"}, {name: "**/.DS_Store", exclude: true}, {name: "go/.git", exclude: true}, {name: "go/.gitattributes", exclude: true}, {name: "go/.github", exclude: true}, {name: "go/VERSION.cache", exclude: true}, {name: "go/bin/**", exclude: true}, {name: "go/pkg/**", exclude: true}, {name: "go/src/cmd/dist/dist", exclude: true}, {name: "go/src/cmd/dist/dist.exe", exclude: true}, {name: "go/src/runtime/internal/sys/zversion.go", exclude: true}, {name: "go/src/time/tzdata/zzipdata.go", exclude: true}, } var zipRules = []testRule{ {name: "go/VERSION"}, {name: "go/src/cmd/go/main.go"}, {name: "go/src/bytes/bytes.go"}, {name: "**/.DS_Store", exclude: true}, {name: "go/.git", exclude: true}, {name: "go/.gitattributes", exclude: true}, {name: "go/.github", exclude: true}, {name: "go/VERSION.cache", exclude: true}, {name: "go/bin", exclude: true}, {name: "go/pkg", exclude: true}, {name: "go/src/cmd/dist/dist", exclude: true}, {name: "go/src/cmd/dist/dist.exe", exclude: true}, {name: "go/bin/go", goos: "linux"}, {name: "go/bin/go", goos: "darwin"}, {name: "go/bin/go", goos: "windows", exclude: true}, {name: "go/bin/go.exe", goos: "windows"}, {name: "go/bin/gofmt", goos: "linux"}, {name: "go/bin/gofmt", goos: "darwin"}, {name: "go/bin/gofmt", goos: "windows", exclude: true}, {name: "go/bin/gofmt.exe", goos: "windows"}, {name: "go/pkg/tool/*/compile", goos: "linux"}, {name: "go/pkg/tool/*/compile", goos: "darwin"}, {name: "go/pkg/tool/*/compile", goos: "windows", exclude: true}, {name: "go/pkg/tool/*/compile.exe", goos: "windows"}, } var modRules = []testRule{ {name: "golang.org/toolchain@*/VERSION"}, {name: "golang.org/toolchain@*/src/cmd/go/main.go"}, {name: "golang.org/toolchain@*/src/bytes/bytes.go"}, {name: "**/.DS_Store", exclude: true}, {name: "golang.org/toolchain@*/.git", exclude: true}, {name: "golang.org/toolchain@*/.gitattributes", exclude: true}, {name: "golang.org/toolchain@*/.github", exclude: true}, {name: "golang.org/toolchain@*/VERSION.cache", exclude: true}, {name: "golang.org/toolchain@*/bin", exclude: true}, {name: "golang.org/toolchain@*/pkg", exclude: true}, {name: "golang.org/toolchain@*/src/cmd/dist/dist", exclude: true}, {name: "golang.org/toolchain@*/src/cmd/dist/dist.exe", exclude: true}, {name: "golang.org/toolchain@*/bin/go", goos: "linux"}, {name: "golang.org/toolchain@*/bin/go", goos: "darwin"}, {name: "golang.org/toolchain@*/bin/go", goos: "windows", exclude: true}, {name: "golang.org/toolchain@*/bin/go.exe", goos: "windows"}, {name: "golang.org/toolchain@*/bin/gofmt", goos: "linux"}, {name: "golang.org/toolchain@*/bin/gofmt", goos: "darwin"}, {name: "golang.org/toolchain@*/bin/gofmt", goos: "windows", exclude: true}, {name: "golang.org/toolchain@*/bin/gofmt.exe", goos: "windows"}, {name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "linux"}, {name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "darwin"}, {name: "golang.org/toolchain@*/pkg/tool/*/compile", goos: "windows", exclude: true}, {name: "golang.org/toolchain@*/pkg/tool/*/compile.exe", goos: "windows"}, // go.mod are renamed to _go.mod. {name: "**/go.mod", exclude: true}, {name: "**/_go.mod"}, } func testSrc(a *Archive) { test("source", a, srcRules) // Check that no generated files slip in, even if new ones are added. for _, f := range a.Files { if strings.HasPrefix(path.Base(f.Name), "z") { data, err := os.ReadFile(filepath.Join(goroot, strings.TrimPrefix(f.Name, "go/"))) if err != nil { log.Fatalf("checking source archive: %v", err) } if strings.Contains(string(data), "generated by go tool dist; DO NOT EDIT") { log.Fatalf("unexpected source archive file: %s (generated by dist)", f.Name) } } } } func testZip(a *Archive) { test("binary", a, zipRules) } func testMod(a *Archive) { test("module", a, modRules) } func test(kind string, a *Archive, rules []testRule) { ok := true have := make([]bool, len(rules)) for _, f := range a.Files { for i, r := range rules { if r.goos != "" && r.goos != goos { continue } match, err := amatch(r.name, f.Name) if err != nil { log.Fatal(err) } if match { if r.exclude { ok = false if !have[i] { log.Printf("unexpected %s archive file: %s", kind, f.Name) have[i] = true // silence future prints for excluded directory } } else { have[i] = true } } } } missing := false for i, r := range rules { if r.goos != "" && r.goos != goos { continue } if !r.exclude && !have[i] { missing = true log.Printf("missing %s archive file: %s", kind, r.name) } } if missing { ok = false var buf bytes.Buffer for _, f := range a.Files { fmt.Fprintf(&buf, "\n\t%s", f.Name) } log.Printf("archive contents: %d files%s", len(a.Files), buf.Bytes()) } if !ok { log.Fatalf("bad archive file") } }