golang.org/x/build@v0.0.0-20240506185731-218518f32b70/update-readmes.go (about)

     1  // Copyright 2017 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 update-readmes.go tool creates or updates README.md files in
     8  // the golang.org/x/build tree. It only updates files if they are
     9  // missing or were previously generated by this tool. If the file
    10  // contains a "<!-- End of auto-generated section -->" comment,
    11  // the tool leaves content in the rest of the file unmodified.
    12  //
    13  // The auto-generated Markdown contains the package doc synopsis
    14  // and a link to pkg.go.dev for the API reference.
    15  package main
    16  
    17  import (
    18  	"bytes"
    19  	"fmt"
    20  	"go/build"
    21  	"log"
    22  	"os"
    23  	"path/filepath"
    24  	"strings"
    25  )
    26  
    27  func main() {
    28  	root, err := build.Import("golang.org/x/build", "", build.FindOnly)
    29  	if err != nil {
    30  		log.Fatalf("failed to find golang.org/x/build root: %v", err)
    31  	}
    32  	err = filepath.Walk(root.Dir, func(path string, fi os.FileInfo, err error) error {
    33  		if err != nil {
    34  			return err
    35  		}
    36  		if !fi.IsDir() {
    37  			return nil
    38  		}
    39  		rest := strings.TrimPrefix(strings.TrimPrefix(path, root.Dir), "/")
    40  		switch rest {
    41  		case "env", "version", "vendor":
    42  			return filepath.SkipDir
    43  		}
    44  		pkgName := "golang.org/x/build/" + filepath.ToSlash(rest)
    45  
    46  		bctx := build.Default
    47  		bctx.Dir = path // Set Dir since some x/build packages are in nested modules.
    48  		pkg, err := bctx.Import(pkgName, "", 0)
    49  		if err != nil {
    50  			// Skip.
    51  			return nil
    52  		}
    53  		if pkg.Doc == "" {
    54  			// There's no package comment, so don't create an empty README.
    55  			return nil
    56  		}
    57  		if _, err := os.Stat(filepath.Join(pkg.Dir, "README")); err == nil {
    58  			// Directory has exiting README; don't touch.
    59  			return nil
    60  		}
    61  		readmePath := filepath.Join(pkg.Dir, "README.md")
    62  		exist, err := os.ReadFile(readmePath)
    63  		if err != nil && !os.IsNotExist(err) {
    64  			// A real error.
    65  			return err
    66  		}
    67  		const header = "Auto-generated by x/build/update-readmes.go"
    68  		if len(exist) > 0 && !bytes.Contains(exist, []byte(header)) {
    69  			return nil
    70  		}
    71  		var footer []byte
    72  		if i := bytes.Index(exist, []byte("<!-- End of auto-generated section -->")); i != -1 {
    73  			footer = exist[i:]
    74  		}
    75  		newContents := []byte(fmt.Sprintf(`<!-- %s -->
    76  
    77  [![Go Reference](https://pkg.go.dev/badge/%s.svg)](https://pkg.go.dev/%s)
    78  
    79  # %s
    80  
    81  %s
    82  %s`, header, pkgName, pkgName, pkgName, pkg.Doc, footer))
    83  		if bytes.Equal(exist, newContents) {
    84  			return nil
    85  		}
    86  		if err := os.WriteFile(readmePath, newContents, 0644); err != nil {
    87  			return err
    88  		}
    89  		log.Printf("Wrote %s", readmePath)
    90  		return nil
    91  	})
    92  	if err != nil {
    93  		log.Fatal(err)
    94  	}
    95  }