Use a CommandLine struct to store the command line parsed by the OptionProcessor.
This replaces the startup_args_, command_ and command_argument members to allow a more consistent representation of the command line throughout the class.
PiperOrigin-RevId: 161408010
diff --git a/src/main/cpp/option_processor.cc b/src/main/cpp/option_processor.cc
index db19d3f..fc6d8b1 100644
--- a/src/main/cpp/option_processor.cc
+++ b/src/main/cpp/option_processor.cc
@@ -169,14 +169,12 @@
OptionProcessor::OptionProcessor(
const WorkspaceLayout* workspace_layout,
std::unique_ptr<StartupOptions> default_startup_options)
- : initialized_(false),
- workspace_layout_(workspace_layout),
+ : workspace_layout_(workspace_layout),
parsed_startup_options_(std::move(default_startup_options)) {
}
std::unique_ptr<CommandLine> OptionProcessor::SplitCommandLine(
- const vector<string>& args,
- string* error) {
+ const vector<string>& args, string* error) const {
const string lowercase_product_name =
parsed_startup_options_->GetLowercaseProductName();
@@ -299,6 +297,7 @@
}
namespace internal {
+
vector<string> DedupeBlazercPaths(const vector<string>& paths) {
set<string> canonical_paths;
vector<string> result;
@@ -314,6 +313,7 @@
}
return result;
}
+
} // namespace internal
// Parses the arguments provided in args using the workspace path and the
@@ -323,24 +323,19 @@
const string& workspace,
const string& cwd,
string* error) {
- assert(!initialized_);
- initialized_ = true;
- args_ = args;
- std::unique_ptr<CommandLine> cmd_line = SplitCommandLine(args, error);
- if (cmd_line == nullptr) {
+ cmd_line_ = SplitCommandLine(args, error);
+ if (cmd_line_ == nullptr) {
return blaze_exit_code::BAD_ARGV;
}
- explicit_command_arguments_ = cmd_line->command_args;
-
- const char* blazerc = SearchUnaryOption(cmd_line->startup_args, "--blazerc");
+ const char* blazerc = SearchUnaryOption(cmd_line_->startup_args, "--blazerc");
if (blazerc == NULL) {
- blazerc = SearchUnaryOption(cmd_line->startup_args, "--bazelrc");
+ blazerc = SearchUnaryOption(cmd_line_->startup_args, "--bazelrc");
}
bool use_master_blazerc = true;
- if (SearchNullaryOption(cmd_line->startup_args, "--nomaster_blazerc") ||
- SearchNullaryOption(cmd_line->startup_args, "--nomaster_bazelrc")) {
+ if (SearchNullaryOption(cmd_line_->startup_args, "--nomaster_blazerc") ||
+ SearchNullaryOption(cmd_line_->startup_args, "--nomaster_bazelrc")) {
use_master_blazerc = false;
}
@@ -350,7 +345,7 @@
vector<string> candidate_blazerc_paths;
if (use_master_blazerc) {
workspace_layout_->FindCandidateBlazercPaths(
- workspace, cwd, cmd_line->path_to_binary, cmd_line->startup_args,
+ workspace, cwd, cmd_line_->path_to_binary, cmd_line_->startup_args,
&candidate_blazerc_paths);
}
@@ -386,20 +381,8 @@
return parse_startup_options_exit_code;
}
- // Once we're done with startup options the next arg is the command.
- if (startup_args_ + 1 >= args.size()) {
- command_ = "";
- return blaze_exit_code::SUCCESS;
- }
- command_ = args[startup_args_ + 1];
-
- AddRcfileArgsAndOptions(cwd);
-
- // The rest of the args are the command options.
- for (unsigned int cmd_arg = startup_args_ + 2;
- cmd_arg < args.size(); cmd_arg++) {
- command_arguments_.push_back(args[cmd_arg]);
- }
+ blazerc_and_env_command_args_ = GetBlazercAndEnvCommandArgs(
+ cwd, blazercs_, rcoptions_);
return blaze_exit_code::SUCCESS;
}
@@ -417,69 +400,28 @@
return ParseOptions(args, workspace, cwd, error);
}
-blaze_exit_code::ExitCode OptionProcessor::ParseStartupOptions(string *error) {
- // Process rcfile startup options
- map< string, vector<RcOption> >::const_iterator it =
- rcoptions_.find("startup");
- blaze_exit_code::ExitCode process_arg_exit_code;
- bool is_space_separated;
- if (it != rcoptions_.end()) {
- const vector<RcOption>& startup_options = it->second;
- int i = 0;
- // Process all elements except the last one.
- for (; i < startup_options.size() - 1; i++) {
- const RcOption& option = startup_options[i];
- const string& blazerc = blazercs_[option.rcfile_index()]->Filename();
- process_arg_exit_code = parsed_startup_options_->ProcessArg(
- option.option(), startup_options[i + 1].option(), blazerc,
- &is_space_separated, error);
- if (process_arg_exit_code != blaze_exit_code::SUCCESS) {
- return process_arg_exit_code;
- }
- if (is_space_separated) {
- i++;
- }
- }
- // Process last element, if any.
- if (i < startup_options.size()) {
- const RcOption& option = startup_options[i];
- if (IsArg(option.option())) {
- const string& blazerc = blazercs_[option.rcfile_index()]->Filename();
- process_arg_exit_code = parsed_startup_options_->ProcessArg(
- option.option(), "", blazerc, &is_space_separated, error);
- if (process_arg_exit_code != blaze_exit_code::SUCCESS) {
- return process_arg_exit_code;
- }
- }
+blaze_exit_code::ExitCode OptionProcessor::ParseStartupOptions(
+ std::string *error) {
+ std::vector<RcStartupFlag> rcstartup_flags;
+
+ auto iter = rcoptions_.find("startup");
+ if (iter != rcoptions_.end()) {
+ const vector<RcOption>& startup_rcoptions = iter->second;
+ for (const RcOption& option : startup_rcoptions) {
+ rcstartup_flags.push_back(
+ RcStartupFlag(blazercs_[option.rcfile_index()]->Filename(),
+ option.option()));
}
}
- // Process command-line args next, so they override any of the same options
- // from .blazerc. Stop on first non-arg, this includes --help
- unsigned int i = 1;
- if (!args_.empty()) {
- for (; (i < args_.size() - 1) && IsArg(args_[i]); i++) {
- process_arg_exit_code = parsed_startup_options_->ProcessArg(
- args_[i], args_[i + 1], "", &is_space_separated, error);
- if (process_arg_exit_code != blaze_exit_code::SUCCESS) {
- return process_arg_exit_code;
- }
- if (is_space_separated) {
- i++;
- }
+ for (const std::string& arg : cmd_line_->startup_args) {
+ if (!IsArg(arg)) {
+ break;
}
- if (i < args_.size() && IsArg(args_[i])) {
- process_arg_exit_code = parsed_startup_options_->ProcessArg(
- args_[i], "", "", &is_space_separated, error);
- if (process_arg_exit_code != blaze_exit_code::SUCCESS) {
- return process_arg_exit_code;
- }
- i++;
- }
+ rcstartup_flags.push_back(RcStartupFlag("", arg));
}
- startup_args_ = i -1;
- return blaze_exit_code::SUCCESS;
+ return parsed_startup_options_->ProcessArgs(rcstartup_flags, error);
}
static bool IsValidEnvName(const char* p) {
@@ -532,39 +474,34 @@
}
#endif // defined(COMPILER_MSVC)
-// Appends the command and arguments from argc/argv to the end of arg_vector,
-// and also splices in some additional terminal and environment options between
-// the command and the arguments. NB: Keep the options added here in sync with
+// IMPORTANT: Keep the options added here in sync with
// BlazeCommandDispatcher.INTERNAL_COMMAND_OPTIONS!
-void OptionProcessor::AddRcfileArgsAndOptions(const string& cwd) {
+std::vector<std::string> OptionProcessor::GetBlazercAndEnvCommandArgs(
+ const std::string& cwd,
+ const std::vector<RcFile*>& blazercs,
+ const std::map<std::string, std::vector<RcOption>>& rcoptions) {
// Provide terminal options as coming from the least important rc file.
- command_arguments_.push_back("--rc_source=client");
- command_arguments_.push_back("--default_override=0:common=--is_stderr_atty=" +
- ToString(IsStderrStandardTerminal()));
- command_arguments_.push_back(
- "--default_override=0:common=--terminal_columns=" +
- ToString(GetStderrTerminalColumns()));
+ std::vector<std::string> result = {
+ "--rc_source=client",
+ "--default_override=0:common=--is_stderr_atty=" +
+ ToString(IsStderrStandardTerminal()),
+ "--default_override=0:common=--terminal_columns=" +
+ ToString(GetStderrTerminalColumns())};
// Push the options mapping .blazerc numbers to filenames.
- for (int i_blazerc = 0; i_blazerc < blazercs_.size(); i_blazerc++) {
- const RcFile* blazerc = blazercs_[i_blazerc];
- command_arguments_.push_back("--rc_source=" +
- blaze::ConvertPath(blazerc->Filename()));
+ for (const RcFile* blazerc : blazercs) {
+ result.push_back("--rc_source=" + blaze::ConvertPath(blazerc->Filename()));
}
- // Push the option defaults
- for (map<string, vector<RcOption> >::const_iterator it = rcoptions_.begin();
- it != rcoptions_.end(); ++it) {
- if (it->first == "startup") {
- // Skip startup options, they are parsed in the C++ wrapper
- continue;
- }
-
- for (int ii = 0; ii < it->second.size(); ii++) {
- const RcOption& rcoption = it->second[ii];
- command_arguments_.push_back(
- "--default_override=" + ToString(rcoption.rcfile_index() + 1) + ":"
- + it->first + "=" + rcoption.option());
+ // Process RcOptions exept for the startup flags that are already parsed
+ // by the client and shouldn't be handled by defult_overrides.
+ for (auto it = rcoptions.begin(); it != rcoptions.end(); ++it) {
+ if (it->first != "startup") {
+ for (const RcOption& rcoption : it->second) {
+ result.push_back(
+ "--default_override=" + ToString(rcoption.rcfile_index() + 1) + ":"
+ + it->first + "=" + rcoption.option());
+ }
}
}
@@ -573,31 +510,44 @@
string env_str(*env);
if (IsValidEnvName(*env)) {
PreprocessEnvString(&env_str);
- command_arguments_.push_back("--client_env=" + env_str);
+ result.push_back("--client_env=" + env_str);
}
}
- command_arguments_.push_back("--client_cwd=" + blaze::ConvertPath(cwd));
+ result.push_back("--client_cwd=" + blaze::ConvertPath(cwd));
if (IsEmacsTerminal()) {
- command_arguments_.push_back("--emacs");
+ result.push_back("--emacs");
}
+ return result;
}
-void OptionProcessor::GetCommandArguments(vector<string>* result) const {
- result->insert(result->end(),
- command_arguments_.begin(),
- command_arguments_.end());
+std::vector<std::string> OptionProcessor::GetCommandArguments() const {
+ assert(cmd_line_ != nullptr);
+ // When the user didn't specify a command, the server expects the command
+ // arguments to be empty in order to display the help message.
+ if (cmd_line_->command.empty()) {
+ return {};
+ }
+
+ std::vector<std::string> command_args = blazerc_and_env_command_args_;
+ command_args.insert(command_args.end(),
+ cmd_line_->command_args.begin(),
+ cmd_line_->command_args.end());
+ return command_args;
}
std::vector<std::string> OptionProcessor::GetExplicitCommandArguments() const {
- return explicit_command_arguments_;
+ assert(cmd_line_ != nullptr);
+ return cmd_line_->command_args;
}
-const string& OptionProcessor::GetCommand() const {
- return command_;
+std::string OptionProcessor::GetCommand() const {
+ assert(cmd_line_ != nullptr);
+ return cmd_line_->command;
}
StartupOptions* OptionProcessor::GetParsedStartupOptions() const {
+ assert(parsed_startup_options_ != NULL);
return parsed_startup_options_.get();
}