fix(packaging): Format `METADATA` correctly if given empty `requires_file` (#2771)

An empty `requires_file` used to be okay, but at some point regressed to
leaving an empty line (due to the `metadata.replace(...)`) in the
`METADATA` file - rendering the wheel uninstallable.

This PR initially attempted to solve that by introducing a new list that
processed `METADATA` lines go into, rather than relying on repeated
string replacement. But it seems like the repeated string replace
actually did more than simply process one line at a time, so I reverted
to a single substitution at the end.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6f86851..e7f9fe3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -96,6 +96,7 @@
 * (toolchains) Run the check on the Python interpreter in isolated mode, to ensure it's not affected by userland environment variables, such as `PYTHONPATH`.
 * (toolchains) Ensure temporary `.pyc` and `.pyo` files are also excluded from the interpreters repository files.
 * (pypi) Run interpreter version call in isolated mode, to ensure it's not affected by userland environment variables, such as `PYTHONPATH`.
+* (packaging) An empty `requires_file` is treated as if it were omitted, resulting in a valid `METADATA` file.
 
 {#v0-0-0-added}
 ### Added
diff --git a/examples/wheel/BUILD.bazel b/examples/wheel/BUILD.bazel
index d9ba800..b434e67 100644
--- a/examples/wheel/BUILD.bazel
+++ b/examples/wheel/BUILD.bazel
@@ -295,6 +295,12 @@
 )
 
 write_file(
+    name = "empty_requires_file",
+    out = "empty_requires.txt",
+    content = [""],
+)
+
+write_file(
     name = "extra_requires_file",
     out = "extra_requires.txt",
     content = """\
@@ -324,6 +330,15 @@
     deps = [":example_pkg"],
 )
 
+py_wheel(
+    name = "empty_requires_files",
+    distribution = "empty_requires_files",
+    python_tag = "py3",
+    requires_file = ":empty_requires.txt",
+    version = "0.0.1",
+    deps = [":example_pkg"],
+)
+
 # Package just a specific py_libraries, without their dependencies
 py_wheel(
     name = "minimal_data_files",
@@ -367,6 +382,7 @@
         ":custom_package_root_multi_prefix",
         ":custom_package_root_multi_prefix_reverse_order",
         ":customized",
+        ":empty_requires_files",
         ":extra_requires",
         ":filename_escaping",
         ":minimal_data_files",
diff --git a/examples/wheel/wheel_test.py b/examples/wheel/wheel_test.py
index a3d6034..9ec1503 100644
--- a/examples/wheel/wheel_test.py
+++ b/examples/wheel/wheel_test.py
@@ -483,7 +483,6 @@
                     if line.startswith(b"Requires-Dist:"):
                         requires.append(line.decode("utf-8").strip())
 
-            print(requires)
             self.assertEqual(
                 [
                     "Requires-Dist: tomli>=2.0.0",
@@ -495,6 +494,29 @@
                 requires,
             )
 
+    def test_empty_requires_file(self):
+        filename = self._get_path("empty_requires_files-0.0.1-py3-none-any.whl")
+
+        with zipfile.ZipFile(filename) as zf:
+            self.assertAllEntriesHasReproducibleMetadata(zf)
+            metadata_file = None
+            for f in zf.namelist():
+                if os.path.basename(f) == "METADATA":
+                    metadata_file = f
+            self.assertIsNotNone(metadata_file)
+
+            metadata = zf.read(metadata_file).decode("utf-8")
+            metadata_lines = metadata.splitlines()
+
+            requires = []
+            for i, line in enumerate(metadata_lines):
+                if line.startswith("Name:"):
+                    self.assertTrue(metadata_lines[i + 1].startswith("Version:"))
+                if line.startswith("Requires-Dist:"):
+                    requires.append(line.strip())
+
+            self.assertEqual([], requires)
+
     def test_minimal_data_files(self):
         filename = self._get_path("minimal_data_files-0.0.1-py3-none-any.whl")
 
diff --git a/python/packaging.bzl b/python/packaging.bzl
index 629af2d..b190635 100644
--- a/python/packaging.bzl
+++ b/python/packaging.bzl
@@ -101,6 +101,11 @@
 
     Currently only pure-python wheels are supported.
 
+    :::{versionchanged} VERSION_NEXT_FEATURE
+    From now on, an empty `requires_file` is treated as if it were omitted, resulting in a valid
+    `METADATA` file.
+    :::
+
     Examples:
 
     ```python
diff --git a/tools/wheelmaker.py b/tools/wheelmaker.py
index 23b18ec..908b3fe 100644
--- a/tools/wheelmaker.py
+++ b/tools/wheelmaker.py
@@ -599,7 +599,12 @@
 
                 reqs.append(get_new_requirement_line(reqs_text, extra))
 
-            metadata = metadata.replace(meta_line, "\n".join(reqs))
+            if reqs:
+                metadata = metadata.replace(meta_line, "\n".join(reqs))
+            # File is empty
+            # So replace the meta_line entirely, including removing newline chars
+            else:
+                metadata = re.sub(re.escape(meta_line) + r"(?:\r?\n)?", "", metadata, count=1)
 
         maker.add_metadata(
             metadata=metadata,