api_version: 1
handlers:
+- url: /package.*
+ script: package.py
+
- url: /.*
script: gobuild.py
--- /dev/null
+# Copyright 2010 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.
+
+# This is the server part of the package dashboard.
+# It must be run by App Engine.
+
+from google.appengine.api import memcache
+from google.appengine.runtime import DeadlineExceededError
+from google.appengine.ext import db
+from google.appengine.ext import webapp
+from google.appengine.ext.webapp import template
+from google.appengine.ext.webapp.util import run_wsgi_app
+import binascii
+import datetime
+import hashlib
+import hmac
+import logging
+import os
+import re
+import struct
+import time
+import urllib2
+
+# Storage model for package info recorded on server.
+# Just path, count, and time of last install.
+class Package(db.Model):
+ path = db.StringProperty()
+ web_url = db.StringProperty() # derived from path
+ count = db.IntegerProperty()
+ last_install = db.DateTimeProperty()
+
+re_bitbucket = re.compile(r'^bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$')
+re_googlecode = re.compile(r'^[a-z0-9\-]+\.googlecode\.com/(svn|hg)$')
+re_github = re.compile(r'^github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+$')
+
+MaxPathLength = 100
+
+class PackagePage(webapp.RequestHandler):
+ def get(self):
+ if self.request.get('fmt') == 'json':
+ return self.json()
+
+ q = Package.all()
+ q.order('-last_install')
+ by_time = q.fetch(100)
+
+ q = Package.all()
+ q.order('-count')
+ by_count = q.fetch(100)
+
+ self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
+ path = os.path.join(os.path.dirname(__file__), 'package.html')
+ self.response.out.write(template.render(path, {"by_time": by_time, "by_count": by_count}))
+
+ def json(self):
+ self.response.set_status(200)
+ self.response.headers['Content-Type'] = 'text/plain; charset=utf-8'
+ q = Package.all()
+ s = '{"packages": ['
+ sep = ''
+ for r in q.fetch(1000):
+ s += '%s\n\t{"path": "%s", "last_install": "%s", "count": "%s"}' % (sep, r.path, r.last_install, r.count)
+ sep = ','
+ s += '\n]}\n'
+ self.response.out.write(s)
+
+ def can_get_url(self, url):
+ try:
+ req = urllib2.Request(url)
+ response = urllib2.urlopen(req)
+ return True
+ except:
+ return False
+
+ def is_valid_package_path(self, path):
+ return (re_bitbucket.match(path) or
+ re_googlecode.match(path) or
+ re_github.match(path))
+
+ def record_pkg(self, path):
+ # sanity check string
+ if not path or len(path) > MaxPathLength or not self.is_valid_package_path(path):
+ return False
+
+ # look in datastore
+ key = 'pkg-' + path
+ p = Package.get_by_key_name(key)
+ if p is None:
+ # not in datastore - verify URL before creating
+ if re_bitbucket.match(path):
+ check_url = 'http://' + path + '/?cmd=heads'
+ web = 'http://' + path + '/'
+ elif re_github.match(path):
+ # github doesn't let you fetch the .git directory anymore.
+ # fetch .git/info/refs instead, like git clone would.
+ check_url = 'http://'+path+'.git/info/refs'
+ web = 'http://' + path
+ elif re_googlecode.match(path):
+ check_url = 'http://'+path
+ web = 'http://code.google.com/p/' + path[:path.index('.')]
+ else:
+ logging.error('unrecognized path: %s', path)
+ return False
+ if not self.can_get_url(check_url):
+ logging.error('cannot get %s', check_url)
+ return False
+ p = Package(key_name = key, path = path, count = 0, web_url = web)
+
+ # update package object
+ p.count += 1
+ p.last_install = datetime.datetime.utcnow()
+ p.put()
+ return True
+
+ def post(self):
+ path = self.request.get('path')
+ ok = self.record_pkg(path)
+ if ok:
+ self.response.set_status(200)
+ self.response.out.write('ok')
+ else:
+ logging.error('invalid path in post: %s', path)
+ self.response.set_status(500)
+ self.response.out.write('not ok')
+
+def main():
+ app = webapp.WSGIApplication([('/package', PackagePage)], debug=True)
+ run_wsgi_app(app)
+
+if __name__ == '__main__':
+ main()
GOBIN="${GOBIN:-$HOME/bin}"
-for i in cc 6l 6a 6c 8l 8a 8c 8g 5l 5a 5c 5g gc 6g gopack nm cgo cov ebnflint godefs godoc gofmt gotest goyacc hgpatch prof
+for i in cc 6l 6a 6c 8l 8a 8c 8g 5l 5a 5c 5g gc 6g gopack nm cgo cov ebnflint godefs godoc gofmt goinstall gotest goyacc hgpatch prof
do
cd $i
"$GOBIN"/gomake clean
--- /dev/null
+# Copyright 2009 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.
+
+include ../../Make.$(GOARCH)
+
+TARG=goinstall
+GOFILES=\
+ download.go\
+ main.go\
+ make.go\
+ parse.go\
+
+include ../../Make.cmd
--- /dev/null
+// Copyright 2010 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.
+
+/*
+
+Goinstall is an experiment in automatic package installation.
+It installs packages, possibly downloading them from the internet.
+It maintains a list of public Go packages at http://godashboard.appspot.com/packages.
+
+Usage:
+ goinstall [flags] importpath...
+
+Flags and default settings:
+ -dashboard=true tally public packages on godashboard.appspot.com
+ -update=false update already-downloaded packages
+ -v=false verbose operation
+
+Goinstall installs each of the packages identified on the command line.
+It installs a package's prerequisites before trying to install the package itself.
+
+The source code for a package with import path foo/bar is expected
+to be in the directory $GOROOT/src/pkg/foo/bar/. If the import
+path refers to a code hosting site, goinstall will download the code
+if necessary. The recognized code hosting sites are:
+
+ BitBucket (Mercurial)
+
+ import "bitbucket.org/user/project"
+ import "bitbucket.org/user/project/sub/directory"
+
+ GitHub (Git)
+
+ import "github.com/user/project.git"
+ import "github.com/user/project.git/sub/directory"
+
+ Google Code Project Hosting (Mercurial, Subversion)
+
+ import "project.googlecode.com/hg"
+ import "project.googlecode.com/hg/sub/directory"
+
+ import "project.googlecode.com/svn/trunk"
+ import "project.googlecode.com/svn/trunk/sub/directory"
+
+
+If the destination directory (e.g., $GOROOT/src/pkg/bitbucket.org/user/project)
+already exists and contains an appropriate checkout, goinstall will not
+attempt to fetch updates. The -update flag changes this behavior,
+causing goinstall to update all remote packages encountered during
+the installation.
+
+When downloading or updating, goinstall first looks for a tag or branch
+named "release". If there is one, it uses that version of the code.
+Otherwise it uses the default version selected by the version control
+system, typically HEAD for git, tip for Mercurial.
+
+After a successful download and installation of a publicly accessible
+remote package, goinstall reports the installation to godashboard.appspot.com,
+which increments a count associated with the package and the time
+of its most recent installation. This mechanism powers the package list
+at http://godashboard.appspot.com/packages, allowing Go programmers
+to learn about popular packages that might be worth looking at.
+The -dashboard=false flag disables this reporting.
+
+By default, goinstall prints output only when it encounters an error.
+The -v flag causes goinstall to print information about packages
+being considered and installed.
+
+Goinstall does not attempt to be a replacement for make.
+Instead, it invokes "make install" after locating the package sources.
+For local packages without a Makefile and all remote packages,
+goinstall creates and uses a temporary Makefile constructed from
+the import path and the list of Go files in the package.
+*/
+package documentation
--- /dev/null
+// Copyright 2010 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.
+
+// Download remote packages.
+
+package main
+
+import (
+ "http"
+ "os"
+ "regexp"
+ "strings"
+)
+
+const dashboardURL = "http://godashboard.appspot.com/package"
+
+// maybeReportToDashboard reports path to dashboard unless
+// -dashboard=false is on command line. It ignores errors.
+func maybeReportToDashboard(path string) {
+ // if -dashboard=false was on command line, do nothing
+ if !*reportToDashboard {
+ return
+ }
+
+ // otherwise lob url to dashboard
+ r, _ := http.Post(dashboardURL, "application/x-www-form-urlencoded", strings.NewReader("path="+path))
+ if r != nil && r.Body != nil {
+ r.Body.Close()
+ }
+}
+
+var googlecode = regexp.MustCompile(`^([a-z0-9\-]+\.googlecode\.com/(svn|hg))(/[a-z0-9A-Z_.\-/]*)?$`)
+var github = regexp.MustCompile(`^(github\.com/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
+var bitbucket = regexp.MustCompile(`^(bitbucket\.org/[a-z0-9A-Z_.\-]+/[a-z0-9A-Z_.\-]+)(/[a-z0-9A-Z_.\-/]*)?$`)
+
+// download checks out or updates pkg from the remote server.
+func download(pkg string) (string, os.Error) {
+ if strings.Index(pkg, "..") >= 0 {
+ return "", os.ErrorString("invalid path (contains ..)")
+ }
+ if m := bitbucket.MatchStrings(pkg); m != nil {
+ if err := vcsCheckout(&hg, root+m[1], "http://"+m[1], m[1]); err != nil {
+ return "", err
+ }
+ return root + pkg, nil
+ }
+ if m := googlecode.MatchStrings(pkg); m != nil {
+ var v *vcs
+ switch m[2] {
+ case "hg":
+ v = &hg
+ case "svn":
+ v = &svn
+ default:
+ // regexp only allows hg, svn to get through
+ panic("missing case in download: ", pkg)
+ }
+ if err := vcsCheckout(v, root+m[1], "http://"+m[1], m[1]); err != nil {
+ return "", err
+ }
+ return root + pkg, nil
+ }
+ if m := github.MatchStrings(pkg); m != nil {
+ if strings.HasSuffix(m[1], ".git") {
+ return "", os.ErrorString("repository " + pkg + " should not have .git suffix")
+ }
+ if err := vcsCheckout(&git, root+m[1], "http://"+m[1]+".git", m[1]); err != nil {
+ return "", err
+ }
+ return root + pkg, nil
+ }
+ return "", os.ErrorString("unknown repository: " + pkg)
+}
+
+// a vcs represents a version control system
+// like Mercurial, Git, or Subversion.
+type vcs struct {
+ cmd string
+ metadir string
+ clone string
+ update string
+ pull string
+ log string
+ logLimitFlag string
+ logReleaseFlag string
+}
+
+var hg = vcs{
+ cmd: "hg",
+ metadir: ".hg",
+ clone: "clone",
+ update: "update",
+ pull: "pull",
+ log: "log",
+ logLimitFlag: "-l1",
+ logReleaseFlag: "-rrelease",
+}
+
+var git = vcs{
+ cmd: "git",
+ metadir: ".git",
+ clone: "clone",
+ update: "checkout",
+ pull: "fetch",
+ log: "log",
+ logLimitFlag: "-n1",
+ logReleaseFlag: "release",
+}
+
+var svn = vcs{
+ cmd: "svn",
+ metadir: ".svn",
+ clone: "checkout",
+ update: "update",
+ pull: "",
+ log: "log",
+ logLimitFlag: "-l1",
+ logReleaseFlag: "release",
+}
+
+// vcsCheckout checks out repo into dst using vcs.
+// It tries to check out (or update, if the dst already
+// exists and -u was specified on the command line)
+// the repository at tag/branch "release". If there is no
+// such tag or branch, it falls back to the repository tip.
+func vcsCheckout(vcs *vcs, dst, repo, dashpath string) os.Error {
+ dir, err := os.Stat(dst + "/" + vcs.metadir)
+ if err == nil && !dir.IsDirectory() {
+ return os.ErrorString("not a directory: " + dst)
+ }
+ if err != nil {
+ if err := os.MkdirAll(dst, 0777); err != nil {
+ return err
+ }
+ if err := run("/", nil, vcs.cmd, vcs.clone, repo, dst); err != nil {
+ return err
+ }
+ quietRun(dst, nil, vcs.cmd, vcs.update, "release")
+
+ // success on first installation - report
+ maybeReportToDashboard(dashpath)
+ } else if *update {
+ if vcs.pull != "" {
+ if err := run(dst, nil, vcs.cmd, vcs.pull); err != nil {
+ return err
+ }
+ }
+ // check for release with hg log -l 1 -r release
+ // if success, hg update release
+ // else hg update
+ if err := quietRun(dst, nil, vcs.cmd, vcs.log, vcs.logLimitFlag, vcs.logReleaseFlag); err == nil {
+ if err := run(dst, nil, vcs.cmd, vcs.update, "release"); err != nil {
+ return err
+ }
+ } else {
+ if err := run(dst, nil, vcs.cmd, vcs.update); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2010 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.
+
+// Experimental Go package installer; see doc.go.
+
+package main
+
+import (
+ "bytes"
+ "exec"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "path"
+ "strings"
+)
+
+func usage() {
+ fmt.Fprint(os.Stderr, "usage: goinstall importpath...\n")
+ flag.PrintDefaults()
+ os.Exit(2)
+}
+
+var (
+ argv0 = os.Args[0]
+ errors = false
+ gobin = os.Getenv("GOBIN")
+ parents = make(map[string]string)
+ root = os.Getenv("GOROOT")
+ visit = make(map[string]status)
+
+ reportToDashboard = flag.Bool("dashboard", true, "report public packages at "+dashboardURL)
+ update = flag.Bool("u", false, "update already-downloaded packages")
+ verbose = flag.Bool("v", false, "verbose")
+)
+
+type status int // status for visited map
+const (
+ unvisited status = iota
+ visiting
+ done
+)
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+ if root == "" {
+ fmt.Fprintf(os.Stderr, "%s: no $GOROOT\n", argv0)
+ os.Exit(1)
+ }
+ root += "/src/pkg/"
+ if gobin == "" {
+ gobin = os.Getenv("HOME") + "/bin"
+ }
+
+ // special case - "unsafe" is already installed
+ visit["unsafe"] = done
+
+ // install command line arguments
+ args := flag.Args()
+ if len(args) == 0 {
+ usage()
+ }
+ for _, path := range args {
+ install(path, "")
+ }
+ if errors {
+ os.Exit(1)
+ }
+}
+
+// printDeps prints the dependency path that leads to pkg.
+func printDeps(pkg string) {
+ if pkg == "" {
+ return
+ }
+ if visit[pkg] != done {
+ printDeps(parents[pkg])
+ }
+ fmt.Fprintf(os.Stderr, "\t%s ->\n", pkg)
+}
+
+// install installs the package named by path, which is needed by parent.
+func install(pkg, parent string) {
+ // Make sure we're not already trying to install pkg.
+ switch v, _ := visit[pkg]; v {
+ case done:
+ return
+ case visiting:
+ fmt.Fprintf(os.Stderr, "%s: package dependency cycle\n", argv0)
+ printDeps(parent)
+ fmt.Fprintf(os.Stderr, "\t%s\n", pkg)
+ os.Exit(2)
+ }
+ visit[pkg] = visiting
+ parents[pkg] = parent
+ if *verbose {
+ fmt.Println(pkg)
+ }
+
+ // Check whether package is local or remote.
+ // If remote, download or update it.
+ var dir string
+ local := false
+ if isLocalPath(pkg) {
+ dir = pkg
+ local = true
+ } else if isStandardPath(pkg) {
+ dir = path.Join(root, pkg)
+ local = true
+ } else {
+ var err os.Error
+ dir, err = download(pkg)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
+ errors = true
+ visit[pkg] = done
+ return
+ }
+ }
+
+ // Install prerequisites.
+ files, m, err := goFiles(dir)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: %s: %s\n", argv0, pkg, err)
+ errors = true
+ visit[pkg] = done
+ return
+ }
+ if len(files) == 0 {
+ fmt.Fprintf(os.Stderr, "%s: %s: package has no files\n", argv0, pkg)
+ errors = true
+ visit[pkg] = done
+ return
+ }
+ for p := range m {
+ install(p, pkg)
+ }
+
+ // Install this package.
+ if !errors {
+ if err := domake(dir, pkg, local); err != nil {
+ fmt.Fprintf(os.Stderr, "%s: installing %s: %s\n", argv0, pkg, err)
+ errors = true
+ }
+ }
+
+ visit[pkg] = done
+}
+
+// Is this a local path? /foo ./foo ../foo . ..
+func isLocalPath(s string) bool {
+ return strings.HasPrefix(s, "/") || strings.HasPrefix(s, "./") || strings.HasPrefix(s, "../") || s == "." || s == ".."
+}
+
+// Is this a standard package path? strings container/vector etc.
+// Assume that if the first element has a dot, it's a domain name
+// and is not the standard package path.
+func isStandardPath(s string) bool {
+ dot := strings.Index(s, ".")
+ slash := strings.Index(s, "/")
+ return dot < 0 || 0 < slash && slash < dot
+}
+
+// run runs the command cmd in directory dir with standard input stdin.
+// If the command fails, run prints the command and output on standard error
+// in addition to returning a non-nil os.Error.
+func run(dir string, stdin []byte, cmd ...string) os.Error {
+ return genRun(dir, stdin, cmd, false)
+}
+
+// quietRun is like run but prints nothing on failure unless -v is used.
+func quietRun(dir string, stdin []byte, cmd ...string) os.Error {
+ return genRun(dir, stdin, cmd, true)
+}
+
+// genRun implements run and tryRun.
+func genRun(dir string, stdin []byte, cmd []string, quiet bool) os.Error {
+ bin, err := exec.LookPath(cmd[0])
+ if err != nil {
+ return err
+ }
+ p, err := exec.Run(bin, cmd, os.Environ(), dir, exec.Pipe, exec.Pipe, exec.MergeWithStdout)
+ if *verbose {
+ fmt.Fprintf(os.Stderr, "%s: %s; %s %s\n", argv0, dir, bin, strings.Join(cmd[1:], " "))
+ }
+ if err != nil {
+ return err
+ }
+ go func() {
+ p.Stdin.Write(stdin)
+ p.Stdin.Close()
+ }()
+ var buf bytes.Buffer
+ io.Copy(&buf, p.Stdout)
+ io.Copy(&buf, p.Stdout)
+ w, err := p.Wait(0)
+ p.Close()
+ if !w.Exited() || w.ExitStatus() != 0 {
+ if !quiet || *verbose {
+ if dir != "" {
+ dir = "cd " + dir + "; "
+ }
+ fmt.Fprintf(os.Stderr, "%s: === %s%s\n", argv0, dir, strings.Join(cmd, " "))
+ os.Stderr.Write(buf.Bytes())
+ fmt.Fprintf(os.Stderr, "--- %s\n", w)
+ }
+ return os.ErrorString("running " + cmd[0] + ": " + w.String())
+ }
+ return nil
+}
--- /dev/null
+// Copyright 2010 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.
+
+// Run "make install" to build package.
+
+package main
+
+import (
+ "bytes"
+ "os"
+ "template"
+)
+
+// domake builds the package in dir.
+// If local is false, the package was copied from an external system.
+// For non-local packages or packages without Makefiles,
+// domake generates a standard Makefile and passes it
+// to make on standard input.
+func domake(dir, pkg string, local bool) os.Error {
+ if local {
+ _, err := os.Stat(dir + "/Makefile")
+ if err == nil {
+ return run(dir, nil, gobin+"/gomake", "install")
+ }
+ }
+ makefile, err := makeMakefile(dir, pkg)
+ if err != nil {
+ return err
+ }
+ return run(dir, makefile, gobin+"/gomake", "-f-", "install")
+}
+
+// makeMakefile computes the standard Makefile for the directory dir
+// installing as package pkg. It includes all *.go files in the directory
+// except those in package main and those ending in _test.go.
+func makeMakefile(dir, pkg string) ([]byte, os.Error) {
+ files, _, err := goFiles(dir)
+ if err != nil {
+ return nil, err
+ }
+
+ var buf bytes.Buffer
+ if err := makefileTemplate.Execute(&makedata{pkg, files}, &buf); err != nil {
+ return nil, err
+ }
+ return buf.Bytes(), nil
+}
+
+// makedata is the data type for the makefileTemplate.
+type makedata struct {
+ pkg string // package import path
+ files []string // list of .go files
+}
+
+var makefileTemplate = template.MustParse(`
+include $(GOROOT)/src/Make.$(GOARCH)
+
+TARG={pkg}
+GOFILES=\
+{.repeated section files}
+ {@}\
+{.end}
+
+include $(GOROOT)/src/Make.pkg
+`,
+ nil)
--- /dev/null
+// Copyright 2010 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.
+
+// Wrappers for Go parser.
+
+package main
+
+import (
+ "path"
+ "os"
+ "log"
+ "strings"
+ "strconv"
+ "go/ast"
+ "go/parser"
+)
+
+// goFiles returns a list of the *.go source files in dir,
+// excluding those in package main or ending in _test.go.
+// It also returns a map giving the packages imported
+// by those files. The map keys are the imported paths.
+// The key's value is one file that imports that path.
+func goFiles(dir string) (files []string, imports map[string]string, err os.Error) {
+ f, err := os.Open(dir, os.O_RDONLY, 0)
+ if err != nil {
+ return nil, nil, err
+ }
+ dirs, err := f.Readdir(-1)
+ f.Close()
+ if err != nil {
+ return nil, nil, err
+ }
+
+ files = make([]string, 0, len(dirs))
+ imports = make(map[string]string)
+ pkgName := ""
+ for i := range dirs {
+ d := &dirs[i]
+ if !strings.HasSuffix(d.Name, ".go") || strings.HasSuffix(d.Name, "_test.go") {
+ continue
+ }
+ filename := path.Join(dir, d.Name)
+ pf, err := parser.ParseFile(filename, nil, nil, parser.ImportsOnly)
+ if err != nil {
+ return nil, nil, err
+ }
+ s := string(pf.Name.Name())
+ if s == "main" {
+ continue
+ }
+ if pkgName == "" {
+ pkgName = s
+ } else if pkgName != s {
+ return nil, nil, os.ErrorString("multiple package names in " + dir)
+ }
+ n := len(files)
+ files = files[0 : n+1]
+ files[n] = filename
+ for _, decl := range pf.Decls {
+ for _, spec := range decl.(*ast.GenDecl).Specs {
+ quoted := string(spec.(*ast.ImportSpec).Path.Value)
+ unquoted, err := strconv.Unquote(quoted)
+ if err != nil {
+ log.Crashf("%s: parser returned invalid quoted string: <%s>", filename, quoted)
+ }
+ imports[unquoted] = filename
+ }
+ }
+ }
+ return files, imports, nil
+}
"$GOBIN"/gomake enam.o
cd ..
-for i in cc ${O}l ${O}a ${O}c gc ${O}g gopack nm cov godefs prof gotest
+# Note: commands written in Go are not listed here.
+# They are in ../make.bash so that they can be built
+# after the Go libraries on which they depend.
+for i in cc ${O}l ${O}a ${O}c gc ${O}g cov godefs gopack gotest nm prof
do
echo; echo; echo %%%% making $i %%%%; echo
cd $i
)
bash "$GOROOT"/src/clean.bash
-for i in lib9 libbio libmach cmd pkg libcgo cmd/cgo cmd/ebnflint cmd/godoc cmd/gofmt cmd/goyacc cmd/hgpatch
+for i in lib9 libbio libmach cmd pkg libcgo cmd/cgo cmd/ebnflint cmd/godoc cmd/gofmt cmd/goinstall cmd/goyacc cmd/hgpatch
do
case "$i-$GOOS-$GOARCH" in
libcgo-nacl-* | cmd/*-nacl-* | libcgo-linux-arm)