| // Copyright 2011 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. |
| |
| package main |
| |
| import ( |
| "log" |
| "os" |
| "path/filepath" |
| "runtime" |
| ) |
| |
| var ( |
| gopath []*pkgroot |
| imports []string |
| defaultRoot *pkgroot // default root for remote packages |
| ) |
| |
| // set up gopath: parse and validate GOROOT and GOPATH variables |
| func init() { |
| p, err := newPkgroot(root) |
| if err != nil { |
| log.Fatalf("Invalid GOROOT %q: %v", root, err) |
| } |
| p.goroot = true |
| gopath = []*pkgroot{p} |
| |
| for _, p := range filepath.SplitList(os.Getenv("GOPATH")) { |
| if p == "" { |
| continue |
| } |
| r, err := newPkgroot(p) |
| if err != nil { |
| log.Printf("Invalid GOPATH %q: %v", p, err) |
| continue |
| } |
| gopath = append(gopath, r) |
| imports = append(imports, r.pkgDir()) |
| |
| // select first GOPATH entry as default |
| if defaultRoot == nil { |
| defaultRoot = r |
| } |
| } |
| |
| // use GOROOT if no valid GOPATH specified |
| if defaultRoot == nil { |
| defaultRoot = gopath[0] |
| } |
| } |
| |
| type pkgroot struct { |
| path string |
| goroot bool // TODO(adg): remove this once Go tree re-organized |
| } |
| |
| func newPkgroot(p string) (*pkgroot, os.Error) { |
| if !filepath.IsAbs(p) { |
| return nil, os.NewError("must be absolute") |
| } |
| ep, err := filepath.EvalSymlinks(p) |
| if err != nil { |
| return nil, err |
| } |
| return &pkgroot{path: ep}, nil |
| } |
| |
| func (r *pkgroot) srcDir() string { |
| if r.goroot { |
| return filepath.Join(r.path, "src", "pkg") |
| } |
| return filepath.Join(r.path, "src") |
| } |
| |
| func (r *pkgroot) pkgDir() string { |
| goos, goarch := runtime.GOOS, runtime.GOARCH |
| if e := os.Getenv("GOOS"); e != "" { |
| goos = e |
| } |
| if e := os.Getenv("GOARCH"); e != "" { |
| goarch = e |
| } |
| return filepath.Join(r.path, "pkg", goos+"_"+goarch) |
| } |
| |
| func (r *pkgroot) binDir() string { |
| return filepath.Join(r.path, "bin") |
| } |
| |
| func (r *pkgroot) hasSrcDir(name string) bool { |
| fi, err := os.Stat(filepath.Join(r.srcDir(), name)) |
| if err != nil { |
| return false |
| } |
| return fi.IsDirectory() |
| } |
| |
| func (r *pkgroot) hasPkg(name string) bool { |
| fi, err := os.Stat(filepath.Join(r.pkgDir(), name+".a")) |
| if err != nil { |
| return false |
| } |
| return fi.IsRegular() |
| // TODO(adg): check object version is consistent |
| } |
| |
| // findPkgroot searches each of the gopath roots |
| // for the source code for the given import path. |
| func findPkgroot(importPath string) *pkgroot { |
| for _, r := range gopath { |
| if r.hasSrcDir(importPath) { |
| return r |
| } |
| } |
| return defaultRoot |
| } |