diff options
Diffstat (limited to 'src/main/cpp/option_processor.cc')
-rw-r--r-- | src/main/cpp/option_processor.cc | 222 |
1 files changed, 152 insertions, 70 deletions
diff --git a/src/main/cpp/option_processor.cc b/src/main/cpp/option_processor.cc index 11da52a2cd..f4c246a9dc 100644 --- a/src/main/cpp/option_processor.cc +++ b/src/main/cpp/option_processor.cc @@ -13,6 +13,7 @@ // limitations under the License. #include "src/main/cpp/option_processor.h" +#include "src/main/cpp/option_processor-internal.h" #include <stdio.h> #include <stdlib.h> @@ -45,6 +46,7 @@ using std::string; using std::vector; constexpr char WorkspaceLayout::WorkspacePrefix[]; +static constexpr const char* kRcBasename = ".bazelrc"; static std::vector<std::string> GetProcessedEnv(); // Path to the system-wide bazelrc configuration file. @@ -135,51 +137,68 @@ std::unique_ptr<CommandLine> OptionProcessor::SplitCommandLine( new CommandLine(path_to_binary, startup_args, command, command_args)); } -blaze_exit_code::ExitCode OptionProcessor::FindUserBlazerc( - const char* cmd_line_rc_file, const string& workspace, - string* user_blazerc_file, string* error) const { - const string rc_basename = - "." + parsed_startup_options_->GetLowercaseProductName() + "rc"; +namespace internal { +std::string FindLegacyUserBazelrc(const char* cmd_line_rc_file, + const std::string& workspace) { if (cmd_line_rc_file != nullptr) { string rcFile = blaze::AbsolutePathFromFlag(cmd_line_rc_file); if (!blaze_util::CanReadFile(rcFile)) { - blaze_util::StringPrintf(error, - "Error: Unable to read %s file '%s'.", rc_basename.c_str(), - rcFile.c_str()); - return blaze_exit_code::BAD_ARGV; + // The actual rc file reading will catch this - we ignore this here in the + // legacy version since this is just a warning. Exit eagerly though. + return ""; } - *user_blazerc_file = rcFile; - return blaze_exit_code::SUCCESS; + return rcFile; } - string workspaceRcFile = blaze_util::JoinPath(workspace, rc_basename); + string workspaceRcFile = blaze_util::JoinPath(workspace, kRcBasename); if (blaze_util::CanReadFile(workspaceRcFile)) { - *user_blazerc_file = workspaceRcFile; - return blaze_exit_code::SUCCESS; + return workspaceRcFile; } string home = blaze::GetHomeDir(); if (!home.empty()) { - string userRcFile = blaze_util::JoinPath(home, rc_basename); + string userRcFile = blaze_util::JoinPath(home, kRcBasename); if (blaze_util::CanReadFile(userRcFile)) { - *user_blazerc_file = userRcFile; - return blaze_exit_code::SUCCESS; + return userRcFile; } } - - BAZEL_LOG(INFO) << "User provided no rc file."; - *user_blazerc_file = ""; - return blaze_exit_code::SUCCESS; + return ""; } -namespace internal { +std::set<std::string> GetOldRcPaths( + const WorkspaceLayout* workspace_layout, const std::string& workspace, + const std::string& cwd, const std::string& path_to_binary, + const std::vector<std::string>& startup_args) { + // Find the old list of rc files that would have been loaded here, so we can + // provide a useful warning about old rc files that might no longer be read. + std::vector<std::string> candidate_bazelrc_paths; + if (SearchNullaryOption(startup_args, "master_bazelrc", true)) { + const std::string workspace_rc = + workspace_layout->GetWorkspaceRcPath(workspace, startup_args); + const std::string binary_rc = + internal::FindRcAlongsideBinary(cwd, path_to_binary); + const std::string system_rc = internal::FindSystemWideRc(); + candidate_bazelrc_paths = {workspace_rc, binary_rc, system_rc}; + } + const std::vector<std::string> deduped_blazerc_paths = + internal::DedupeBlazercPaths(candidate_bazelrc_paths); + std::set<std::string> old_rc_paths(deduped_blazerc_paths.begin(), + deduped_blazerc_paths.end()); + string user_bazelrc_path = internal::FindLegacyUserBazelrc( + SearchUnaryOption(startup_args, "--bazelrc"), workspace); + if (!user_bazelrc_path.empty()) { + old_rc_paths.insert(user_bazelrc_path); + } + return old_rc_paths; +} -vector<string> DedupeBlazercPaths(const vector<string>& paths) { - set<string> canonical_paths; - vector<string> result; - for (const string& path : paths) { - const string canonical_path = blaze_util::MakeCanonical(path.c_str()); +std::vector<std::string> DedupeBlazercPaths( + const std::vector<std::string>& paths) { + std::set<std::string> canonical_paths; + std::vector<std::string> result; + for (const std::string& path : paths) { + const std::string canonical_path = blaze_util::MakeCanonical(path.c_str()); if (canonical_path.empty()) { // MakeCanonical returns an empty string when it fails. We ignore this // failure since blazerc paths may point to invalid locations. @@ -191,26 +210,22 @@ vector<string> DedupeBlazercPaths(const vector<string>& paths) { return result; } -string FindSystemWideRc() { - // MakeAbsoluteAndResolveWindowsEnvvars will standardize the form of the - // provided path. This also means we accept relative paths, which is - // is convenient for testing. - const string path = blaze_util::MakeAbsoluteAndResolveWindowsEnvvars( - system_bazelrc_path); +std::string FindSystemWideRc() { + const std::string path = + blaze_util::MakeAbsoluteAndResolveWindowsEnvvars(system_bazelrc_path); if (blaze_util::CanReadFile(path)) { return path; } - BAZEL_LOG(INFO) << "Looked for a system bazelrc at path '" << path - << "', but none was found."; return ""; } -string FindRcAlongsideBinary(const string& cwd, const string& path_to_binary) { - const string path = blaze_util::IsAbsolute(path_to_binary) - ? path_to_binary - : blaze_util::JoinPath(cwd, path_to_binary); - const string base = blaze_util::Basename(path_to_binary); - const string binary_blazerc_path = path + "." + base + "rc"; +std::string FindRcAlongsideBinary(const std::string& cwd, + const std::string& path_to_binary) { + const std::string path = blaze_util::IsAbsolute(path_to_binary) + ? path_to_binary + : blaze_util::JoinPath(cwd, path_to_binary); + const std::string base = blaze_util::Basename(path_to_binary); + const std::string binary_blazerc_path = path + "." + base + "rc"; if (blaze_util::CanReadFile(binary_blazerc_path)) { return binary_blazerc_path; } @@ -243,41 +258,72 @@ blaze_exit_code::ExitCode OptionProcessor::GetRcFiles( std::string* error) const { assert(cmd_line != nullptr); assert(result_rc_files != nullptr); - - // Find the master bazelrcs if requested. This list may contain duplicates. - vector<string> candidate_bazelrc_paths; - if (SearchNullaryOption(cmd_line->startup_args, "master_bazelrc", true)) { - const string workspace_rc = - workspace_layout->GetWorkspaceRcPath(workspace, cmd_line->startup_args); - // TODO(b/36168162): Remove the alongside-binary rc file. (Part of GitHub - // issue #4502) - const string binary_rc = - internal::FindRcAlongsideBinary(cwd, cmd_line->path_to_binary); - // TODO(b/36168162): This is not the desired order, see - // https://github.com/bazelbuild/bazel/issues/4502#issuecomment-372697374. - const string system_rc = internal::FindSystemWideRc(); - BAZEL_LOG(INFO) - << "Looking for master bazelrcs in the following three paths: " - << workspace_rc << ", " << binary_rc << ", " << system_rc; - candidate_bazelrc_paths = {workspace_rc, binary_rc, system_rc}; + assert(!workspace.empty()); + + std::vector<std::string> rc_files; + + // Get the system rc (unless --nosystem_rc). + if (SearchNullaryOption(cmd_line->startup_args, "system_rc", true)) { + // MakeAbsoluteAndResolveWindowsEnvvars will standardize the form of the + // provided path. This also means we accept relative paths, which is + // is convenient for testing. + const std::string system_rc = + blaze_util::MakeAbsoluteAndResolveWindowsEnvvars(system_bazelrc_path); + rc_files.push_back(system_rc); } - string user_bazelrc_path; - blaze_exit_code::ExitCode find_bazelrc_exit_code = - FindUserBlazerc(SearchUnaryOption(cmd_line->startup_args, "--bazelrc"), - workspace, &user_bazelrc_path, error); - if (find_bazelrc_exit_code != blaze_exit_code::SUCCESS) { - return find_bazelrc_exit_code; + // Get the workspace rc: %workspace%/.bazelrc (unless --noworkspace_rc) + if (SearchNullaryOption(cmd_line->startup_args, "workspace_rc", true)) { + const std::string workspaceRcFile = + blaze_util::JoinPath(workspace, kRcBasename); + rc_files.push_back(workspaceRcFile); } - vector<string> deduped_blazerc_paths = - internal::DedupeBlazercPaths(candidate_bazelrc_paths); - deduped_blazerc_paths.push_back(user_bazelrc_path); + // Get the user rc: $HOME/.bazelrc (unless --nohome_rc) + if (SearchNullaryOption(cmd_line->startup_args, "home_rc", true)) { + const std::string home = blaze::GetHomeDir(); + if (home.empty()) { + BAZEL_LOG(WARNING) << "The home directory is not defined, no home_rc " + "will be looked for."; + } else { + rc_files.push_back(blaze_util::JoinPath(home, kRcBasename)); + } + } - for (const auto& bazelrc_path : deduped_blazerc_paths) { - if (bazelrc_path.empty()) { - continue; + // Get the command-line provided rc, passed as --bazelrc or nothing if the + // flag is absent. + const char* cmd_line_rc_file = + SearchUnaryOption(cmd_line->startup_args, "--bazelrc"); + if (cmd_line_rc_file != nullptr) { + string absolute_cmd_line_rc = blaze::AbsolutePathFromFlag(cmd_line_rc_file); + // Unlike the previous 3 paths, where we ignore it if the file does not + // exist or is unreadable, since this path is explicitly passed, this is an + // error. Check this condition here. + if (!blaze_util::CanReadFile(absolute_cmd_line_rc)) { + BAZEL_LOG(ERROR) << "Error: Unable to read .bazelrc file '" + << absolute_cmd_line_rc << "'."; + return blaze_exit_code::BAD_ARGV; } + rc_files.push_back(absolute_cmd_line_rc); + } + + // Log which files we're looking for before removing duplicates and + // non-existent files, so that this can serve to debug why a certain file is + // not being read. The final files which are read will be logged as they are + // parsed, and can be found using --announce_rc. + std::string joined_rcs; + blaze_util::JoinStrings(rc_files, ',', &joined_rcs); + BAZEL_LOG(INFO) << "Looking for the following rc files: " << joined_rcs; + + // It's possible that workspace == home, that files are symlinks for each + // other, or that the --bazelrc flag is a duplicate. Dedupe them to minimize + // the likelihood of repeated options. Since bazelrcs can include one another, + // this isn't sufficient to prevent duplicate options, but it's good enough. + // This also has the effect of removing paths that don't point to real files. + rc_files = internal::DedupeBlazercPaths(rc_files); + + // Parse these potential files, in priority order; + for (const auto& bazelrc_path : rc_files) { std::unique_ptr<RcFile> parsed_rc; blaze_exit_code::ExitCode parse_rcfile_exit_code = ParseRcFile( workspace_layout, workspace, bazelrc_path, &parsed_rc, error); @@ -287,6 +333,42 @@ blaze_exit_code::ExitCode OptionProcessor::GetRcFiles( result_rc_files->push_back(std::move(parsed_rc)); } + // Provide a warning for any old file that might have been missed with the new + // expectations. This compares "canonical" paths to one another, so should not + // require additional transformation. + // TODO(b/36168162): Remove this warning along with + // internal::GetOldRcPaths and internal::FindLegacyUserBazelrc after + // the transition period has passed. + std::set<std::string> read_files; + for (auto& result_rc : *result_rc_files) { + const std::deque<std::string>& sources = result_rc->sources(); + read_files.insert(sources.begin(), sources.end()); + } + + const std::set<std::string> old_files = + internal::GetOldRcPaths(workspace_layout, workspace, cwd, + cmd_line->path_to_binary, cmd_line->startup_args); + + // std::vector<std::string> old_files = internal::GetOldRcPathsInOrder( + // workspace_layout, workspace, cwd, cmd_line->path_to_binary, + // cmd_line->startup_args); + // + // std::sort(old_files.begin(), old_files.end()); + std::vector<std::string> lost_files(old_files.size()); + std::vector<std::string>::iterator end_iter = std::set_difference( + old_files.begin(), old_files.end(), read_files.begin(), read_files.end(), + lost_files.begin()); + lost_files.resize(end_iter - lost_files.begin()); + if (!lost_files.empty()) { + std::string joined_lost_rcs; + blaze_util::JoinStrings(lost_files, '\n', &joined_lost_rcs); + BAZEL_LOG(WARNING) + << "The following rc files are no longer being read, please transfer " + "their contents or import their path into one of the standard rc " + "files:\n" + << joined_lost_rcs; + } + return blaze_exit_code::SUCCESS; } |