import (
"io"
+ "io/fs"
"os"
"path/filepath"
"strings"
return err
}
- return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
+ return filepath.WalkDir(srcRoot, func(srcPath string, entry fs.DirEntry, err error) error {
if err != nil || srcPath == srcRoot {
return err
}
+ if filepath.Base(srcPath) == "testdata" {
+ // We're just building, so no need to copy those.
+ return fs.SkipDir
+ }
suffix := strings.TrimPrefix(srcPath, srcRoot)
for len(suffix) > 0 && suffix[0] == filepath.Separator {
}
dstPath := filepath.Join(dstRoot, suffix)
+ info, err := entry.Info()
perm := info.Mode() & os.ModePerm
if info.Mode()&os.ModeSymlink != 0 {
info, err = os.Stat(srcPath)
perm = info.Mode() & os.ModePerm
}
- // Always copy directories (don't symlink them).
+ // Always make copies of directories.
// If we add a file in the overlay, we don't want to add it in the original.
if info.IsDir() {
return os.MkdirAll(dstPath, perm|0200)
}
- // If the OS supports symlinks, use them instead of copying bytes.
- if err := os.Symlink(srcPath, dstPath); err == nil {
+ // If we can use a hard link, do that instead of copying bytes.
+ // Go builds don't like symlinks in some cases, such as go:embed.
+ if err := os.Link(srcPath, dstPath); err == nil {
return nil
}
"path/filepath"
"runtime"
"testing"
+ "time"
)
func TestRepeatBootstrap(t *testing.T) {
t.Skipf("skipping test that rebuilds the entire toolchain")
}
- goroot, err := os.MkdirTemp("", "reboot-goroot")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(goroot)
+ goroot := t.TempDir()
gorootSrc := filepath.Join(goroot, "src")
+ overlayStart := time.Now()
if err := overlayDir(gorootSrc, filepath.Join(runtime.GOROOT(), "src")); err != nil {
t.Fatal(err)
}
+ t.Logf("GOROOT/src overlay set up in %s", time.Since(overlayStart))
if err := os.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
t.Fatal(err)