From ce714f8a1d93c540257d237144c88769251a0d62 Mon Sep 17 00:00:00 2001 From: Googler Date: Thu, 26 Oct 2017 18:23:29 +0200 Subject: Adjust the singlejar binary to accept an optional comma-separated "label" with each entry in the --outputs flag. RELNOTES: n/a PiperOrigin-RevId: 173547248 --- src/tools/singlejar/options.cc | 64 ++++++++++++++++----------- src/tools/singlejar/options.h | 23 +++++++++- src/tools/singlejar/options_test.cc | 6 +-- src/tools/singlejar/output_jar.cc | 19 +++++--- src/tools/singlejar/output_jar.h | 5 ++- src/tools/singlejar/output_jar_simple_test.cc | 3 +- src/tools/singlejar/token_stream.h | 26 +++++++++++ src/tools/singlejar/token_stream_test.cc | 19 ++++++++ 8 files changed, 124 insertions(+), 41 deletions(-) (limited to 'src/tools') diff --git a/src/tools/singlejar/options.cc b/src/tools/singlejar/options.cc index 86c35fe142..7e5a077d3e 100644 --- a/src/tools/singlejar/options.cc +++ b/src/tools/singlejar/options.cc @@ -15,43 +15,55 @@ #include "src/tools/singlejar/options.h" #include "src/tools/singlejar/diag.h" -#include "src/tools/singlejar/token_stream.h" void Options::ParseCommandLine(int argc, const char * const argv[]) { ArgTokenStream tokens(argc, argv); std::string optarg; while (!tokens.AtEnd()) { - if (tokens.MatchAndSet("--output", &output_jar) || - tokens.MatchAndSet("--main_class", &main_class) || - tokens.MatchAndSet("--java_launcher", &java_launcher) || - tokens.MatchAndSet("--deploy_manifest_lines", &manifest_lines) || - tokens.MatchAndSet("--sources", &input_jars) || - tokens.MatchAndSet("--resources", &resources) || - tokens.MatchAndSet("--classpath_resources", &classpath_resources) || - tokens.MatchAndSet("--include_prefixes", &include_prefixes) || - tokens.MatchAndSet("--exclude_build_data", &exclude_build_data) || - tokens.MatchAndSet("--compression", &force_compression) || - tokens.MatchAndSet("--dont_change_compression", - &preserve_compression) || - tokens.MatchAndSet("--normalize", &normalize_timestamps) || - tokens.MatchAndSet("--no_duplicates", &no_duplicates) || - tokens.MatchAndSet("--verbose", &verbose) || - tokens.MatchAndSet("--warn_duplicate_resources", - &warn_duplicate_resources) || - tokens.MatchAndSet("--nocompress_suffixes", &nocompress_suffixes) || - tokens.MatchAndSet("--check_desugar_deps", &check_desugar_deps)) { - continue; - } else if (tokens.MatchAndSet("--build_info_file", &optarg)) { - build_info_files.push_back(optarg); - continue; - } else if (tokens.MatchAndSet("--extra_build_info", &optarg)) { - build_info_lines.push_back(optarg); + if (ParseToken(&tokens)) { continue; } else { diag_errx(1, "Bad command line argument %s", tokens.token().c_str()); } } + PostValidateOptions(); +} + +bool Options::ParseToken(ArgTokenStream *tokens) { + std::string optarg; + + if (tokens->MatchAndSet("--output", &output_jar) || + tokens->MatchAndSet("--main_class", &main_class) || + tokens->MatchAndSet("--java_launcher", &java_launcher) || + tokens->MatchAndSet("--deploy_manifest_lines", &manifest_lines) || + tokens->MatchAndSet("--sources", &input_jars) || + tokens->MatchAndSet("--resources", &resources) || + tokens->MatchAndSet("--classpath_resources", &classpath_resources) || + tokens->MatchAndSet("--include_prefixes", &include_prefixes) || + tokens->MatchAndSet("--exclude_build_data", &exclude_build_data) || + tokens->MatchAndSet("--compression", &force_compression) || + tokens->MatchAndSet("--dont_change_compression", &preserve_compression) || + tokens->MatchAndSet("--normalize", &normalize_timestamps) || + tokens->MatchAndSet("--no_duplicates", &no_duplicates) || + tokens->MatchAndSet("--verbose", &verbose) || + tokens->MatchAndSet("--warn_duplicate_resources", + &warn_duplicate_resources) || + tokens->MatchAndSet("--nocompress_suffixes", &nocompress_suffixes) || + tokens->MatchAndSet("--check_desugar_deps", &check_desugar_deps)) { + return true; + } else if (tokens->MatchAndSet("--build_info_file", &optarg)) { + build_info_files.push_back(optarg); + return true; + } else if (tokens->MatchAndSet("--extra_build_info", &optarg)) { + build_info_lines.push_back(optarg); + return true; + } + + return false; +} + +void Options::PostValidateOptions() { if (output_jar.empty()) { diag_errx(1, "Use --output to specify the output file name"); } diff --git a/src/tools/singlejar/options.h b/src/tools/singlejar/options.h index c228fc6892..1fea135572 100644 --- a/src/tools/singlejar/options.h +++ b/src/tools/singlejar/options.h @@ -17,6 +17,7 @@ #include #include +#include "src/tools/singlejar/token_stream.h" /* Command line options. */ class Options { @@ -32,14 +33,16 @@ class Options { warn_duplicate_resources(false), check_desugar_deps(false) {} + virtual ~Options() {} + // Parses command line arguments into the fields of this instance. - void ParseCommandLine(int argc, const char * const argv[]); + void ParseCommandLine(int argc, const char *const argv[]); std::string output_jar; std::string main_class; std::string java_launcher; std::vector manifest_lines; - std::vector input_jars; + std::vector > input_jars; std::vector resources; std::vector classpath_resources; std::vector build_info_files; @@ -55,6 +58,22 @@ class Options { bool verbose; bool warn_duplicate_resources; bool check_desugar_deps; + + protected: + /* + * Given the token stream, consume one notional flag from the input stream and + * return true if the flag was recognized and fully consumed. This notional + * flag may result in many tokens being consumed, as flags like --inputs ends + * up consuming many future tokens: --inputs a b c d e --some_other_flag + */ + virtual bool ParseToken(ArgTokenStream *tokens); + + /* + * After all of the command line options are consumed, validate that the + * options make sense. This function will exit(1) if invalid combinations of + * flags are passed (e.g.: is missing --output_jar) + */ + virtual void PostValidateOptions(); }; #endif // THIRD_PARTY_BAZEL_SRC_TOOLS_SINGLEJAR_OPTIONS_H_ diff --git a/src/tools/singlejar/options_test.cc b/src/tools/singlejar/options_test.cc index a16c134161..2d33227885 100644 --- a/src/tools/singlejar/options_test.cc +++ b/src/tools/singlejar/options_test.cc @@ -93,9 +93,9 @@ TEST(OptionsTest, MultiOptargs) { options.ParseCommandLine(arraysize(args), args); ASSERT_EQ(3, options.input_jars.size()); - EXPECT_EQ("jar1", options.input_jars[0]); - EXPECT_EQ("jar2", options.input_jars[1]); - EXPECT_EQ("jar3", options.input_jars[2]); + EXPECT_EQ("jar1", options.input_jars[0].first); + EXPECT_EQ("jar2", options.input_jars[1].first); + EXPECT_EQ("jar3", options.input_jars[2].first); ASSERT_EQ(2, options.resources.size()); EXPECT_EQ("res1", options.resources[0]); EXPECT_EQ("res2", options.resources[1]); diff --git a/src/tools/singlejar/output_jar.cc b/src/tools/singlejar/output_jar.cc index df158749a6..a028df70a7 100644 --- a/src/tools/singlejar/output_jar.cc +++ b/src/tools/singlejar/output_jar.cc @@ -282,7 +282,11 @@ bool OutputJar::Open() { } bool OutputJar::AddJar(int jar_path_index) { - const std::string& input_jar_path = options_->input_jars[jar_path_index]; + const std::string &input_jar_path = + options_->input_jars[jar_path_index].first; + const std::string &input_jar_aux_label = + options_->input_jars[jar_path_index].second; + InputJar input_jar; if (!input_jar.Open(input_jar_path)) { return false; @@ -336,7 +340,7 @@ bool OutputJar::AddJar(int jar_path_index) { known_members_.emplace(service_path, EntryInfo{service_handler}); } } else { - ExtraHandler(jar_entry); + ExtraHandler(jar_entry, &input_jar_aux_label); } // Install a new entry unless it is already present. All the plain (non-dir) @@ -363,10 +367,11 @@ bool OutputJar::AddJar(int jar_path_index) { if (options_->no_duplicates || (options_->no_duplicate_classes && ends_with(file_name, file_name_length, ".class"))) { - diag_errx(1, "%s:%d: %.*s is present both in %s and %s", __FILE__, - __LINE__, file_name_length, file_name, - options_->input_jars[entry_info.input_jar_index_].c_str(), - input_jar_path.c_str()); + diag_errx( + 1, "%s:%d: %.*s is present both in %s and %s", __FILE__, __LINE__, + file_name_length, file_name, + options_->input_jars[entry_info.input_jar_index_].first.c_str(), + input_jar_path.c_str()); } else { duplicate_entries_++; continue; @@ -913,4 +918,4 @@ bool OutputJar::WriteBytes(const void *buffer, size_t count) { return written == count; } -void OutputJar::ExtraHandler(const CDH *) {} +void OutputJar::ExtraHandler(const CDH *, const std::string *) {} diff --git a/src/tools/singlejar/output_jar.h b/src/tools/singlejar/output_jar.h index 5917c864e1..0ad74c1ac2 100644 --- a/src/tools/singlejar/output_jar.h +++ b/src/tools/singlejar/output_jar.h @@ -34,14 +34,15 @@ class OutputJar { // Constructor. OutputJar(); // Do all that needs to be done. Can be called only once. - virtual int Doit(Options *options); + int Doit(Options *options); // Destructor. virtual ~OutputJar(); // Add a combiner to handle the entries with given name. OutputJar will // own the instance of the combiner and will delete it on self destruction. void ExtraCombiner(const std::string& entry_name, Combiner *combiner); // Additional file handler to be redefined by a subclass. - virtual void ExtraHandler(const CDH *entry); + virtual void ExtraHandler(const CDH *entry, + const std::string *input_jar_aux_label); // Return jar path. const char *path() const { return options_->output_jar.c_str(); } diff --git a/src/tools/singlejar/output_jar_simple_test.cc b/src/tools/singlejar/output_jar_simple_test.cc index 21bfbf7143..a0b946c214 100644 --- a/src/tools/singlejar/output_jar_simple_test.cc +++ b/src/tools/singlejar/output_jar_simple_test.cc @@ -54,7 +54,8 @@ static bool HasSubstr(const string &s, const string &what) { class CustomOutputJar : public OutputJar { public: ~CustomOutputJar() override {} - void ExtraHandler(const CDH *cdh) override { + void ExtraHandler(const CDH *cdh, + const std::string *input_jar_aux_label) override { auto file_name = cdh->file_name(); auto file_name_length = cdh->file_name_length(); if (file_name_length > 0 && file_name[file_name_length - 1] != '/' && diff --git a/src/tools/singlejar/token_stream.h b/src/tools/singlejar/token_stream.h index 5d6342c78d..23ee84d7ad 100644 --- a/src/tools/singlejar/token_stream.h +++ b/src/tools/singlejar/token_stream.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "src/tools/singlejar/diag.h" @@ -223,6 +224,31 @@ class ArgTokenStream { return true; } + // Process --OPTION OPTARG1,OPTSUFF1 OPTARG2,OPTSUFF2 ... + // If a current token is --OPTION, push_back all subsequent tokens up to the + // next option to the OPTARGS array, splitting the OPTARG,OPTSUFF by a comma, + // proceed to the next option and return true. + bool MatchAndSet(const char *option, + std::vector > *optargs) { + if (token_.compare(option) != 0) { + return false; + } + next(); + while (!AtEnd() && '-' != token_.at(0)) { + size_t commapos = token_.find(','); + if (commapos == std::string::npos) { + optargs->push_back(std::pair(token_, "")); + } else { + std::string first = token_.substr(0, commapos); + token_.erase(0, commapos + 1); + optargs->push_back(std::pair(first, token_)); + } + + next(); + } + return true; + } + // Current token. const std::string &token() const { return token_; } diff --git a/src/tools/singlejar/token_stream_test.cc b/src/tools/singlejar/token_stream_test.cc index 6d146cfd59..e277da3267 100644 --- a/src/tools/singlejar/token_stream_test.cc +++ b/src/tools/singlejar/token_stream_test.cc @@ -115,3 +115,22 @@ TEST(TokenStreamTest, OptargMulti) { EXPECT_TRUE(token_stream.AtEnd()); } + +// '--arg1 optval1,optsuff1 optval2,optstuff2 --arg2' command line. +TEST(TokenStreamTest, OptargMultiSplit) { + const char *args[] = {"--arg1", "optval1,optsuff1", "optval2,optsuff2", + "optvalnosuff"}; + ArgTokenStream token_stream(ARRAY_SIZE(args), args); + std::vector > optvals1; + + EXPECT_FALSE(token_stream.MatchAndSet("--foo", &optvals1)); + ASSERT_TRUE(token_stream.MatchAndSet("--arg1", &optvals1)); + + ASSERT_EQ(3, optvals1.size()); + EXPECT_EQ("optval1", optvals1[0].first); + EXPECT_EQ("optsuff1", optvals1[0].second); + EXPECT_EQ("optval2", optvals1[1].first); + EXPECT_EQ("optsuff2", optvals1[1].second); + EXPECT_EQ("optvalnosuff", optvals1[2].first); + EXPECT_EQ("", optvals1[2].second); +} -- cgit v1.2.3