blob: 64a8aded79e0ff967129a6446b344ff97876c301 [file] [log] [blame]
// 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"
"io/ioutil"
"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(':')
cmd := exec.Command("git", "ls-files", "--cached", "--others", "--exclude-standard", "-z")
cmd.Dir = *sourceGoroot
cmd.Env = []string{
"PATH=" + os.Getenv("PATH"),
}
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 := ioutil.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)
}
}