kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/extractors/bazel/treeset/treeset.go (about) 1 /* 2 * Copyright 2021 The Kythe Authors. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // Package treeset provides functions for extracting targets that use bazel treesets. 18 package treeset 19 20 import ( 21 "context" 22 "os" 23 "path/filepath" 24 25 "kythe.io/kythe/go/platform/vfs" 26 "kythe.io/kythe/go/util/log" 27 28 "bitbucket.org/creachadair/stringset" 29 ) 30 31 // ListSources returns the source files underneath path. If path is a file, it returns a set with 32 // a single element. If path is a directory, it returns a set containing all the files 33 // (recursively) under path. 34 func ListSources(ctx context.Context, arg string) (stringset.Set, error) { 35 fi, err := vfs.Stat(ctx, arg) 36 if err != nil { 37 return nil, err 38 } 39 if fi.IsDir() { 40 s := stringset.New() 41 if err := filepath.Walk(arg, func(path string, info os.FileInfo, err error) error { 42 if err != nil { 43 return err 44 } 45 if !info.IsDir() { 46 s.Add(path) 47 } 48 return nil 49 }); err != nil { 50 return nil, err 51 } 52 return s, nil 53 } 54 return stringset.New(arg), nil 55 } 56 57 // FindMissingTreeInputs returns the required files that are not explicitly listed in bazel's 58 // inputs because they were tree artifacts. 59 // 60 // Some bazel rules use tree artifacts for the inputs to the compiler. These are directories that 61 // Bazel expands to files when the action is run. Consequently, the list of inputs that Bazel has 62 // only contains the tree artifact directory. This function reports the files that are (1) required, 63 // (2) not included in bazel's inputs, and (3) have their parent directory included in Bazel's 64 // inputs. 65 func FindMissingTreeInputs(inputs []string, requiredFiles stringset.Set) []string { 66 missingInputs := stringset.New() 67 inputsSet := stringset.New(inputs...) 68 for file := range requiredFiles { 69 if inputsSet.Contains(file) { 70 continue 71 } 72 dir := filepath.Dir(file) 73 for dir != "" { 74 if inputsSet.Contains(dir) { 75 missingInputs.Add(file) 76 break 77 } 78 dir = filepath.Dir(dir) 79 } 80 if dir == "" { 81 log.Warningf("couldn't find an input for %s\n", file) 82 } 83 84 } 85 return missingInputs.Elements() 86 } 87 88 // ExpandDirectories returns the list of files contained in the provided paths. 89 // 90 // Paths can be individual files or directories. If it's a directory - all files 91 // within that directory added to the result. 92 func ExpandDirectories(ctx context.Context, paths []string) []string { 93 var nps []string 94 for _, root := range paths { 95 files, err := ListSources(ctx, root) 96 if err != nil { 97 log.WarningContextf(ctx, "couldn't list files for %s: %s\n", root, err) 98 nps = append(nps, root) 99 } else { 100 nps = append(nps, files.Elements()...) 101 } 102 } 103 104 return nps 105 }