github.com/bazelbuild/bazel-gazelle@v0.36.1-0.20240520142334-61b277ba6fed/internal/module/module.go (about) 1 /* Copyright 2023 The Bazel Authors. All rights reserved. 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 16 // Package module provides functions to read information out of MODULE.bazel files. 17 18 package module 19 20 import ( 21 "os" 22 "path/filepath" 23 24 "github.com/bazelbuild/buildtools/build" 25 ) 26 27 // ExtractModuleToApparentNameMapping collects the mapping of module names (e.g. "rules_go") to 28 // user-configured apparent names (e.g. "my_rules_go") from the repos MODULE.bazel, if it exists. 29 // See https://bazel.build/external/module#repository_names_and_strict_deps for more information on 30 // apparent names. 31 func ExtractModuleToApparentNameMapping(repoRoot string) (func(string) string, error) { 32 moduleFile, err := parseModuleFile(repoRoot) 33 if err != nil { 34 return nil, err 35 } 36 var moduleToApparentName map[string]string 37 if moduleFile != nil { 38 moduleToApparentName = collectApparentNames(moduleFile) 39 } else { 40 // If there is no MODULE.bazel file, return a function that always returns the empty string. 41 // Languages will know to fall back to the WORKSPACE names of repos. 42 moduleToApparentName = make(map[string]string) 43 } 44 45 return func(moduleName string) string { 46 return moduleToApparentName[moduleName] 47 }, nil 48 } 49 50 func parseModuleFile(repoRoot string) (*build.File, error) { 51 path := filepath.Join(repoRoot, "MODULE.bazel") 52 bytes, err := os.ReadFile(path) 53 if os.IsNotExist(err) { 54 return nil, nil 55 } else if err != nil { 56 return nil, err 57 } 58 return build.ParseModule(path, bytes) 59 } 60 61 // Collects the mapping of module names (e.g. "rules_go") to user-configured apparent names (e.g. 62 // "my_rules_go"). See https://bazel.build/external/module#repository_names_and_strict_deps for more 63 // information on apparent names. 64 func collectApparentNames(m *build.File) map[string]string { 65 apparentNames := make(map[string]string) 66 67 for _, dep := range m.Rules("") { 68 if dep.Name() == "" { 69 continue 70 } 71 if dep.Kind() != "module" && dep.Kind() != "bazel_dep" { 72 continue 73 } 74 // We support module in addition to bazel_dep to handle language repos that use Gazelle to 75 // manage their own BUILD files. 76 if name := dep.AttrString("name"); name != "" { 77 if repoName := dep.AttrString("repo_name"); repoName != "" { 78 apparentNames[name] = repoName 79 } else { 80 apparentNames[name] = name 81 } 82 } 83 } 84 85 return apparentNames 86 }