Fix BOM-only pinning (#1592)
diff --git a/MODULE.bazel b/MODULE.bazel
index 8affb13..db0a453 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -576,6 +576,15 @@
     group = "com.google.cloud",
 )
 dev_maven.install(
+    name = "bom_only_pinning",
+    boms = [
+        "io.servicetalk:servicetalk-bom:0.42.62",
+    ],
+    fetch_sources = True,
+    lock_file = "//tests/custom_maven_install:bom_only_pinning_install.json",
+    strict_visibility = True,
+)
+dev_maven.install(
     name = "override_target_in_deps",
     artifacts = [
         "io.opentelemetry:opentelemetry-sdk:1.28.0",
@@ -1017,6 +1026,7 @@
 use_repo(
     dev_maven,
     "amend_artifacts",
+    "bom_only_pinning",
     "duplicate_version_warning",
     "duplicate_version_warning_same_version",
     "exclusion_testing",
diff --git a/private/rules/coursier.bzl b/private/rules/coursier.bzl
index 84d3195..96d9aff 100644
--- a/private/rules/coursier.bzl
+++ b/private/rules/coursier.bzl
@@ -197,9 +197,12 @@
     # This could be avoided by adding a disambiguator to the argsfile name.
 
     # Avoid argument limits by putting list of files to inspect into a file
+    argsfile_content = "\n".join([str(f) for f in files_to_inspect])
+    if argsfile_content:
+        argsfile_content += "\n"
     repository_ctx.file(
         "{}_argsfile".format(tool_name),
-        "\n".join([str(f) for f in files_to_inspect]) + "\n",
+        argsfile_content,
         executable = False,
     )
 
@@ -1162,6 +1165,7 @@
                 if _is_verbose(repository_ctx):
                     print("Removing source artifact with no file: %s" % dep["coord"])
             else:
+                dep["file"] = None
                 amended_deps.append(dep)
             continue
 
@@ -1279,8 +1283,8 @@
 
     for artifact in dep_tree["dependencies"]:
         # Some artifacts don't contain files; they are just parent artifacts
-        # to other artifacts.
-        if artifact["file"] == None:
+        # to other artifacts. Coursier may represent these as null or "".
+        if not artifact.get("file", None):
             continue
 
         coord_split = artifact["coord"].split(":")
@@ -1412,7 +1416,7 @@
 
     for artifact in dep_tree["dependencies"]:
         file = artifact["file"]
-        if file == None:
+        if not file:
             continue
         path = str(repository_ctx.path(file))
 
diff --git a/tests/bazel_run_tests.sh b/tests/bazel_run_tests.sh
index e45ef1a..0589ab9 100755
--- a/tests/bazel_run_tests.sh
+++ b/tests/bazel_run_tests.sh
@@ -253,6 +253,13 @@
   expect_not_log "\[None"
 }
 
+function test_bom_only_pinning() {
+  REPIN=1 bazel run @bom_only_pinning//:pin >> "$TEST_LOG" 2>&1
+
+  expect_log "Successfully pinned resolved artifacts"
+  expect_file_is_not_empty "tests/custom_maven_install/bom_only_pinning_install.json"
+}
+
 function test_coursier_resolution_with_boms() {
     # Only run for Bazel 7 or above
     RELEASE="$(bazel info release | sed -e 's/release //' | cut -d '.' -f 1)"
@@ -386,6 +393,7 @@
 }
 
 TESTS=(
+  "test_bom_only_pinning"
   "test_coursier_resolution_with_boms"
   "test_maven_resolution"
   "test_dependency_aggregation"
diff --git a/tests/custom_maven_install/bom_only_pinning_install.json b/tests/custom_maven_install/bom_only_pinning_install.json
new file mode 100644
index 0000000..bc7ca45
--- /dev/null
+++ b/tests/custom_maven_install/bom_only_pinning_install.json
@@ -0,0 +1,16 @@
+{
+  "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
+  "__INPUT_ARTIFACTS_HASH": {
+    "io.servicetalk:servicetalk-bom": -717155927,
+    "repositories": -1949687017
+  },
+  "__RESOLVED_ARTIFACTS_HASH": {},
+  "artifacts": {},
+  "dependencies": {},
+  "packages": {},
+  "repositories": {
+    "https://repo1.maven.org/maven2/": []
+  },
+  "services": {},
+  "version": "3"
+}