Merge remote-tracking branch 'aosp/upstream'

* aosp/upstream:
  Use go1.9 instead of go1.9rc1
  Expose the installed path for Go binaries
  Move generated Travis test dirs outside the tree
  Clearer error in case of Android.bp being unreadable

Test: m
diff --git a/.travis.yml b/.travis.yml
index f616ff8..dd1c743 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@
 
 go:
     - 1.8.3
-    - 1.9rc1
+    - 1.9
 
 cache:
     directories:
diff --git a/bootstrap/bootstrap.go b/bootstrap/bootstrap.go
index 25e5d39..ab53938 100644
--- a/bootstrap/bootstrap.go
+++ b/bootstrap/bootstrap.go
@@ -127,15 +127,15 @@
 		},
 		"depfile")
 
-	binDir = pctx.StaticVariable("BinDir", filepath.Join(bootstrapDir, "bin"))
+	_ = pctx.VariableFunc("BinDir", func(config interface{}) (string, error) {
+		return binDir(), nil
+	})
+
+	_ = pctx.VariableFunc("ToolDir", func(config interface{}) (string, error) {
+		return toolDir(config), nil
+	})
 
 	docsDir = filepath.Join(bootstrapDir, "docs")
-	toolDir = pctx.VariableFunc("ToolDir", func(config interface{}) (string, error) {
-		if c, ok := config.(ConfigBlueprintToolLocation); ok {
-			return c.BlueprintToolLocation(), nil
-		}
-		return filepath.Join("$buildDir", "bin"), nil
-	})
 
 	bootstrapDir     = filepath.Join("$buildDir", bootstrapSubDir)
 	miniBootstrapDir = filepath.Join("$buildDir", miniBootstrapSubDir)
@@ -143,6 +143,24 @@
 	minibpFile = filepath.Join(miniBootstrapDir, "minibp")
 )
 
+type GoBinaryTool interface {
+	InstallPath() string
+
+	// So that other packages can't implement this interface
+	isGoBinary()
+}
+
+func binDir() string {
+	return filepath.Join(BuildDir, bootstrapSubDir, "bin")
+}
+
+func toolDir(config interface{}) string {
+	if c, ok := config.(ConfigBlueprintToolLocation); ok {
+		return filepath.Join(c.BlueprintToolLocation())
+	}
+	return filepath.Join(BuildDir, "bin")
+}
+
 func pluginDeps(ctx blueprint.BottomUpMutatorContext) {
 	if pkg, ok := ctx.Module().(*goPackage); ok {
 		for _, plugin := range pkg.properties.PluginFor {
@@ -332,10 +350,14 @@
 		Tool_dir bool `blueprint:mutated`
 	}
 
+	installPath string
+
 	// The bootstrap Config
 	config *Config
 }
 
+var _ GoBinaryTool = (*goBinary)(nil)
+
 func newGoBinaryModuleFactory(config *Config, tooldir bool) func() (blueprint.Module, []interface{}) {
 	return func() (blueprint.Module, []interface{}) {
 		module := &goBinary{
@@ -350,11 +372,9 @@
 	return g.properties.Deps
 }
 
+func (g *goBinary) isGoBinary() {}
 func (g *goBinary) InstallPath() string {
-	if g.properties.Tool_dir {
-		return "$ToolDir"
-	}
-	return "$BinDir"
+	return g.installPath
 }
 
 func (g *goBinary) GenerateBuildActions(ctx blueprint.ModuleContext) {
@@ -364,12 +384,17 @@
 		archiveFile     = filepath.Join(objDir, name+".a")
 		testArchiveFile = filepath.Join(testRoot(ctx), name+".a")
 		aoutFile        = filepath.Join(objDir, "a.out")
-		binaryFile      = filepath.Join(g.InstallPath(), name)
 		hasPlugins      = false
 		pluginSrc       = ""
 		genSrcs         = []string{}
 	)
 
+	if g.properties.Tool_dir {
+		g.installPath = filepath.Join(toolDir(ctx.Config()), name)
+	} else {
+		g.installPath = filepath.Join(binDir(), name)
+	}
+
 	ctx.VisitDepsDepthFirstIf(isGoPluginFor(name),
 		func(module blueprint.Module) { hasPlugins = true })
 	if hasPlugins {
@@ -423,7 +448,7 @@
 
 	ctx.Build(pctx, blueprint.BuildParams{
 		Rule:      cp,
-		Outputs:   []string{binaryFile},
+		Outputs:   []string{g.installPath},
 		Inputs:    []string{aoutFile},
 		OrderOnly: deps,
 		Optional:  !g.properties.Default,
@@ -588,11 +613,9 @@
 	ctx.VisitAllModulesIf(isBootstrapBinaryModule,
 		func(module blueprint.Module) {
 			binaryModule := module.(*goBinary)
-			binaryModuleName := ctx.ModuleName(binaryModule)
-			installPath := filepath.Join(binaryModule.InstallPath(), binaryModuleName)
 
 			if binaryModule.properties.Tool_dir {
-				blueprintTools = append(blueprintTools, installPath)
+				blueprintTools = append(blueprintTools, binaryModule.InstallPath())
 			}
 			if binaryModule.properties.PrimaryBuilder {
 				primaryBuilders = append(primaryBuilders, binaryModule)
diff --git a/context.go b/context.go
index 9dd68b4..4b9ea72 100644
--- a/context.go
+++ b/context.go
@@ -19,6 +19,7 @@
 	"errors"
 	"fmt"
 	"io"
+	"os"
 	"path/filepath"
 	"reflect"
 	"runtime"
@@ -793,6 +794,23 @@
 
 	f, err := c.fs.Open(filename)
 	if err != nil {
+		// couldn't open the file; see if we can provide a clearer error than "could not open file"
+		stats, statErr := c.fs.Lstat(filename)
+		if statErr == nil {
+			isSymlink := stats.Mode()&os.ModeSymlink != 0
+			if isSymlink {
+				err = fmt.Errorf("could not open symlink %v : %v", filename, err)
+				target, readlinkErr := os.Readlink(filename)
+				if readlinkErr == nil {
+					_, targetStatsErr := c.fs.Lstat(target)
+					if targetStatsErr != nil {
+						err = fmt.Errorf("could not open symlink %v; its target (%v) cannot be opened", filename, target)
+					}
+				}
+			} else {
+				err = fmt.Errorf("%v exists but could not be opened: %v", filename, err)
+			}
+		}
 		errsCh <- []error{err}
 		return
 	}
diff --git a/pathtools/fs.go b/pathtools/fs.go
index 4f98c6e..60d73b3 100644
--- a/pathtools/fs.go
+++ b/pathtools/fs.go
@@ -16,6 +16,7 @@
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -61,6 +62,7 @@
 	Glob(pattern string, excludes []string) (matches, dirs []string, err error)
 	glob(pattern string) (matches []string, err error)
 	IsDir(name string) (bool, error)
+	Lstat(name string) (os.FileInfo, error)
 }
 
 // osFs implements FileSystem using the local disk.
@@ -94,6 +96,10 @@
 	return filepath.Glob(pattern)
 }
 
+func (osFs) Lstat(path string) (stats os.FileInfo, err error) {
+	return os.Lstat(path)
+}
+
 type mockFs struct {
 	files map[string][]byte
 	dirs  map[string]bool
@@ -150,3 +156,7 @@
 	}
 	return matches, nil
 }
+
+func (m *mockFs) Lstat(path string) (stats os.FileInfo, err error) {
+	return nil, errors.New("Lstat is not yet implemented in MockFs")
+}
diff --git a/tests/test_tree_tests.sh b/tests/test_tree_tests.sh
index dd545c7..b393d30 100755
--- a/tests/test_tree_tests.sh
+++ b/tests/test_tree_tests.sh
@@ -5,19 +5,25 @@
 }
 
 # Go to top of blueprint tree
-TOP=$(dirname ${BASH_SOURCE[0]})/..
-cd ${TOP}
+cd $(dirname ${BASH_SOURCE[0]})/..
+TOP=${PWD}
 
-rm -rf out.test
-mkdir out.test
+export TEMPDIR=$(mktemp -d -t blueprint.test.XXX)
 
-rm -rf src.test
-mkdir src.test
-cp -r tests/test_tree src.test/test_tree
-ln -s ../.. src.test/test_tree/blueprint
+function cleanup() {
+    cd "${TOP}"
+    rm -rf "${TEMPDIR}"
+}
+trap cleanup EXIT
 
-cd out.test
-export SRCDIR=../src.test/test_tree
+export OUTDIR="${TEMPDIR}/out"
+mkdir "${OUTDIR}"
+
+export SRCDIR="${TEMPDIR}/src"
+cp -r tests/test_tree "${SRCDIR}"
+ln -s "${TOP}" "${SRCDIR}/blueprint"
+
+cd "${OUTDIR}"
 export BLUEPRINTDIR=${SRCDIR}/blueprint
 ${SRCDIR}/blueprint/bootstrap.bash $@
 ./blueprint.bash