diff options
author | Brad Fitzpatrick <bradfitz@golang.org> | 2012-05-22 18:41:20 -0700 |
---|---|---|
committer | Brad Fitzpatrick <bradfitz@golang.org> | 2012-05-22 18:41:20 -0700 |
commit | c0bbeb3795be0770e3c884af3b488119c551710d (patch) | |
tree | dfd3f894061103d64e4517c21de19db716b479cb /src | |
parent | 8f5a616d7f1f5ad0431b5d7f2371cd0cd3aa2754 (diff) | |
download | go-c0bbeb3795be0770e3c884af3b488119c551710d.tar.gz |
cmd/api: add api/next.txt
This quiets all.bash noise for upcoming features we know about.
The all.bash warnings will now only print for things not in next.txt
(or in next.txt but not in the API).
Once an API is frozen, we rename next.txt to a new frozen file
(like go1.txt)
Fixes issue 3651
R=golang-dev, r
CC=golang-dev
http://codereview.appspot.com/6218069
Diffstat (limited to 'src')
-rw-r--r-- | src/cmd/api/goapi.go | 107 | ||||
-rwxr-xr-x | src/run.bash | 2 | ||||
-rw-r--r-- | src/run.bat | 2 |
3 files changed, 76 insertions, 35 deletions
diff --git a/src/cmd/api/goapi.go b/src/cmd/api/goapi.go index 3d5151754..533636cd8 100644 --- a/src/cmd/api/goapi.go +++ b/src/cmd/api/goapi.go @@ -35,8 +35,12 @@ import ( // Flags var ( + // TODO(bradfitz): once Go 1.1 comes out, allow the -c flag to take a comma-separated + // list of files, rather than just one. checkFile = flag.String("c", "", "optional filename to check API against") - verbose = flag.Bool("v", false, "Verbose debugging") + allowNew = flag.Bool("allow_new", true, "allow API additions") + nextFile = flag.String("next", "", "optional filename of tentative upcoming API features for the next release. This file can be lazily maintained. It only affects the delta warnings from the -c file printed on success.") + verbose = flag.Bool("v", false, "verbose debugging") ) var contexts = []*build.Context{ @@ -123,45 +127,82 @@ func main() { } sort.Strings(features) + fail := false + defer func() { + if fail { + os.Exit(1) + } + }() + bw := bufio.NewWriter(os.Stdout) defer bw.Flush() - if *checkFile != "" { - bs, err := ioutil.ReadFile(*checkFile) - if err != nil { - log.Fatalf("Error reading file %s: %v", *checkFile, err) - } - v1 := strings.Split(strings.TrimSpace(string(bs)), "\n") - sort.Strings(v1) - v2 := features - take := func(sl *[]string) string { - s := (*sl)[0] - *sl = (*sl)[1:] - return s - } - changes := false - for len(v1) > 0 || len(v2) > 0 { - switch { - case len(v2) == 0 || v1[0] < v2[0]: - fmt.Fprintf(bw, "-%s\n", take(&v1)) - changes = true - case len(v1) == 0 || v1[0] > v2[0]: - fmt.Fprintf(bw, "+%s\n", take(&v2)) - // we allow API additions now - default: - take(&v1) - take(&v2) - } - } - if changes { - bw.Flush() - os.Exit(1) - } - } else { + if *checkFile == "" { for _, f := range features { fmt.Fprintf(bw, "%s\n", f) } + return + } + + var required []string + for _, filename := range []string{*checkFile} { + required = append(required, fileFeatures(filename)...) + } + sort.Strings(required) + + var optional = make(map[string]bool) // feature => true + if *nextFile != "" { + for _, feature := range fileFeatures(*nextFile) { + optional[feature] = true + } + } + + take := func(sl *[]string) string { + s := (*sl)[0] + *sl = (*sl)[1:] + return s + } + + for len(required) > 0 || len(features) > 0 { + switch { + case len(features) == 0 || required[0] < features[0]: + fmt.Fprintf(bw, "-%s\n", take(&required)) + fail = true // broke compatibility + case len(required) == 0 || required[0] > features[0]: + newFeature := take(&features) + if optional[newFeature] { + // Known added feature to the upcoming release. + // Delete it from the map so we can detect any upcoming features + // which were never seen. (so we can clean up the nextFile) + delete(optional, newFeature) + } else { + fmt.Fprintf(bw, "+%s\n", newFeature) + if !*allowNew { + fail = true // we're in lock-down mode for next release + } + } + default: + take(&required) + take(&features) + } + } + + var missing []string + for feature := range optional { + missing = append(missing, feature) + } + sort.Strings(missing) + for _, feature := range missing { + fmt.Fprintf(bw, "(in next file, but not in API) -%s\n", feature) + } +} + +func fileFeatures(filename string) []string { + bs, err := ioutil.ReadFile(filename) + if err != nil { + log.Fatalf("Error reading file %s: %v", filename, err) } + return strings.Split(strings.TrimSpace(string(bs)), "\n") } // pkgSymbol represents a symbol in a package diff --git a/src/run.bash b/src/run.bash index 6619fc1ff..ca84b7034 100755 --- a/src/run.bash +++ b/src/run.bash @@ -106,7 +106,7 @@ time go run run.go echo echo '# Checking API compatibility.' -go tool api -c $GOROOT/api/go1.txt +go tool api -c $GOROOT/api/go1.txt -next $GOROOT/api/next.txt echo echo ALL TESTS PASSED diff --git a/src/run.bat b/src/run.bat index 3bf9e8fc7..9a09d435c 100644 --- a/src/run.bat +++ b/src/run.bat @@ -68,7 +68,7 @@ echo. if %FAIL%==1 goto fail echo # Checking API compatibility. -go tool api -c ..\api\go1.txt +go tool api -c ..\api\go1.txt -next ..\api\next.txt if errorlevel 1 goto fail echo. |