aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2017-10-26 18:23:29 +0200
committerGravatar Dmitry Lomov <dslomov@google.com>2017-10-27 16:29:27 +0200
commitce714f8a1d93c540257d237144c88769251a0d62 (patch)
treed267e3d9a434308c4ebfd2daf7656ec958c27861 /src/tools
parentaca69a974ade777c54119dbe2c3a52aef61bc243 (diff)
Adjust the singlejar binary to accept an optional comma-separated "label" with
each entry in the --outputs flag. RELNOTES: n/a PiperOrigin-RevId: 173547248
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/singlejar/options.cc64
-rw-r--r--src/tools/singlejar/options.h23
-rw-r--r--src/tools/singlejar/options_test.cc6
-rw-r--r--src/tools/singlejar/output_jar.cc19
-rw-r--r--src/tools/singlejar/output_jar.h5
-rw-r--r--src/tools/singlejar/output_jar_simple_test.cc3
-rw-r--r--src/tools/singlejar/token_stream.h26
-rw-r--r--src/tools/singlejar/token_stream_test.cc19
8 files changed, 124 insertions, 41 deletions
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 <output_jar> 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 <string>
#include <vector>
+#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<std::string> manifest_lines;
- std::vector<std::string> input_jars;
+ std::vector<std::pair<std::string, std::string> > input_jars;
std::vector<std::string> resources;
std::vector<std::string> classpath_resources;
std::vector<std::string> 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 <string.h>
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#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<std::pair<std::string, std::string> > *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<std::string, std::string>(token_, ""));
+ } else {
+ std::string first = token_.substr(0, commapos);
+ token_.erase(0, commapos + 1);
+ optargs->push_back(std::pair<std::string, std::string>(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<std::pair<std::string, std::string> > 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);
+}