| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // The makeroot.go script copies a GOROOT. It is a precursor to makefuchsia.go, |
| // used to stage a clean GOROOT into the build directory. |
| // Note: this script exists because the `go` tool globs for inputs, as such, a |
| // copy tool is required that will actively remove files that are not found in |
| // the source. |
| |
| package main |
| |
| import ( |
| "bytes" |
| "flag" |
| "io" |
| "log" |
| "os" |
| "os/exec" |
| "path/filepath" |
| "time" |
| ) |
| |
| var ( |
| sourceGoroot = flag.String("source-goroot", "", "GOROOT to copy from") |
| targetGoroot = flag.String("target-goroot", "", "GOROOT to copy into") |
| depfilePath = flag.String("depfile", "", "depfile to write into") |
| stampPath = flag.String("stamp-file", "", "Path of a file to create upon completion") |
| ) |
| |
| func main() { |
| log.SetFlags(log.Lshortfile) |
| flag.Parse() |
| |
| if err := os.RemoveAll(*targetGoroot); err != nil { |
| log.Fatal(err) |
| } |
| |
| var buf bytes.Buffer |
| buf.WriteString(*stampPath) |
| buf.WriteByte(':') |
| |
| git, err := exec.LookPath("git") |
| if err != nil { |
| log.Fatal(err) |
| } |
| cmd := exec.Command(git, "--no-optional-locks", "-C", *sourceGoroot, "ls-files", "--cached", "--others", "--exclude-standard", "-z") |
| out, err := cmd.Output() |
| if err != nil { |
| log.Fatal(err) |
| } |
| for _, path := range bytes.Split(out, []byte{0}) { |
| if len(path) == 0 { |
| continue |
| } |
| path := string(path) |
| src := filepath.Join(*sourceGoroot, path) |
| dst := filepath.Join(*targetGoroot, path) |
| srcFile, err := os.Open(src) |
| if err != nil { |
| // Renaming or deleting files will cause git ls-files to return the old (or deleted) |
| // paths unless the change is staged, so ignore these errors. |
| if os.IsNotExist(err) { |
| log.Print("could not open file: ", src) |
| continue |
| } |
| log.Fatal(err) |
| } |
| dstDir := filepath.Dir(dst) |
| if _, err := os.Stat(dstDir); os.IsNotExist(err) { |
| info, err := os.Stat(filepath.Dir(src)) |
| if err != nil { |
| log.Fatal(err) |
| } |
| if err := os.MkdirAll(dstDir, info.Mode()); err != nil { |
| log.Fatal(err) |
| } |
| } else if err != nil { |
| log.Fatal(err) |
| } |
| info, err := srcFile.Stat() |
| if err != nil { |
| log.Fatal(err) |
| } |
| dstFile, err := os.OpenFile(dst, os.O_WRONLY|os.O_CREATE|os.O_EXCL, info.Mode()) |
| if err != nil { |
| log.Fatal(err) |
| } |
| if _, err := io.Copy(dstFile, srcFile); err != nil { |
| log.Fatal(err) |
| } |
| if err := dstFile.Close(); err != nil { |
| log.Fatal(err) |
| } |
| if err := srcFile.Close(); err != nil { |
| log.Fatal(err) |
| } |
| buf.WriteByte(' ') |
| buf.WriteString(src) |
| } |
| buf.WriteByte('\n') |
| |
| if err := os.WriteFile(*depfilePath, buf.Bytes(), os.ModePerm); err != nil { |
| log.Fatal(err) |
| } |
| |
| f, err := os.OpenFile(*stampPath, os.O_CREATE|os.O_TRUNC, os.ModePerm) |
| if err != nil { |
| log.Fatal(err) |
| } |
| if err := f.Close(); err != nil { |
| log.Fatal(err) |
| } |
| now := time.Now() |
| if err := os.Chtimes(*stampPath, now, now); err != nil { |
| log.Fatal(err) |
| } |
| } |