Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/api/run.go

Documentation: cmd/api

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

View as plain text