github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/go/not-internal/imports/scan.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package imports 6 7 import ( 8 "fmt" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "sort" 13 "strconv" 14 "strings" 15 ) 16 17 func ScanDir(dir string, tags map[string]bool) ([]string, []string, error) { 18 infos, err := ioutil.ReadDir(dir) 19 if err != nil { 20 return nil, nil, err 21 } 22 var files []string 23 for _, info := range infos { 24 name := info.Name() 25 26 // If the directory entry is a symlink, stat it to obtain the info for the 27 // link target instead of the link itself. 28 if info.Mode()&os.ModeSymlink != 0 { 29 info, err = os.Stat(filepath.Join(dir, name)) 30 if err != nil { 31 continue // Ignore broken symlinks. 32 } 33 } 34 35 if info.Mode().IsRegular() && !strings.HasPrefix(name, "_") && strings.HasSuffix(name, ".go") && MatchFile(name, tags) { 36 files = append(files, filepath.Join(dir, name)) 37 } 38 } 39 return scanFiles(files, tags, false) 40 } 41 42 func ScanFiles(files []string, tags map[string]bool) ([]string, []string, error) { 43 return scanFiles(files, tags, true) 44 } 45 46 func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]string, []string, error) { 47 imports := make(map[string]bool) 48 testImports := make(map[string]bool) 49 numFiles := 0 50 Files: 51 for _, name := range files { 52 r, err := os.Open(name) 53 if err != nil { 54 return nil, nil, err 55 } 56 var list []string 57 data, err := ReadImports(r, false, &list) 58 r.Close() 59 if err != nil { 60 return nil, nil, fmt.Errorf("reading %s: %v", name, err) 61 } 62 63 // import "C" is implicit requirement of cgo tag. 64 // When listing files on the command line (explicitFiles=true) 65 // we do not apply build tag filtering but we still do apply 66 // cgo filtering, so no explicitFiles check here. 67 // Why? Because we always have, and it's not worth breaking 68 // that behavior now. 69 for _, path := range list { 70 if path == `"C"` && !tags["cgo"] && !tags["*"] { 71 continue Files 72 } 73 } 74 75 if !explicitFiles && !ShouldBuild(data, tags) { 76 continue 77 } 78 numFiles++ 79 m := imports 80 if strings.HasSuffix(name, "_test.go") { 81 m = testImports 82 } 83 for _, p := range list { 84 q, err := strconv.Unquote(p) 85 if err != nil { 86 continue 87 } 88 m[q] = true 89 } 90 } 91 if numFiles == 0 { 92 return nil, nil, ErrNoGo 93 } 94 return keys(imports), keys(testImports), nil 95 } 96 97 var ErrNoGo = fmt.Errorf("no Go source files") 98 99 func keys(m map[string]bool) []string { 100 var list []string 101 for k := range m { 102 list = append(list, k) 103 } 104 sort.Strings(list) 105 return list 106 }