Add a `--multi_release` option to singlejar

PiperOrigin-RevId: 437129108
diff --git a/src/tools/singlejar/combiners.cc b/src/tools/singlejar/combiners.cc
index e4da589..a6c8d59 100644
--- a/src/tools/singlejar/combiners.cc
+++ b/src/tools/singlejar/combiners.cc
@@ -188,6 +188,8 @@
 static const char *MULTI_RELEASE_PREFIX = "Multi-Release: ";
 static const size_t MULTI_RELEASE_PREFIX_LENGTH = strlen(MULTI_RELEASE_PREFIX);
 
+void ManifestCombiner::EnableMultiRelease() { multi_release_ = true; }
+
 void ManifestCombiner::AppendLine(const std::string &line) {
   if (line.find(MULTI_RELEASE_PREFIX, 0, MULTI_RELEASE_PREFIX_LENGTH) !=
       std::string::npos) {
diff --git a/src/tools/singlejar/combiners.h b/src/tools/singlejar/combiners.h
index a8e372e..b484140 100644
--- a/src/tools/singlejar/combiners.h
+++ b/src/tools/singlejar/combiners.h
@@ -145,6 +145,8 @@
   }
   ~ManifestCombiner() override;
 
+  void EnableMultiRelease();
+
   void AppendLine(const std::string &line);
 
   bool Merge(const CDH *cdh, const LH *lh) override;
diff --git a/src/tools/singlejar/options.cc b/src/tools/singlejar/options.cc
index f6673c7..633fd97 100644
--- a/src/tools/singlejar/options.cc
+++ b/src/tools/singlejar/options.cc
@@ -53,7 +53,8 @@
       tokens->MatchAndSet("--warn_duplicate_resources",
                           &warn_duplicate_resources) ||
       tokens->MatchAndSet("--nocompress_suffixes", &nocompress_suffixes) ||
-      tokens->MatchAndSet("--check_desugar_deps", &check_desugar_deps)) {
+      tokens->MatchAndSet("--check_desugar_deps", &check_desugar_deps) ||
+      tokens->MatchAndSet("--multi_release", &multi_release)) {
     return true;
   } else if (tokens->MatchAndSet("--build_info_file", &optarg)) {
     build_info_files.push_back(optarg);
diff --git a/src/tools/singlejar/options.h b/src/tools/singlejar/options.h
index 0c3c960..977e5de 100644
--- a/src/tools/singlejar/options.h
+++ b/src/tools/singlejar/options.h
@@ -33,7 +33,8 @@
         preserve_compression(false),
         verbose(false),
         warn_duplicate_resources(false),
-        check_desugar_deps(false) {}
+        check_desugar_deps(false),
+        multi_release(false) {}
 
   virtual ~Options() {}
 
@@ -62,6 +63,7 @@
   bool verbose;
   bool warn_duplicate_resources;
   bool check_desugar_deps;
+  bool multi_release;
 
  protected:
   /*
diff --git a/src/tools/singlejar/options_test.cc b/src/tools/singlejar/options_test.cc
index e9e591b..9da883d 100644
--- a/src/tools/singlejar/options_test.cc
+++ b/src/tools/singlejar/options_test.cc
@@ -36,6 +36,7 @@
   EXPECT_FALSE(options.verbose);
   EXPECT_FALSE(options.warn_duplicate_resources);
   EXPECT_FALSE(options.check_desugar_deps);
+  EXPECT_FALSE(options.multi_release);
   EXPECT_EQ("output_jar", options.output_jar);
 }
 
@@ -44,7 +45,9 @@
                         "--verbose",
                         "--warn_duplicate_resources",
                         "--check_desugar_deps",
-                        "--output", "output_jar"};
+                        "--output",
+                        "output_jar",
+                        "--multi_release"};
   Options options;
   options.ParseCommandLine(arraysize(args), args);
 
@@ -56,6 +59,7 @@
   ASSERT_TRUE(options.verbose);
   ASSERT_TRUE(options.warn_duplicate_resources);
   ASSERT_TRUE(options.check_desugar_deps);
+  ASSERT_TRUE(options.multi_release);
 }
 
 TEST(OptionsTest, SingleOptargs) {
diff --git a/src/tools/singlejar/output_jar.cc b/src/tools/singlejar/output_jar.cc
index 2b03d736..d6b2081 100644
--- a/src/tools/singlejar/output_jar.cc
+++ b/src/tools/singlejar/output_jar.cc
@@ -134,6 +134,9 @@
     AppendCDSArchive(options->cds_archive);
   }
 
+  if (options_->multi_release) {
+    manifest_.EnableMultiRelease();
+  }
   for (auto &manifest_line : options_->manifest_lines) {
     if (!manifest_line.empty()) {
       manifest_.AppendLine(manifest_line);
diff --git a/src/tools/singlejar/output_jar_simple_test.cc b/src/tools/singlejar/output_jar_simple_test.cc
index 7b427c8..d1a6645 100644
--- a/src/tools/singlejar/output_jar_simple_test.cc
+++ b/src/tools/singlejar/output_jar_simple_test.cc
@@ -889,4 +889,30 @@
   input_jar.Close();
 }
 
+// --multi_release option.
+TEST_F(OutputJarSimpleTest, MultiRelease) {
+  string out_path = OutputFilePath("out.jar");
+  CreateOutput(out_path, {"--multi_release"});
+  string manifest = GetEntryContents(out_path, "META-INF/MANIFEST.MF");
+  EXPECT_EQ(
+      "Manifest-Version: 1.0\r\n"
+      "Created-By: singlejar\r\n"
+      "Multi-Release: true\r\n"
+      "\r\n",
+      manifest);
+}
+
+// --multi_release option doesn't override --deploy_manifest_lines.
+TEST_F(OutputJarSimpleTest, MultiReleaseManifestLines) {
+  string out_path = OutputFilePath("out.jar");
+  CreateOutput(out_path, {"--multi_release", "--deploy_manifest_lines",
+                          "Multi-Release: false"});
+  string manifest = GetEntryContents(out_path, "META-INF/MANIFEST.MF");
+  EXPECT_EQ(
+      "Manifest-Version: 1.0\r\n"
+      "Created-By: singlejar\r\n"
+      "\r\n",
+      manifest);
+}
+
 }  // namespace