github.com/sc0rp1us/gb@v0.4.1-0.20160319180011-4ba8cf1baa5a/vendor/imports.go (about) 1 package vendor 2 3 import ( 4 "fmt" 5 "go/parser" 6 "go/token" 7 "io" 8 "net/http" 9 "os" 10 "path/filepath" 11 "strings" 12 ) 13 14 // ParseImports parses Go packages from a specific root returning a set of import paths. 15 func ParseImports(root string) (map[string]bool, error) { 16 pkgs := make(map[string]bool) 17 18 var walkFn = func(path string, info os.FileInfo, err error) error { 19 if info.IsDir() { 20 name := info.Name() 21 if strings.HasPrefix(name, ".") || strings.HasPrefix(name, "_") || name == "testdata" { 22 return filepath.SkipDir 23 } 24 return nil 25 } 26 if filepath.Ext(path) != ".go" { // Parse only go source files 27 return nil 28 } 29 30 fs := token.NewFileSet() 31 f, err := parser.ParseFile(fs, path, nil, parser.ImportsOnly) 32 if err != nil { 33 return err 34 } 35 36 for _, s := range f.Imports { 37 p := strings.Replace(s.Path.Value, "\"", "", -1) 38 pkgs[p] = true 39 } 40 return nil 41 } 42 43 err := filepath.Walk(root, walkFn) 44 return pkgs, err 45 } 46 47 // FetchMetadata fetchs the remote metadata for path. 48 func FetchMetadata(path string, insecure bool) (rc io.ReadCloser, err error) { 49 defer func() { 50 if err != nil { 51 err = fmt.Errorf("unable to determine remote metadata protocol: %s", err) 52 } 53 }() 54 // try https first 55 rc, err = fetchMetadata("https", path) 56 if err == nil { 57 return 58 } 59 // try http if supported 60 if insecure { 61 rc, err = fetchMetadata("http", path) 62 } 63 return 64 } 65 66 func fetchMetadata(scheme, path string) (io.ReadCloser, error) { 67 url := fmt.Sprintf("%s://%s?go-get=1", scheme, path) 68 switch scheme { 69 case "https", "http": 70 resp, err := http.Get(url) 71 if err != nil { 72 return nil, fmt.Errorf("failed to access url %q", url) 73 } 74 return resp.Body, nil 75 default: 76 return nil, fmt.Errorf("unknown remote protocol scheme: %q", scheme) 77 } 78 } 79 80 // ParseMetadata fetchs and decodes remote metadata for path. 81 func ParseMetadata(path string, insecure bool) (string, string, string, error) { 82 rc, err := FetchMetadata(path, insecure) 83 if err != nil { 84 return "", "", "", err 85 } 86 defer rc.Close() 87 88 imports, err := parseMetaGoImports(rc) 89 if err != nil { 90 return "", "", "", err 91 } 92 match := -1 93 for i, im := range imports { 94 if !strings.HasPrefix(path, im.Prefix) { 95 continue 96 } 97 if match != -1 { 98 return "", "", "", fmt.Errorf("multiple meta tags match import path %q", path) 99 } 100 match = i 101 } 102 if match == -1 { 103 return "", "", "", fmt.Errorf("go-import metadata not found") 104 } 105 return imports[match].Prefix, imports[match].VCS, imports[match].RepoRoot, nil 106 }