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

View as plain text