Automated g4 rollback of commit c4134802dd15d6ef5cca6521f6bf6aac395ee2ad.

*** Reason for rollback ***

Roll forward of directory name change

*** Original change description ***

Automated g4 rollback of commit 1d9e1ac90197b1d3d7b137ba3c1ada67bb9ba31b.

*** Reason for rollback ***

Breaks //src/test/shell/integration:force_delete_output_test

*** Original change description ***

Symlink output directories to the correct directory name

If the workspace directory is /path/to/my/proj and the name in the WORKSPACE
file is "floop", this will symlink the output directories to
output_base/execroot/floop instead of output_base/execroot/proj.

More prep for #1262, fixes #1681.

PiperOrigin-RevId: 156892980
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisPhaseStartedEvent.java b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisPhaseStartedEvent.java
index 48b746c..25e9594 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/AnalysisPhaseStartedEvent.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/AnalysisPhaseStartedEvent.java
@@ -15,6 +15,7 @@
 package com.google.devtools.build.lib.analysis;
 
 import com.google.common.base.Function;
+import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.devtools.build.lib.cmdline.Label;
 import com.google.devtools.build.lib.packages.Target;
@@ -26,19 +27,14 @@
  */
 public class AnalysisPhaseStartedEvent {
 
-  private final Iterable<Label> labels;
+  private final ImmutableSet<Target> targets;
 
   /**
    * Construct the event.
    * @param targets The set of active targets that remain.
    */
   public AnalysisPhaseStartedEvent(Collection<Target> targets) {
-    this.labels = Iterables.transform(targets, new Function<Target, Label>() {
-      @Override
-      public Label apply(Target input) {
-        return input.getLabel();
-      }
-    });
+    this.targets = ImmutableSet.copyOf(targets);
   }
 
   /**
@@ -46,6 +42,15 @@
    *     of the targets we attempted to load.
    */
   public Iterable<Label> getLabels() {
-    return labels;
+    return Iterables.transform(targets, new Function<Target, Label>() {
+      @Override
+      public Label apply(Target input) {
+        return input.getLabel();
+      }
+    });
+  }
+
+  public ImmutableSet<Target> getTargets() {
+    return targets;
   }
 }
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java
index 75ac3a0..ae209c9 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/ConfigurationCollectionFactory.java
@@ -39,6 +39,7 @@
    * @param loadedPackageProvider the package provider
    * @param buildOptions top-level build options representing the command-line
    * @param errorEventListener the event listener for errors
+   * @param mainRepositoryName the workspace name of the main repository
    * @return the top-level configuration
    * @throws InvalidConfigurationException
    */
@@ -48,7 +49,8 @@
       Cache<String, BuildConfiguration> cache,
       PackageProviderForConfigurations loadedPackageProvider,
       BuildOptions buildOptions,
-      EventHandler errorEventListener)
+      EventHandler errorEventListener,
+      String mainRepositoryName)
       throws InvalidConfigurationException, InterruptedException;
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
index f1e1db2..5989b62 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/RuleContext.java
@@ -257,7 +257,7 @@
    * Returns the workspace name for the rule.
    */
   public String getWorkspaceName() {
-    return rule.getPackage().getWorkspaceName();
+    return rule.getRepository().strippedName();
   }
 
   /**
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java
index 2dd779f..8c50b36 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BinTools.java
@@ -37,12 +37,14 @@
  */
 public final class BinTools {
   private final BlazeDirectories directories;
-  private final Path binDir;  // the working bin directory under execRoot
+  private final Path execrootParent;
   private final ImmutableList<String> embeddedTools;
 
+  private Path binDir;  // the working bin directory under execRoot
+
   private BinTools(BlazeDirectories directories, ImmutableList<String> tools) {
     this.directories = directories;
-    this.binDir = directories.getExecRoot().getRelative("_bin");
+    this.execrootParent = directories.getExecRoot().getParentDirectory();
     ImmutableList.Builder<String> builder = ImmutableList.builder();
     // Files under embedded_tools shouldn't be copied to under _bin dir
     // They won't be used during action execution time.
@@ -52,6 +54,7 @@
       }
     }
     this.embeddedTools = builder.build();
+    this.binDir = null;
   }
 
   /**
@@ -69,7 +72,8 @@
    */
   @VisibleForTesting
   public static BinTools empty(BlazeDirectories directories) {
-    return new BinTools(directories, ImmutableList.<String>of());
+    return new BinTools(directories, ImmutableList.<String>of()).setBinDir(
+        directories.getWorkspace().getBaseName());
   }
 
   /**
@@ -79,7 +83,8 @@
    */
   @VisibleForTesting
   public static BinTools forUnitTesting(BlazeDirectories directories, Iterable<String> tools) {
-    return new BinTools(directories, ImmutableList.copyOf(tools));
+    return new BinTools(directories, ImmutableList.copyOf(tools)).setBinDir(
+        directories.getWorkspace().getBaseName());
   }
 
   /**
@@ -88,7 +93,7 @@
    */
   @VisibleForTesting
   public static BinTools forIntegrationTesting(
-      BlazeDirectories directories, String srcDir, Iterable<String> tools)
+      BlazeDirectories directories, String srcDir, Iterable<String> tools, String repositoryName)
       throws IOException {
     Path srcPath = directories.getOutputBase().getFileSystem().getPath(srcDir);
     for (String embedded : tools) {
@@ -101,7 +106,7 @@
         // much point in creating a symlink to a non-existent binary here.
         continue;
       }
-      Path outputPath = directories.getExecRoot().getChild("_bin").getChild(embedded);
+      Path outputPath = directories.getExecRoot(repositoryName).getChild("_bin").getChild(embedded);
       if (outputPath.exists()) {
         outputPath.delete();
       }
@@ -109,7 +114,7 @@
       outputPath.createSymbolicLink(runfilesPath);
     }
 
-    return new BinTools(directories, ImmutableList.copyOf(tools));
+    return new BinTools(directories, ImmutableList.copyOf(tools)).setBinDir(repositoryName);
   }
 
   private static void scanDirectoryRecursively(
@@ -143,6 +148,7 @@
   }
 
   public Artifact getEmbeddedArtifact(String embedPath, ArtifactFactory artifactFactory) {
+    Preconditions.checkNotNull(binDir);
     PathFragment path = getExecPath(embedPath);
     Preconditions.checkNotNull(path, embedPath + " not found in embedded tools");
     return artifactFactory.getDerivedArtifact(path, binDir.getParentDirectory());
@@ -156,11 +162,17 @@
     return builder.build();
   }
 
+  private BinTools setBinDir(String workspaceName) {
+    binDir = execrootParent.getRelative(workspaceName).getRelative("_bin");
+    return this;
+  }
+
   /**
    * Initializes the build tools not available at absolute paths. Note that
    * these must be constant across all configurations.
    */
-  public void setupBuildTools() throws ExecException {
+  public void setupBuildTools(String workspaceName) throws ExecException {
+    setBinDir(workspaceName);
     try {
       FileSystemUtils.createDirectoryAndParents(binDir);
     } catch (IOException e) {
@@ -173,6 +185,7 @@
   }
 
   private void setupTool(String embeddedPath) throws ExecException {
+    Preconditions.checkNotNull(binDir);
     Path sourcePath = directories.getEmbeddedBinariesRoot().getRelative(embeddedPath);
     Path linkPath = binDir.getRelative(PathFragment.create(embeddedPath).getBaseName());
     linkTool(sourcePath, linkPath);
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
index 170c9c6..1098e2a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/BuildConfiguration.java
@@ -1137,6 +1137,7 @@
 
   private final ImmutableMap<Class<? extends Fragment>, Fragment> fragments;
   private final ImmutableMap<String, Class<? extends Fragment>> skylarkVisibleFragments;
+  private final RepositoryName mainRepositoryName;
 
 
   /**
@@ -1207,21 +1208,21 @@
     }
 
     Root getRoot(
-        RepositoryName repositoryName, String outputDirName, BlazeDirectories directories) {
+        RepositoryName repositoryName, String outputDirName, BlazeDirectories directories,
+        RepositoryName mainRepositoryName) {
       // e.g., execroot/repo1
-      Path execRoot = directories.getExecRoot();
+      Path execRoot = directories.getExecRoot(mainRepositoryName.strippedName());
       // e.g., execroot/repo1/bazel-out/config/bin
       Path outputDir = execRoot.getRelative(directories.getRelativeOutputPath())
           .getRelative(outputDirName);
       if (middleman) {
-        return INTERNER.intern(Root.middlemanRoot(execRoot, outputDir, repositoryName.isMain()));
+        return INTERNER.intern(Root.middlemanRoot(execRoot, outputDir,
+            repositoryName.equals(mainRepositoryName)));
       }
       // e.g., [[execroot/repo1]/bazel-out/config/bin]
       return INTERNER.intern(
-          Root.asDerivedRoot(
-              execRoot,
-              outputDir.getRelative(nameFragment),
-              repositoryName.isMain()));
+          Root.asDerivedRoot(execRoot, outputDir.getRelative(nameFragment),
+              repositoryName.equals(mainRepositoryName)));
     }
   }
 
@@ -1446,7 +1447,8 @@
    */
   public BuildConfiguration(BlazeDirectories directories,
       Map<Class<? extends Fragment>, Fragment> fragmentsMap,
-      BuildOptions buildOptions) {
+      BuildOptions buildOptions,
+      String repositoryName) {
     this.directories = directories;
     this.fragments = ImmutableSortedMap.copyOf(fragmentsMap, lexicalFragmentSorter);
 
@@ -1455,6 +1457,7 @@
     this.buildOptions = buildOptions.clone();
     this.actionsEnabled = buildOptions.enableActions();
     this.options = buildOptions.get(Options.class);
+    this.mainRepositoryName = RepositoryName.createFromValidStrippedName(repositoryName);
 
     Map<String, String> testEnv = new TreeMap<>();
     for (Map.Entry<String, String> entry : this.options.testEnvironment) {
@@ -1479,19 +1482,26 @@
         ? options.outputDirectoryName : mnemonic;
 
     this.outputDirectoryForMainRepository =
-        OutputDirectory.OUTPUT.getRoot(RepositoryName.MAIN, outputDirName, directories);
+        OutputDirectory.OUTPUT.getRoot(
+            RepositoryName.MAIN, outputDirName, directories, mainRepositoryName);
     this.binDirectoryForMainRepository =
-        OutputDirectory.BIN.getRoot(RepositoryName.MAIN, outputDirName, directories);
+        OutputDirectory.BIN.getRoot(
+            RepositoryName.MAIN, outputDirName, directories, mainRepositoryName);
     this.includeDirectoryForMainRepository =
-        OutputDirectory.INCLUDE.getRoot(RepositoryName.MAIN, outputDirName, directories);
+        OutputDirectory.INCLUDE.getRoot(
+            RepositoryName.MAIN, outputDirName, directories, mainRepositoryName);
     this.genfilesDirectoryForMainRepository =
-        OutputDirectory.GENFILES.getRoot(RepositoryName.MAIN, outputDirName, directories);
+        OutputDirectory.GENFILES.getRoot(
+            RepositoryName.MAIN, outputDirName, directories, mainRepositoryName);
     this.coverageDirectoryForMainRepository =
-        OutputDirectory.COVERAGE.getRoot(RepositoryName.MAIN, outputDirName, directories);
+        OutputDirectory.COVERAGE.getRoot(
+            RepositoryName.MAIN, outputDirName, directories, mainRepositoryName);
     this.testlogsDirectoryForMainRepository =
-        OutputDirectory.TESTLOGS.getRoot(RepositoryName.MAIN, outputDirName, directories);
+        OutputDirectory.TESTLOGS.getRoot(
+            RepositoryName.MAIN, outputDirName, directories, mainRepositoryName);
     this.middlemanDirectoryForMainRepository =
-        OutputDirectory.MIDDLEMAN.getRoot(RepositoryName.MAIN, outputDirName, directories);
+        OutputDirectory.MIDDLEMAN.getRoot(
+            RepositoryName.MAIN, outputDirName, directories, mainRepositoryName);
 
     this.platformName = buildPlatformName();
 
@@ -1540,8 +1550,8 @@
     }
     BuildOptions options = buildOptions.trim(
         getOptionsClasses(fragmentsMap.keySet(), ruleClassProvider));
-    BuildConfiguration newConfig =
-        new BuildConfiguration(directories, fragmentsMap, options);
+    BuildConfiguration newConfig = new BuildConfiguration(
+        directories, fragmentsMap, options, mainRepositoryName.strippedName());
     newConfig.setConfigurationTransitions(this.transitions);
     return newConfig;
   }
@@ -2117,9 +2127,10 @@
    * Returns the output directory for this build configuration.
    */
   public Root getOutputDirectory(RepositoryName repositoryName) {
-    return repositoryName.equals(RepositoryName.MAIN)
+    return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? outputDirectoryForMainRepository
-        : OutputDirectory.OUTPUT.getRoot(repositoryName, outputDirName, directories);
+        : OutputDirectory.OUTPUT.getRoot(
+            repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
   /**
@@ -2138,9 +2149,10 @@
    * repositories (external) but will need to be fixed.
    */
   public Root getBinDirectory(RepositoryName repositoryName) {
-    return repositoryName.equals(RepositoryName.MAIN)
+    return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? binDirectoryForMainRepository
-        : OutputDirectory.BIN.getRoot(repositoryName, outputDirName, directories);
+        : OutputDirectory.BIN.getRoot(
+            repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
   /**
@@ -2154,9 +2166,10 @@
    * Returns the include directory for this build configuration.
    */
   public Root getIncludeDirectory(RepositoryName repositoryName) {
-    return repositoryName.equals(RepositoryName.MAIN)
+    return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? includeDirectoryForMainRepository
-        : OutputDirectory.INCLUDE.getRoot(repositoryName, outputDirName, directories);
+        : OutputDirectory.INCLUDE.getRoot(
+            repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
   /**
@@ -2169,9 +2182,10 @@
   }
 
   public Root getGenfilesDirectory(RepositoryName repositoryName) {
-    return repositoryName.equals(RepositoryName.MAIN)
+    return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? genfilesDirectoryForMainRepository
-        : OutputDirectory.GENFILES.getRoot(repositoryName, outputDirName, directories);
+        : OutputDirectory.GENFILES.getRoot(
+            repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
   /**
@@ -2180,18 +2194,20 @@
    * needed for Jacoco's coverage reporting tools.
    */
   public Root getCoverageMetadataDirectory(RepositoryName repositoryName) {
-    return repositoryName.equals(RepositoryName.MAIN)
+    return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? coverageDirectoryForMainRepository
-        : OutputDirectory.COVERAGE.getRoot(repositoryName, outputDirName, directories);
+        : OutputDirectory.COVERAGE.getRoot(
+            repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
   /**
    * Returns the testlogs directory for this build configuration.
    */
   public Root getTestLogsDirectory(RepositoryName repositoryName) {
-    return repositoryName.equals(RepositoryName.MAIN)
+    return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? testlogsDirectoryForMainRepository
-        : OutputDirectory.TESTLOGS.getRoot(repositoryName, outputDirName, directories);
+        : OutputDirectory.TESTLOGS.getRoot(
+            repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
   /**
@@ -2218,9 +2234,10 @@
    * Returns the internal directory (used for middlemen) for this build configuration.
    */
   public Root getMiddlemanDirectory(RepositoryName repositoryName) {
-    return repositoryName.equals(RepositoryName.MAIN)
+    return repositoryName.isMain() || repositoryName.equals(mainRepositoryName)
         ? middlemanDirectoryForMainRepository
-        : OutputDirectory.MIDDLEMAN.getRoot(repositoryName, outputDirName, directories);
+        : OutputDirectory.MIDDLEMAN.getRoot(
+            repositoryName, outputDirName, directories, mainRepositoryName);
   }
 
   public boolean getAllowRuntimeDepsOnNeverLink() {
@@ -2235,6 +2252,10 @@
     return options.pluginList;
   }
 
+  public String getMainRepositoryName() {
+    return mainRepositoryName.strippedName();
+  }
+
   /**
    * Returns the configuration-dependent string for this configuration. This is also the name of the
    * configuration's base output directory unless {@link Options#outputDirectoryName} overrides it.
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java
index 9301784..3a95a4b 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/config/ConfigurationFactory.java
@@ -69,10 +69,11 @@
       Cache<String, BuildConfiguration> cache,
       PackageProviderForConfigurations loadedPackageProvider,
       BuildOptions buildOptions,
-      EventHandler errorEventListener)
+      EventHandler errorEventListener,
+      String mainRepositoryName)
       throws InvalidConfigurationException, InterruptedException {
     return configurationCollectionFactory.createConfigurations(this, cache,
-        loadedPackageProvider, buildOptions, errorEventListener);
+        loadedPackageProvider, buildOptions, errorEventListener, mainRepositoryName);
   }
 
   /**
@@ -85,7 +86,8 @@
   public BuildConfiguration getConfiguration(
       PackageProviderForConfigurations loadedPackageProvider,
       BuildOptions buildOptions,
-      Cache<String, BuildConfiguration> cache)
+      Cache<String, BuildConfiguration> cache,
+      String repositoryName)
       throws InvalidConfigurationException, InterruptedException {
 
     String cacheKey = buildOptions.computeCacheKey();
@@ -108,7 +110,7 @@
       return null;
     }
 
-    result = new BuildConfiguration(directories, fragments, buildOptions);
+    result = new BuildConfiguration(directories, fragments, buildOptions, repositoryName);
     cache.put(cacheKey, result);
     return result;
   }