Source file src/cmd/api/run.go

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  
     7  // The run program is invoked via the dist tool.
     8  // To invoke manually: go tool dist test -run api --no-rebuild
     9  package main
    10  
    11  import (
    12  	"errors"
    13  	"fmt"
    14  	exec "internal/execabs"
    15  	"internal/goversion"
    16  	"io/fs"
    17  	"log"
    18  	"os"
    19  	"path/filepath"
    20  	"runtime"
    21  	"strings"
    22  )
    23  
    24  func goCmd() string {
    25  	var exeSuffix string
    26  	if runtime.GOOS == "windows" {
    27  		exeSuffix = ".exe"
    28  	}
    29  	path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
    30  	if _, err := os.Stat(path); err == nil {
    31  		return path
    32  	}
    33  	return "go"
    34  }
    35  
    36  var goroot string
    37  
    38  func main() {
    39  	log.SetFlags(0)
    40  	goroot = os.Getenv("GOROOT") // should be set by run.{bash,bat}
    41  	if goroot == "" {
    42  		log.Fatal("No $GOROOT set.")
    43  	}
    44  
    45  	apiDir := filepath.Join(goroot, "api")
    46  	out, err := exec.Command(goCmd(), "tool", "api",
    47  		"-c", findAPIDirFiles(apiDir),
    48  		allowNew(apiDir),
    49  		"-next", filepath.Join(apiDir, "next.txt"),
    50  		"-except", filepath.Join(apiDir, "except.txt")).CombinedOutput()
    51  	if err != nil {
    52  		log.Fatalf("Error running API checker: %v\n%s", err, out)
    53  	}
    54  	fmt.Print(string(out))
    55  }
    56  
    57  // findAPIDirFiles returns a comma-separated list of Go API files
    58  // (go1.txt, go1.1.txt, etc.) located in apiDir.
    59  func findAPIDirFiles(apiDir string) string {
    60  	dir, err := os.Open(apiDir)
    61  	if err != nil {
    62  		log.Fatal(err)
    63  	}
    64  	defer dir.Close()
    65  	fs, err := dir.Readdirnames(-1)
    66  	if err != nil {
    67  		log.Fatal(err)
    68  	}
    69  	var apiFiles []string
    70  	for _, fn := range fs {
    71  		if strings.HasPrefix(fn, "go1") {
    72  			apiFiles = append(apiFiles, filepath.Join(apiDir, fn))
    73  		}
    74  	}
    75  	return strings.Join(apiFiles, ",")
    76  }
    77  
    78  // allowNew returns the -allow_new flag to use for the 'go tool api' invocation.
    79  func allowNew(apiDir string) string {
    80  	// Verify that the api/go1.n.txt for previous Go version exists.
    81  	// It definitely should, otherwise it's a signal that the logic below may be outdated.
    82  	if _, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version-1))); err != nil {
    83  		log.Fatalln("Problem with api file for previous release:", err)
    84  	}
    85  
    86  	// See whether the api/go1.n.txt for this Go version has been created.
    87  	// (As of April 2021, it gets created during the release of the first Beta.)
    88  	_, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version)))
    89  	if errors.Is(err, fs.ErrNotExist) {
    90  		// It doesn't exist, so we're in development or before Beta 1.
    91  		// At this stage, unmentioned API additions are deemed okay.
    92  		// (They will be quietly shown in API check output, but the test won't fail).
    93  		return "-allow_new=true"
    94  	} else if err == nil {
    95  		// The api/go1.n.txt for this Go version has been created,
    96  		// so we're definitely past Beta 1 in the release cycle.
    97  		//
    98  		// From this point, enforce that api/go1.n.txt is an accurate and complete
    99  		// representation of what's going into the release by failing API check if
   100  		// there are API additions (a month into the freeze, there shouldn't be many).
   101  		//
   102  		// See golang.org/issue/43956.
   103  		return "-allow_new=false"
   104  	} else {
   105  		log.Fatal(err)
   106  	}
   107  	panic("unreachable")
   108  }
   109  

View as plain text