| /* Copyright 2023 The Bazel Authors. All rights reserved. |
| |
| Licensed under the Apache License, Version 2.0 (the "License"); |
| you may not use this file except in compliance with the License. |
| You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| */ |
| |
| // Package module provides functions to read information out of MODULE.bazel files. |
| |
| package module |
| |
| import ( |
| "os" |
| "path/filepath" |
| |
| "github.com/bazelbuild/buildtools/build" |
| ) |
| |
| // ExtractModuleToApparentNameMapping collects the mapping of module names (e.g. "rules_go") to |
| // user-configured apparent names (e.g. "my_rules_go") from the repos MODULE.bazel, if it exists. |
| // See https://bazel.build/external/module#repository_names_and_strict_deps for more information on |
| // apparent names. |
| func ExtractModuleToApparentNameMapping(repoRoot string) (func(string) string, error) { |
| moduleFile, err := parseModuleFile(repoRoot) |
| if err != nil { |
| return nil, err |
| } |
| var moduleToApparentName map[string]string |
| if moduleFile != nil { |
| moduleToApparentName = collectApparentNames(moduleFile) |
| } else { |
| // If there is no MODULE.bazel file, return a function that always returns the empty string. |
| // Languages will know to fall back to the WORKSPACE names of repos. |
| moduleToApparentName = make(map[string]string) |
| } |
| |
| return func(moduleName string) string { |
| return moduleToApparentName[moduleName] |
| }, nil |
| } |
| |
| func parseModuleFile(repoRoot string) (*build.File, error) { |
| path := filepath.Join(repoRoot, "MODULE.bazel") |
| bytes, err := os.ReadFile(path) |
| if os.IsNotExist(err) { |
| return nil, nil |
| } else if err != nil { |
| return nil, err |
| } |
| return build.ParseModule(path, bytes) |
| } |
| |
| // Collects the mapping of module names (e.g. "rules_go") to user-configured apparent names (e.g. |
| // "my_rules_go"). See https://bazel.build/external/module#repository_names_and_strict_deps for more |
| // information on apparent names. |
| func collectApparentNames(m *build.File) map[string]string { |
| apparentNames := make(map[string]string) |
| |
| for _, dep := range m.Rules("") { |
| if dep.Name() == "" { |
| continue |
| } |
| if dep.Kind() != "module" && dep.Kind() != "bazel_dep" { |
| continue |
| } |
| // We support module in addition to bazel_dep to handle language repos that use Gazelle to |
| // manage their own BUILD files. |
| if name := dep.AttrString("name"); name != "" { |
| if repoName := dep.AttrString("repo_name"); repoName != "" { |
| apparentNames[name] = repoName |
| } else { |
| apparentNames[name] = name |
| } |
| } |
| } |
| |
| return apparentNames |
| } |