зеркало из https://github.com/golang/tools.git
118 строки
3.6 KiB
Go
118 строки
3.6 KiB
Go
// Copyright 2022 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
//go:build ignore
|
|
// +build ignore
|
|
|
|
// The copyfiles script copies the contents of the internal cmd/go robustio
|
|
// package to the current directory, with adjustments to make it build.
|
|
//
|
|
// NOTE: In retrospect this script got out of hand, as we have to perform
|
|
// various operations on the package to get it to build at old Go versions. If
|
|
// in the future it proves to be flaky, delete it and just copy code manually.
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"go/build/constraint"
|
|
"go/scanner"
|
|
"go/token"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
func main() {
|
|
dir := filepath.Join(runtime.GOROOT(), "src", "cmd", "go", "internal", "robustio")
|
|
|
|
entries, err := os.ReadDir(dir)
|
|
if err != nil {
|
|
log.Fatalf("reading the robustio dir: %v", err)
|
|
}
|
|
|
|
// Collect file content so that we can validate before copying.
|
|
fileContent := make(map[string][]byte)
|
|
windowsImport := []byte("\t\"internal/syscall/windows\"\n")
|
|
foundWindowsImport := false
|
|
for _, entry := range entries {
|
|
if strings.HasSuffix(entry.Name(), ".go") {
|
|
pth := filepath.Join(dir, entry.Name())
|
|
content, err := os.ReadFile(pth)
|
|
if err != nil {
|
|
log.Fatalf("reading %q: %v", entry.Name(), err)
|
|
}
|
|
|
|
// Replace the use of internal/syscall/windows.ERROR_SHARING_VIOLATION
|
|
// with a local constant.
|
|
if entry.Name() == "robustio_windows.go" && bytes.Contains(content, windowsImport) {
|
|
foundWindowsImport = true
|
|
content = bytes.Replace(content, windowsImport, nil, 1)
|
|
content = bytes.Replace(content, []byte("windows.ERROR_SHARING_VIOLATION"), []byte("ERROR_SHARING_VIOLATION"), -1)
|
|
}
|
|
|
|
// Replace os.ReadFile with os.ReadFile (for 1.15 and older). We
|
|
// attempt to match calls (via the '('), to avoid matching mentions of
|
|
// os.ReadFile in comments.
|
|
//
|
|
// TODO(rfindley): once we (shortly!) no longer support 1.15, remove
|
|
// this and break the build.
|
|
if bytes.Contains(content, []byte("os.ReadFile(")) {
|
|
content = bytes.Replace(content, []byte("\"os\""), []byte("\"io/ioutil\"\n\t\"os\""), 1)
|
|
content = bytes.Replace(content, []byte("os.ReadFile("), []byte("os.ReadFile("), -1)
|
|
}
|
|
|
|
// Add +build constraints, for 1.16.
|
|
content = addPlusBuildConstraints(content)
|
|
|
|
fileContent[entry.Name()] = content
|
|
}
|
|
}
|
|
|
|
if !foundWindowsImport {
|
|
log.Fatal("missing expected import of internal/syscall/windows in robustio_windows.go")
|
|
}
|
|
|
|
for name, content := range fileContent {
|
|
if err := os.WriteFile(name, content, 0644); err != nil {
|
|
log.Fatalf("writing %q: %v", name, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// addPlusBuildConstraints splices in +build constraints for go:build
|
|
// constraints encountered in the source.
|
|
//
|
|
// Gopls still builds at Go 1.16, which requires +build constraints.
|
|
func addPlusBuildConstraints(src []byte) []byte {
|
|
var s scanner.Scanner
|
|
fset := token.NewFileSet()
|
|
file := fset.AddFile("", fset.Base(), len(src))
|
|
s.Init(file, src, nil /* no error handler */, scanner.ScanComments)
|
|
|
|
result := make([]byte, 0, len(src))
|
|
lastInsertion := 0
|
|
for {
|
|
pos, tok, lit := s.Scan()
|
|
if tok == token.EOF {
|
|
break
|
|
}
|
|
if tok == token.COMMENT {
|
|
if c, err := constraint.Parse(lit); err == nil {
|
|
plusBuild, err := constraint.PlusBuildLines(c)
|
|
if err != nil {
|
|
log.Fatalf("computing +build constraint for %q: %v", lit, err)
|
|
}
|
|
insertAt := file.Offset(pos) + len(lit)
|
|
result = append(result, src[lastInsertion:insertAt]...)
|
|
result = append(result, []byte("\n"+strings.Join(plusBuild, "\n"))...)
|
|
lastInsertion = insertAt
|
|
}
|
|
}
|
|
}
|
|
result = append(result, src[lastInsertion:]...)
|
|
return result
|
|
}
|