Create symlinks using deps_mapping instead of input swapping

RELNOTES: None.
PiperOrigin-RevId: 301821539
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaActionsHelper.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaActionsHelper.java
index b617204..61a989f 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaActionsHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaActionsHelper.java
@@ -288,7 +288,7 @@
         .forEach((key, value) -> builder.put(key, ImmutableList.of(Pair.of(0L, value))));
     String inNewline =
         target.getUsualInputs().stream()
-            .map(this::getInputPathWithDepsMappingReplacement)
+            .map(PathFragment::getPathString)
             .collect(Collectors.joining("\n"));
     String out =
         target.getOutputs().stream()
@@ -320,12 +320,4 @@
         .modifyExecutionInfo(map, "NinjaRule");
     return map;
   }
-
-  private String getInputPathWithDepsMappingReplacement(PathFragment fragment) {
-    Artifact bazelArtifact = artifactsHelper.getDepsMappingArtifact(fragment);
-    if (bazelArtifact != null) {
-      return bazelArtifact.getPath().getPathString();
-    }
-    return fragment.getPathString();
-  }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaBuild.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaBuild.java
index 11cb1db..48f753d 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaBuild.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaBuild.java
@@ -27,6 +27,7 @@
 import com.google.devtools.build.lib.analysis.RuleContext;
 import com.google.devtools.build.lib.analysis.RunfilesProvider;
 import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
+import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
 import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
 import com.google.devtools.build.lib.bazel.rules.ninja.file.GenericParsingException;
 import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -63,12 +64,14 @@
         ImmutableSortedMap.naturalOrder();
     createDepsMap(
         ruleContext, graphProvider.getWorkingDirectory(), depsMapBuilder, symlinksMapBuilder);
+
+    ImmutableSortedMap<PathFragment, Artifact> depsMap = depsMapBuilder.build();
+
     NinjaGraphArtifactsHelper artifactsHelper =
         new NinjaGraphArtifactsHelper(
             ruleContext,
             graphProvider.getOutputRoot(),
             graphProvider.getWorkingDirectory(),
-            depsMapBuilder.build(),
             symlinksMapBuilder.build(),
             graphProvider.getOutputRootSymlinks());
     if (ruleContext.hasErrors()) {
@@ -76,8 +79,16 @@
     }
 
     try {
+      symlinkDepsMappings(ruleContext, artifactsHelper, depsMap);
+
       PhonyTargetArtifacts phonyTargetArtifacts =
           new PhonyTargetArtifacts(graphProvider.getPhonyTargetsMap(), artifactsHelper);
+      ImmutableSet<PathFragment> symlinks =
+          ImmutableSet.<PathFragment>builder()
+              .addAll(graphProvider.getOutputRootInputsSymlinks())
+              .addAll(depsMap.keySet())
+              .build();
+
       new NinjaActionsHelper(
               ruleContext,
               artifactsHelper,
@@ -85,7 +96,7 @@
               graphProvider.getPhonyTargetsMap(),
               phonyTargetArtifacts,
               pathsToBuild,
-              graphProvider.getOutputRootInputsSymlinks())
+              symlinks)
           .createNinjaActions();
 
       if (!checkOrphanArtifacts(ruleContext)) {
@@ -121,6 +132,28 @@
     }
   }
 
+  private static void symlinkDepsMappings(
+      RuleContext ruleContext,
+      NinjaGraphArtifactsHelper artifactsHelper,
+      ImmutableSortedMap<PathFragment, Artifact> depsMap)
+      throws GenericParsingException {
+    for (Map.Entry<PathFragment, Artifact> entry : depsMap.entrySet()) {
+      PathFragment depPath = entry.getKey();
+      Artifact destinationArtifact = entry.getValue();
+      Artifact outputArtifact = artifactsHelper.createOutputArtifact(depPath);
+
+      SymlinkAction symlinkAction =
+          SymlinkAction.toArtifact(
+              ruleContext.getActionOwner(),
+              destinationArtifact,
+              outputArtifact,
+              String.format(
+                  "Symlinking deps_mapping entry '%s' to '%s'",
+                  destinationArtifact.getExecPath(), outputArtifact.getExecPath()));
+      ruleContext.registerAction(symlinkAction);
+    }
+  }
+
   private static boolean checkOrphanArtifacts(RuleContext ruleContext) {
     ImmutableSet<Artifact> orphanArtifacts =
         ruleContext.getAnalysisEnvironment().getOrphanArtifacts();
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java
index bea9f17..72e905d 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraph.java
@@ -103,7 +103,6 @@
             outputRoot,
             workingDirectory,
             ImmutableSortedMap.of(),
-            ImmutableSortedMap.of(),
             ImmutableSortedSet.of());
     if (ruleContext.hasErrors()) {
       return null;
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraphArtifactsHelper.java b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraphArtifactsHelper.java
index 6f2f1d5..3f581f9 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraphArtifactsHelper.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/rules/ninja/actions/NinjaGraphArtifactsHelper.java
@@ -41,7 +41,6 @@
   private final PathFragment workingDirectory;
   private final ArtifactRoot derivedOutputRoot;
 
-  private final ImmutableSortedMap<PathFragment, Artifact> depsNameToArtifact;
   private final ImmutableSortedMap<PathFragment, Artifact> symlinkPathToArtifact;
   private final ImmutableSortedSet<PathFragment> outputRootSymlinks;
 
@@ -52,7 +51,6 @@
    * @param outputRootPath name of output directory for Ninja actions under execroot
    * @param workingDirectory relative path under execroot, the root for interpreting all paths in
    *     Ninja file
-   * @param depsNameToArtifact mapping between the path fragment in the Ninja file and prebuilt
    * @param symlinkPathToArtifact mapping of paths to artifacts for input symlinks under output_root
    * @param outputRootSymlinks list of output paths for which symlink artifacts should be created,
    *     paths are relative to the output_root.
@@ -61,13 +59,11 @@
       RuleContext ruleContext,
       PathFragment outputRootPath,
       PathFragment workingDirectory,
-      ImmutableSortedMap<PathFragment, Artifact> depsNameToArtifact,
       ImmutableSortedMap<PathFragment, Artifact> symlinkPathToArtifact,
       ImmutableSortedSet<PathFragment> outputRootSymlinks) {
     this.ruleContext = ruleContext;
     this.outputRootPath = outputRootPath;
     this.workingDirectory = workingDirectory;
-    this.depsNameToArtifact = depsNameToArtifact;
     this.symlinkPathToArtifact = symlinkPathToArtifact;
     this.outputRootSymlinks = outputRootSymlinks;
     Path execRoot =
@@ -98,10 +94,6 @@
   }
 
   Artifact getInputArtifact(PathFragment workingDirectoryPath) throws GenericParsingException {
-    if (depsNameToArtifact.containsKey(workingDirectoryPath)) {
-      return depsNameToArtifact.get(workingDirectoryPath);
-    }
-
     if (symlinkPathToArtifact.containsKey(workingDirectoryPath)) {
       return symlinkPathToArtifact.get(workingDirectoryPath);
     }
@@ -144,10 +136,6 @@
             execPath, ruleContext.getRule().getPackage().getSourceRoot());
   }
 
-  public Artifact getDepsMappingArtifact(PathFragment fragment) {
-    return depsNameToArtifact.get(fragment);
-  }
-
   public PathFragment getOutputRootPath() {
     return outputRootPath;
   }
diff --git a/src/test/java/com/google/devtools/build/lib/bazel/rules/ninja/NinjaBuildTest.java b/src/test/java/com/google/devtools/build/lib/bazel/rules/ninja/NinjaBuildTest.java
index 4d7e5d3..58ffb23 100644
--- a/src/test/java/com/google/devtools/build/lib/bazel/rules/ninja/NinjaBuildTest.java
+++ b/src/test/java/com/google/devtools/build/lib/bazel/rules/ninja/NinjaBuildTest.java
@@ -25,6 +25,7 @@
 import com.google.devtools.build.lib.actions.CommandLines.CommandLineAndParamFileInfo;
 import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
 import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.SymlinkAction;
 import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
 import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
 import com.google.devtools.build.lib.bazel.rules.ninja.actions.NinjaAction;
@@ -279,17 +280,24 @@
     assertThat(configuredTarget).isInstanceOf(RuleConfiguredTarget.class);
     RuleConfiguredTarget ninjaConfiguredTarget = (RuleConfiguredTarget) configuredTarget;
     ImmutableList<ActionAnalysisMetadata> actions = ninjaConfiguredTarget.getActions();
-    assertThat(actions).hasSize(1);
+    assertThat(actions).hasSize(2);
 
-    ActionAnalysisMetadata action = Iterables.getOnlyElement(actions);
+    ActionAnalysisMetadata symlinkAction = actions.get(0);
+    assertThat(symlinkAction).isInstanceOf(SymlinkAction.class);
+    assertThat(symlinkAction.getPrimaryInput().getExecPathString()).isEqualTo("input.txt");
+    assertThat(symlinkAction.getPrimaryOutput().getExecPathString())
+        .isEqualTo("build_config/placeholder");
+
+    ActionAnalysisMetadata action = actions.get(1);
     assertThat(action).isInstanceOf(NinjaAction.class);
     NinjaAction ninjaAction = (NinjaAction) action;
     List<CommandLineAndParamFileInfo> commandLines =
         ninjaAction.getCommandLines().getCommandLines();
     assertThat(commandLines).hasSize(1);
     assertThat(commandLines.get(0).commandLine.toString())
-        .endsWith("cd build_config && echo \"Hello $(cat /workspace/input.txt)!\" > hello.txt");
-    assertThat(ninjaAction.getPrimaryInput().getExecPathString()).isEqualTo("input.txt");
+        .endsWith("cd build_config && echo \"Hello $(cat placeholder)!\" > hello.txt");
+    assertThat(ninjaAction.getPrimaryInput().getExecPathString())
+        .isEqualTo("build_config/placeholder");
     assertThat(ninjaAction.getPrimaryOutput().getExecPathString())
         .isEqualTo("build_config/hello.txt");
   }
diff --git a/src/test/java/com/google/devtools/build/lib/blackbox/tests/NinjaBlackBoxTest.java b/src/test/java/com/google/devtools/build/lib/blackbox/tests/NinjaBlackBoxTest.java
index a8a415b..791ee82 100644
--- a/src/test/java/com/google/devtools/build/lib/blackbox/tests/NinjaBlackBoxTest.java
+++ b/src/test/java/com/google/devtools/build/lib/blackbox/tests/NinjaBlackBoxTest.java
@@ -493,12 +493,14 @@
     Exception exception = assertThrows(Exception.class, () -> bazel.build("//..."));
     assertThat(exception)
         .hasMessageThat()
-        .contains("ERROR: file 'a' is generated by these conflicting actions:");
+        .contains("ERROR: file 'a.txt' is generated by these conflicting actions:");
     assertThat(exception)
         .hasMessageThat()
         .contains(
-            "for a, previous action: action 'running Ninja targets: 'a'', "
-                + "attempted action: action 'running Ninja targets: 'a''");
+            "for a.txt, previous action: action "
+                + "'Symlinking deps_mapping entry 'variant1.txt' to 'build_dir/a.txt'', "
+                + "attempted action: action "
+                + "'Symlinking deps_mapping entry 'variant2.txt' to 'build_dir/a.txt''");
   }
 
   @Test