github.com/jonsyu1/godel@v0.0.0-20171017211503-64567a0cf169/apps/distgo/pkg/imports/imports.go (about) 1 // Copyright 2016 Palantir Technologies, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package imports 16 17 import ( 18 "go/build" 19 "os" 20 "path" 21 "path/filepath" 22 "strings" 23 24 "github.com/pkg/errors" 25 ) 26 27 // GoFiles is a map from package paths to the names of the buildable .go source files (.go files excluding Cgo and test 28 // files) in the package. 29 type GoFiles map[string][]string 30 31 // NewerThan returns true if the modification time of any of the GoFiles is newer than that of the provided file. 32 func (g GoFiles) NewerThan(fi os.FileInfo) (bool, error) { 33 for pkg, files := range g { 34 for _, goFile := range files { 35 currPath := path.Join(pkg, goFile) 36 currFi, err := os.Stat(currPath) 37 if err != nil { 38 return false, errors.Wrapf(err, "Failed to stat file %v", currPath) 39 } 40 if currFi.ModTime().After(fi.ModTime()) { 41 return true, nil 42 } 43 } 44 } 45 return false, nil 46 } 47 48 // AllFiles returns a map that contains all of the non-standard library Go files that are imported (and thus required to 49 // build) the specified package (including the package itself). The keys in the returned map are the paths to the 50 // packages and the values are a slice of the names of the .go source files in the package (excluding Cgo and test 51 // files). 52 func AllFiles(pkgPath string) (GoFiles, error) { 53 // package name to all non-test Go files in the package 54 pkgFiles := make(map[string][]string) 55 56 absPkgPath, err := filepath.Abs(pkgPath) 57 if err != nil { 58 return nil, errors.Wrapf(err, "Failed to convert %v to absolute path", pkgPath) 59 } 60 61 pkgsToProcess := []string{ 62 absPkgPath, 63 } 64 65 for len(pkgsToProcess) > 0 { 66 currPkg := pkgsToProcess[0] 67 pkgsToProcess = pkgsToProcess[1:] 68 if _, ok := pkgFiles[currPkg]; ok { 69 continue 70 } 71 72 // parse current package 73 pkg, err := build.Import(".", currPkg, build.ImportComment) 74 if err != nil { 75 return nil, errors.Wrapf(err, "Failed to import package %v", currPkg) 76 } 77 78 // add all files for the current package to output 79 pkgFiles[currPkg] = pkg.GoFiles 80 81 // convert all non-built-in imports into packages and add to packages to process 82 for importPath := range pkg.ImportPos { 83 if !strings.Contains(importPath, ".") { 84 // if import is a standard package, skip 85 continue 86 } 87 importPkg, err := build.Import(importPath, currPkg, build.ImportComment) 88 if err != nil { 89 return nil, errors.Wrapf(err, "Failed to import package %v using srcDir %v", importPath, currPkg) 90 } 91 pkgsToProcess = append(pkgsToProcess, importPkg.Dir) 92 } 93 } 94 return GoFiles(pkgFiles), nil 95 }