"os/exec"
"path"
"path/filepath"
+ "regexp"
"runtime"
"sort"
"strconv"
fail = !compareAPI(bw, features, required, optional, exception)
}
+func set(items []string) map[string]bool {
+ s := make(map[string]bool)
+ for _, v := range items {
+ s[v] = true
+ }
+ return s
+}
+
+var spaceParensRx = regexp.MustCompile(` \(\S+?\)`)
+
+func featureWithoutContext(f string) string {
+ if !strings.Contains(f, "(") {
+ return f
+ }
+ return spaceParensRx.ReplaceAllString(f, "")
+}
+
func compareAPI(w io.Writer, features, required, optional, exception []string) (ok bool) {
ok = true
- var optionalSet = make(map[string]bool) // feature => true
- var exceptionSet = make(map[string]bool) // exception => true
- for _, f := range optional {
- optionalSet[f] = true
- }
- for _, f := range exception {
- exceptionSet[f] = true
- }
+ optionalSet := set(optional)
+ exceptionSet := set(exception)
+ featureSet := set(features)
sort.Strings(features)
sort.Strings(required)
for len(required) > 0 || len(features) > 0 {
switch {
- case len(features) == 0 || required[0] < features[0]:
+ case len(features) == 0 || (len(required) > 0 && required[0] < features[0]):
feature := take(&required)
if exceptionSet[feature] {
fmt.Fprintf(w, "~%s\n", feature)
+ } else if featureSet[featureWithoutContext(feature)] {
+ // okay.
} else {
fmt.Fprintf(w, "-%s\n", feature)
ok = false // broke compatibility
}
- case len(required) == 0 || required[0] > features[0]:
+ case len(required) == 0 || (len(features) > 0 && required[0] > features[0]):
newFeature := take(&features)
if optionalSet[newFeature] {
// Known added feature to the upcoming release.
}{
{
name: "feature added",
- features: []string{"C", "A", "B"},
- required: []string{"A", "C"},
+ features: []string{"A", "B", "C", "D", "E", "F"},
+ required: []string{"B", "D"},
ok: true,
- out: "+B\n",
+ out: "+A\n+C\n+E\n+F\n",
},
{
name: "feature removed",
ok: true,
out: "~B\n",
},
+ {
+ // http://golang.org/issue/4303
+ name: "contexts reconverging",
+ required: []string{
+ "A",
+ "pkg syscall (darwin-386), type RawSockaddrInet6 struct",
+ "pkg syscall (darwin-amd64), type RawSockaddrInet6 struct",
+ },
+ features: []string{
+ "A",
+ "pkg syscall, type RawSockaddrInet6 struct",
+ },
+ ok: true,
+ out: "+pkg syscall, type RawSockaddrInet6 struct\n",
+ },
}
for _, tt := range tests {
buf := new(bytes.Buffer)