2017-03-31 19:01:58 +03:00
|
|
|
// Copyright 2015 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.
|
|
|
|
|
|
|
|
// +build ignore
|
|
|
|
|
|
|
|
// gen runs go generate on Unicode- and CLDR-related package in the text
|
|
|
|
// repositories, taking into account dependencies and versions.
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"go/build"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"os/exec"
|
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"unicode"
|
|
|
|
|
|
|
|
"golang.org/x/text/internal/gen"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
verbose = flag.Bool("v", false, "verbose output")
|
|
|
|
force = flag.Bool("force", false, "ignore failing dependencies")
|
|
|
|
doCore = flag.Bool("core", false, "force an update to core")
|
|
|
|
excludeList = flag.String("exclude", "",
|
|
|
|
"comma-separated list of packages to exclude")
|
|
|
|
|
|
|
|
// The user can specify a selection of packages to build on the command line.
|
|
|
|
args []string
|
|
|
|
)
|
|
|
|
|
|
|
|
func exclude(pkg string) bool {
|
|
|
|
if len(args) > 0 {
|
|
|
|
return !contains(args, pkg)
|
|
|
|
}
|
|
|
|
return contains(strings.Split(*excludeList, ","), pkg)
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO:
|
|
|
|
// - Better version handling.
|
|
|
|
// - Generate tables for the core unicode package?
|
|
|
|
// - Add generation for encodings. This requires some retooling here and there.
|
|
|
|
// - Running repo-wide "long" tests.
|
|
|
|
|
|
|
|
var vprintf = fmt.Printf
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
gen.Init()
|
|
|
|
args = flag.Args()
|
|
|
|
if !*verbose {
|
|
|
|
// Set vprintf to a no-op.
|
|
|
|
vprintf = func(string, ...interface{}) (int, error) { return 0, nil }
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: create temporary cache directory to load files and create and set
|
|
|
|
// a "cache" option if the user did not specify the UNICODE_DIR environment
|
|
|
|
// variable. This will prevent duplicate downloads and also will enable long
|
|
|
|
// tests, which really need to be run after each generated package.
|
|
|
|
|
|
|
|
updateCore := *doCore
|
|
|
|
if gen.UnicodeVersion() != unicode.Version {
|
|
|
|
fmt.Printf("Requested Unicode version %s; core unicode version is %s.\n",
|
|
|
|
gen.UnicodeVersion(),
|
|
|
|
unicode.Version)
|
|
|
|
// TODO: use collate to compare. Simple comparison will work, though,
|
|
|
|
// until Unicode reaches version 10. To avoid circular dependencies, we
|
|
|
|
// could use the NumericWeighter without using package collate using a
|
|
|
|
// trivial Weighter implementation.
|
|
|
|
if gen.UnicodeVersion() < unicode.Version && !*force {
|
|
|
|
os.Exit(2)
|
|
|
|
}
|
|
|
|
updateCore = true
|
|
|
|
}
|
|
|
|
|
|
|
|
var unicode = &dependency{}
|
|
|
|
if updateCore {
|
|
|
|
fmt.Printf("Updating core to version %s...\n", gen.UnicodeVersion())
|
|
|
|
unicode = generate("unicode")
|
|
|
|
|
|
|
|
// Test some users of the unicode packages, especially the ones that
|
|
|
|
// keep a mirrored table. These may need to be corrected by hand.
|
|
|
|
generate("regexp", unicode)
|
|
|
|
generate("strconv", unicode) // mimics Unicode table
|
|
|
|
generate("strings", unicode)
|
|
|
|
generate("testing", unicode) // mimics Unicode table
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
cldr = generate("./unicode/cldr", unicode)
|
|
|
|
language = generate("./language", cldr)
|
|
|
|
internal = generate("./internal", unicode, language)
|
|
|
|
norm = generate("./unicode/norm", unicode)
|
|
|
|
rangetable = generate("./unicode/rangetable", unicode)
|
|
|
|
cases = generate("./cases", unicode, norm, language, rangetable)
|
|
|
|
width = generate("./width", unicode)
|
|
|
|
bidi = generate("./unicode/bidi", unicode, norm, rangetable)
|
|
|
|
_ = generate("./secure/precis", unicode, norm, rangetable, cases, width, bidi)
|
2017-05-18 19:54:23 +03:00
|
|
|
_ = generate("./encoding/htmlindex", unicode, language)
|
2017-03-31 19:01:58 +03:00
|
|
|
_ = generate("./currency", unicode, cldr, language, internal)
|
|
|
|
_ = generate("./internal/number", unicode, cldr, language, internal)
|
|
|
|
_ = generate("./language/display", unicode, cldr, language, internal)
|
|
|
|
_ = generate("./collate", unicode, norm, cldr, language, rangetable)
|
|
|
|
_ = generate("./search", unicode, norm, cldr, language, rangetable)
|
|
|
|
)
|
|
|
|
|
|
|
|
if updateCore {
|
|
|
|
copyVendored()
|
2017-05-18 19:54:23 +03:00
|
|
|
generate("vendor/golang_org/x/net/idna", unicode, norm, width, cases)
|
2017-03-31 19:01:58 +03:00
|
|
|
}
|
2017-05-18 19:54:23 +03:00
|
|
|
all.Wait()
|
2017-03-31 19:01:58 +03:00
|
|
|
|
|
|
|
if hasErrors {
|
|
|
|
fmt.Println("FAIL")
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
vprintf("SUCCESS\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
all sync.WaitGroup
|
|
|
|
hasErrors bool
|
|
|
|
)
|
|
|
|
|
|
|
|
type dependency struct {
|
|
|
|
sync.WaitGroup
|
|
|
|
hasErrors bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func generate(pkg string, deps ...*dependency) *dependency {
|
|
|
|
var wg dependency
|
|
|
|
if exclude(pkg) {
|
|
|
|
return &wg
|
|
|
|
}
|
|
|
|
wg.Add(1)
|
|
|
|
all.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer wg.Done()
|
|
|
|
defer all.Done()
|
|
|
|
// Wait for dependencies to finish.
|
|
|
|
for _, d := range deps {
|
|
|
|
d.Wait()
|
|
|
|
if d.hasErrors && !*force {
|
|
|
|
fmt.Printf("--- ABORT: %s\n", pkg)
|
|
|
|
wg.hasErrors = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vprintf("=== GENERATE %s\n", pkg)
|
|
|
|
args := []string{"generate"}
|
|
|
|
if *verbose {
|
|
|
|
args = append(args, "-v")
|
|
|
|
}
|
|
|
|
args = append(args, pkg)
|
|
|
|
cmd := exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...)
|
|
|
|
w := &bytes.Buffer{}
|
|
|
|
cmd.Stderr = w
|
|
|
|
cmd.Stdout = w
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
fmt.Printf("--- FAIL: %s:\n\t%v\n\tError: %v\n", pkg, indent(w), err)
|
|
|
|
hasErrors = true
|
|
|
|
wg.hasErrors = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
vprintf("=== TEST %s\n", pkg)
|
|
|
|
args[0] = "test"
|
|
|
|
cmd = exec.Command(filepath.Join(runtime.GOROOT(), "bin", "go"), args...)
|
|
|
|
wt := &bytes.Buffer{}
|
|
|
|
cmd.Stderr = wt
|
|
|
|
cmd.Stdout = wt
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
|
|
fmt.Printf("--- FAIL: %s:\n\t%v\n\tError: %v\n", pkg, indent(wt), err)
|
|
|
|
hasErrors = true
|
|
|
|
wg.hasErrors = true
|
|
|
|
return
|
|
|
|
}
|
|
|
|
vprintf("--- SUCCESS: %s\n\t%v\n", pkg, indent(w))
|
|
|
|
fmt.Print(wt.String())
|
|
|
|
}()
|
|
|
|
return &wg
|
|
|
|
}
|
|
|
|
|
|
|
|
func copyVendored() {
|
2017-05-18 19:54:23 +03:00
|
|
|
// Copy the vendored files. Some more may need to be copied in by hand.
|
|
|
|
dir := filepath.Join(build.Default.GOROOT, "src/vendor/golang_org/x/text")
|
|
|
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
|
|
|
if info.IsDir() {
|
2017-03-31 19:01:58 +03:00
|
|
|
return nil
|
|
|
|
}
|
2017-05-18 19:54:23 +03:00
|
|
|
b, err := ioutil.ReadFile(path[len(dir)+1:])
|
|
|
|
if err != nil {
|
2017-03-31 19:01:58 +03:00
|
|
|
return err
|
|
|
|
}
|
2017-05-18 19:54:23 +03:00
|
|
|
vprintf("=== COPY %s\n", path)
|
|
|
|
b = bytes.Replace(b, []byte("golang.org"), []byte("golang_org"), -1)
|
|
|
|
return ioutil.WriteFile(path, b, 0666)
|
2017-03-31 19:01:58 +03:00
|
|
|
})
|
|
|
|
if err != nil {
|
2017-05-18 19:54:23 +03:00
|
|
|
fmt.Println("Copying vendored files failed:", err)
|
2017-03-31 19:01:58 +03:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func contains(a []string, s string) bool {
|
|
|
|
for _, e := range a {
|
|
|
|
if s == e {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func indent(b *bytes.Buffer) string {
|
|
|
|
return strings.Replace(strings.TrimSpace(b.String()), "\n", "\n\t", -1)
|
|
|
|
}
|