Source file src/cmd/go/testdata/addmod.go

     1  // Copyright 2018 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  // Addmod adds a module as a txtar archive to the testdata/mod directory.
     9  //
    10  // Usage:
    11  //
    12  //	go run addmod.go path@version...
    13  //
    14  // It should only be used for very small modules - we do not want to check
    15  // very large files into testdata/mod.
    16  //
    17  // It is acceptable to edit the archive afterward to remove or shorten files.
    18  // See mod/README for more information.
    19  //
    20  package main
    21  
    22  import (
    23  	"bytes"
    24  	"flag"
    25  	"fmt"
    26  	exec "internal/execabs"
    27  	"io/fs"
    28  	"log"
    29  	"os"
    30  	"path/filepath"
    31  	"strings"
    32  
    33  	"golang.org/x/tools/txtar"
    34  )
    35  
    36  func usage() {
    37  	fmt.Fprintf(os.Stderr, "usage: go run addmod.go path@version...\n")
    38  	os.Exit(2)
    39  }
    40  
    41  var tmpdir string
    42  
    43  func fatalf(format string, args ...any) {
    44  	os.RemoveAll(tmpdir)
    45  	log.Fatalf(format, args...)
    46  }
    47  
    48  const goCmd = "go"
    49  
    50  func main() {
    51  	flag.Usage = usage
    52  	flag.Parse()
    53  	if flag.NArg() == 0 {
    54  		usage()
    55  	}
    56  
    57  	log.SetPrefix("addmod: ")
    58  	log.SetFlags(0)
    59  
    60  	var err error
    61  	tmpdir, err = os.MkdirTemp("", "addmod-")
    62  	if err != nil {
    63  		log.Fatal(err)
    64  	}
    65  
    66  	run := func(command string, args ...string) string {
    67  		cmd := exec.Command(command, args...)
    68  		cmd.Dir = tmpdir
    69  		var stderr bytes.Buffer
    70  		cmd.Stderr = &stderr
    71  		out, err := cmd.Output()
    72  		if err != nil {
    73  			fatalf("%s %s: %v\n%s", command, strings.Join(args, " "), err, stderr.Bytes())
    74  		}
    75  		return string(out)
    76  	}
    77  
    78  	gopath := strings.TrimSpace(run("go", "env", "GOPATH"))
    79  	if gopath == "" {
    80  		fatalf("cannot find GOPATH")
    81  	}
    82  
    83  	exitCode := 0
    84  	for _, arg := range flag.Args() {
    85  		if err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte("module m\n"), 0666); err != nil {
    86  			fatalf("%v", err)
    87  		}
    88  		run(goCmd, "get", "-d", arg)
    89  		path := arg
    90  		if i := strings.Index(path, "@"); i >= 0 {
    91  			path = path[:i]
    92  		}
    93  		out := run(goCmd, "list", "-m", "-f={{.Path}} {{.Version}} {{.Dir}}", path)
    94  		f := strings.Fields(out)
    95  		if len(f) != 3 {
    96  			log.Printf("go list -m %s: unexpected output %q", arg, out)
    97  			exitCode = 1
    98  			continue
    99  		}
   100  		path, vers, dir := f[0], f[1], f[2]
   101  		mod, err := os.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".mod"))
   102  		if err != nil {
   103  			log.Printf("%s: %v", arg, err)
   104  			exitCode = 1
   105  			continue
   106  		}
   107  		info, err := os.ReadFile(filepath.Join(gopath, "pkg/mod/cache/download", path, "@v", vers+".info"))
   108  		if err != nil {
   109  			log.Printf("%s: %v", arg, err)
   110  			exitCode = 1
   111  			continue
   112  		}
   113  
   114  		a := new(txtar.Archive)
   115  		title := arg
   116  		if !strings.Contains(arg, "@") {
   117  			title += "@" + vers
   118  		}
   119  		a.Comment = []byte(fmt.Sprintf("module %s\n\n", title))
   120  		a.Files = []txtar.File{
   121  			{Name: ".mod", Data: mod},
   122  			{Name: ".info", Data: info},
   123  		}
   124  		dir = filepath.Clean(dir)
   125  		err = filepath.WalkDir(dir, func(path string, info fs.DirEntry, err error) error {
   126  			if !info.Type().IsRegular() {
   127  				return nil
   128  			}
   129  			name := info.Name()
   130  			if name == "go.mod" || strings.HasSuffix(name, ".go") {
   131  				data, err := os.ReadFile(path)
   132  				if err != nil {
   133  					return err
   134  				}
   135  				a.Files = append(a.Files, txtar.File{Name: strings.TrimPrefix(path, dir+string(filepath.Separator)), Data: data})
   136  			}
   137  			return nil
   138  		})
   139  		if err != nil {
   140  			log.Printf("%s: %v", arg, err)
   141  			exitCode = 1
   142  			continue
   143  		}
   144  
   145  		data := txtar.Format(a)
   146  		target := filepath.Join("mod", strings.ReplaceAll(path, "/", "_")+"_"+vers+".txt")
   147  		if err := os.WriteFile(target, data, 0666); err != nil {
   148  			log.Printf("%s: %v", arg, err)
   149  			exitCode = 1
   150  			continue
   151  		}
   152  	}
   153  	os.RemoveAll(tmpdir)
   154  	os.Exit(exitCode)
   155  }
   156  

View as plain text