Make include() work with remote repositories.

This in itself is not very interesting because include() is deprecated, but it paves the way for fetching the appropriate dependencies for the eventual label-based load() statements.

--
MOS_MIGRATED_REVID=97849076
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalRepositoryFunction.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalRepositoryFunction.java
index cd7d6ac..e79ef39 100644
--- a/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalRepositoryFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/LocalRepositoryFunction.java
@@ -71,6 +71,8 @@
     }
     FileValue repositoryValue = getRepositoryDirectory(repositoryPath, env);
     if (repositoryValue == null) {
+      // TODO(bazel-team): If this returns null, we unnecessarily recreate the symlink above on the
+      // second execution.
       return null;
     }
 
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
index 7dc81e8..56fa8df 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/PackageFunction.java
@@ -232,7 +232,7 @@
     Set<SkyKey> subincludePackageLookupDepKeys = Sets.newHashSet();
     for (Label label : pkg.getSubincludeLabels()) {
       // Declare a dependency on the package lookup for the package giving access to the label.
-      subincludePackageLookupDepKeys.add(PackageLookupValue.key(label.getPackageFragment()));
+      subincludePackageLookupDepKeys.add(PackageLookupValue.key(label.getPackageIdentifier()));
     }
     Pair<? extends Map<PathFragment, PackageLookupValue>, Boolean> subincludePackageLookupResult =
         getPackageLookupDepsAndPropagateInconsistentFilesystemExceptions(
@@ -457,9 +457,27 @@
       throw new PackageFunctionException(new BuildFileContainsErrorsException(
           packageId, e.getMessage()), Transience.TRANSIENT);
     }
-    SkylarkImportResult importResult = fetchImportsFromBuildFile(buildFilePath, buildFileFragment,
-        packageId, preludeStatements, inputSource, env);
-    if (importResult == null) {
+
+    StoredEventHandler eventHandler = new StoredEventHandler();
+    BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(
+          inputSource, preludeStatements, eventHandler, null, true);
+
+    SkylarkImportResult importResult;
+    boolean includeRepositoriesFetched;
+    if (eventHandler.hasErrors()) {
+      // In case of Python preprocessing, errors have already been reported (see checkSyntax).
+      // In other cases, errors will be reported later.
+      // TODO(bazel-team): maybe we could get rid of checkSyntax and always report errors here?
+      importResult = new SkylarkImportResult(
+          ImmutableMap.<PathFragment, SkylarkEnvironment>of(), ImmutableList.<Label>of());
+      includeRepositoriesFetched = true;
+    } else {
+      importResult = fetchImportsFromBuildFile(buildFilePath, buildFileFragment,
+          packageId, buildFileAST, env);
+      includeRepositoriesFetched = fetchIncludeRepositoryDeps(env, buildFileAST);
+    }
+
+    if (importResult == null || !includeRepositoriesFetched) {
       return null;
     }
 
@@ -509,23 +527,26 @@
     return new PackageValue(pkg);
   }
 
-  private SkylarkImportResult fetchImportsFromBuildFile(Path buildFilePath,
-      PathFragment buildFileFragment, PackageIdentifier packageIdentifier,
-      List<Statement> preludeStatements, ParserInputSource inputSource, Environment env)
-      throws PackageFunctionException {
-    StoredEventHandler eventHandler = new StoredEventHandler();
-    BuildFileAST buildFileAST = BuildFileAST.parseBuildFile(
-          inputSource, preludeStatements, eventHandler, null, true);
-
-    if (eventHandler.hasErrors()) {
-      // In case of Python preprocessing, errors have already been reported (see checkSyntax).
-      // In other cases, errors will be reported later.
-      // TODO(bazel-team): maybe we could get rid of checkSyntax and always report errors here?
-      return new SkylarkImportResult(
-          ImmutableMap.<PathFragment, SkylarkEnvironment>of(),
-          ImmutableList.<Label>of());
+  private boolean fetchIncludeRepositoryDeps(Environment env, BuildFileAST ast) {
+    boolean ok = true;
+    for (Label label : ast.getIncludes()) {
+      if (!label.getPackageIdentifier().getRepository().isDefault()) {
+        // If this is the default repository, the include refers to the same repository, whose
+        // RepositoryValue is already a dependency of this PackageValue.
+        if (env.getValue(RepositoryValue.key(
+            label.getPackageIdentifier().getRepository())) == null) {
+          ok = false;
+        }
+      }
     }
 
+    return ok;
+  }
+
+  private SkylarkImportResult fetchImportsFromBuildFile(Path buildFilePath,
+      PathFragment buildFileFragment, PackageIdentifier packageIdentifier,
+      BuildFileAST buildFileAST, Environment env)
+      throws PackageFunctionException {
     ImmutableCollection<PathFragment> imports = buildFileAST.getImports();
     Map<PathFragment, SkylarkEnvironment> importMap = new HashMap<>();
     ImmutableList.Builder<SkylarkFileDependency> fileDependencies = ImmutableList.builder();
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
index dc0995a..35a9af8 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BuildFileAST.java
@@ -41,6 +41,8 @@
 
   private ImmutableSet<String> subincludes;
 
+  private ImmutableSet<Label> includes;
+
   /**
    * Whether any errors were encountered during scanning or parsing.
    */
@@ -94,6 +96,40 @@
     return subincludes.build();
   }
 
+  private ImmutableSet<Label> fetchIncludes(List<Statement> stmts) {
+    ImmutableSet.Builder<Label> result = new ImmutableSet.Builder<>();
+    for (Statement stmt : stmts) {
+      if (!(stmt instanceof ExpressionStatement)) {
+        continue;
+      }
+
+      ExpressionStatement expr = (ExpressionStatement) stmt;
+      if (!(expr.getExpression() instanceof FuncallExpression)) {
+        continue;
+      }
+
+      FuncallExpression funcall = (FuncallExpression) expr.getExpression();
+      if (!funcall.getFunction().getName().equals("include")
+          || funcall.getArguments().size() != 1) {
+        continue;
+      }
+
+      Expression arg = funcall.getArguments().get(0).value;
+      if (!(arg instanceof StringLiteral)) {
+        continue;
+      }
+
+      try {
+        Label label = Label.parseAbsolute(((StringLiteral) arg).getValue());
+        result.add(label);
+      } catch (Label.SyntaxException e) {
+        // Ignore. This will be reported when the BUILD file is actually evaluated.
+      }
+    }
+
+    return result.build();
+  }
+
   /** Collects paths from all load statements */
   private ImmutableSet<PathFragment> fetchLoads(List<Statement> stmts) {
     ImmutableSet.Builder<PathFragment> loads = new ImmutableSet.Builder<>();
@@ -149,6 +185,14 @@
     return subincludes;
   }
 
+  public synchronized ImmutableSet<Label> getIncludes() {
+    if (includes == null) {
+      includes = fetchIncludes(stmts);
+    }
+
+    return includes;
+  }
+
   /**
    * Executes this build file in a given Environment.
    *