summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBrad Fitzpatrick <bradfitz@golang.org>2012-05-22 18:41:20 -0700
committerBrad Fitzpatrick <bradfitz@golang.org>2012-05-22 18:41:20 -0700
commitc0bbeb3795be0770e3c884af3b488119c551710d (patch)
treedfd3f894061103d64e4517c21de19db716b479cb /src
parent8f5a616d7f1f5ad0431b5d7f2371cd0cd3aa2754 (diff)
downloadgo-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.go107
-rwxr-xr-xsrc/run.bash2
-rw-r--r--src/run.bat2
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.