Skip to content

Commit

Permalink
Lberki cherrypick 8.0.0 ignored subdirectories (#23999)
Browse files Browse the repository at this point in the history
As discussed; for ease of further cherry-picking, it's probably a good
idea to cherry-pick this big refactoring to 8.0.0 .
  • Loading branch information
lberki authored Oct 16, 2024
1 parent 19c91e9 commit 8bfb921
Show file tree
Hide file tree
Showing 59 changed files with 478 additions and 406 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

import com.github.difflib.patch.PatchFailedException;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.docgen.annot.DocCategory;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.bazel.debug.WorkspaceRuleEvent;
import com.google.devtools.build.lib.bazel.repository.PatchUtil;
import com.google.devtools.build.lib.bazel.repository.downloader.DownloadManager;
import com.google.devtools.build.lib.cmdline.IgnoredSubdirectories;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.packages.Attribute;
Expand Down Expand Up @@ -78,7 +78,7 @@ public class StarlarkRepositoryContext extends StarlarkBaseExternalContext {
private final Rule rule;
private final PathPackageLocator packageLocator;
private final StructImpl attrObject;
private final ImmutableSet<PathFragment> ignoredPatterns;
private final IgnoredSubdirectories ignoredSubdirectories;
private final SyscallCache syscallCache;
private final HashMap<RepoRecordedInput.DirTree, String> recordedDirTreeInputs = new HashMap<>();

Expand All @@ -90,7 +90,7 @@ public class StarlarkRepositoryContext extends StarlarkBaseExternalContext {
Rule rule,
PathPackageLocator packageLocator,
Path outputDirectory,
ImmutableSet<PathFragment> ignoredPatterns,
IgnoredSubdirectories ignoredSubdirectories,
Environment environment,
ImmutableMap<String, String> env,
DownloadManager downloadManager,
Expand All @@ -116,7 +116,7 @@ public class StarlarkRepositoryContext extends StarlarkBaseExternalContext {
/* allowWatchingPathsOutsideWorkspace= */ true);
this.rule = rule;
this.packageLocator = packageLocator;
this.ignoredPatterns = ignoredPatterns;
this.ignoredSubdirectories = ignoredSubdirectories;
this.syscallCache = syscallCache;
WorkspaceAttributeMapper attrs = WorkspaceAttributeMapper.of(rule);
ImmutableMap.Builder<String, Object> attrBuilder = new ImmutableMap.Builder<>();
Expand Down Expand Up @@ -177,10 +177,8 @@ private StarlarkPath externalPath(String method, Object pathObject)
}
Path workspaceRoot = packageLocator.getWorkspaceFile(syscallCache).getParentDirectory();
PathFragment relativePath = path.relativeTo(workspaceRoot);
for (PathFragment ignoredPattern : ignoredPatterns) {
if (relativePath.startsWith(ignoredPattern)) {
return starlarkPath;
}
if (ignoredSubdirectories.matchingEntry(relativePath) != null) {
return starlarkPath;
}
throw Starlark.errorf(
"%s can only be applied to external paths (that is, outside the workspace or ignored in"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.devtools.build.lib.bazel.bzlmod.NonRegistryOverride;
import com.google.devtools.build.lib.bazel.repository.RepositoryResolvedEvent;
import com.google.devtools.build.lib.bazel.repository.downloader.DownloadManager;
import com.google.devtools.build.lib.cmdline.IgnoredSubdirectories;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.RepositoryMapping;
Expand All @@ -52,7 +53,6 @@
import com.google.devtools.build.lib.skyframe.RepositoryMappingValue;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.SyscallCache;
import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
Expand Down Expand Up @@ -222,7 +222,8 @@ private FetchResult fetchInternal(
if (env.valuesMissing()) {
return null;
}
ImmutableSet<PathFragment> ignoredPatterns = checkNotNull(ignoredPackagesValue).getPatterns();
IgnoredSubdirectories ignoredSubdirectories =
checkNotNull(ignoredPackagesValue).asIgnoredSubdirectories();

Map<RepoRecordedInput, String> recordedInputValues = new LinkedHashMap<>();
try (Mutability mu = Mutability.create("Starlark repository");
Expand All @@ -231,7 +232,7 @@ private FetchResult fetchInternal(
rule,
packageLocator,
outputDirectory,
ignoredPatterns,
ignoredSubdirectories,
env,
ImmutableMap.copyOf(clientEnvironment),
downloadManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.cmdline.IgnoredSubdirectories;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.cmdline.RepositoryName;
Expand Down Expand Up @@ -387,7 +388,7 @@ public static ImmutableSet<String> eagerlyPlantSymlinkForestSinglePackagePath(
Path execroot,
Path sourceRoot,
String prefix,
ImmutableSet<Path> ignoredPaths,
IgnoredSubdirectories ignoredPaths,
boolean siblingRepositoryLayout)
throws IOException {
deleteTreesBelowNotPrefixed(execroot, prefix);
Expand Down Expand Up @@ -424,19 +425,19 @@ public static ImmutableSet<String> eagerlyPlantSymlinkForestSinglePackagePath(
static boolean symlinkShouldBePlanted(
String prefix, boolean siblingRepositoryLayout, String baseName, Path target) {
return symlinkShouldBePlanted(
prefix, ImmutableSet.of(), siblingRepositoryLayout, baseName, target);
prefix, IgnoredSubdirectories.EMPTY, siblingRepositoryLayout, baseName, target);
}

public static boolean symlinkShouldBePlanted(
String prefix,
ImmutableSet<Path> ignoredPaths,
IgnoredSubdirectories ignoredSubdirectories,
boolean siblingRepositoryLayout,
String baseName,
Path target) {
// Create any links that don't start with bazel-, and ignore external/ directory if
// user has it in the source tree because it conflicts with external repository location.
return !baseName.startsWith(prefix)
&& !ignoredPaths.contains(target)
&& ignoredSubdirectories.matchingEntry(target.asFragment().toRelative()) == null
&& (siblingRepositoryLayout
|| !baseName.equals(LabelConstants.EXTERNAL_PATH_PREFIX.getBaseName()));
}
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/google/devtools/build/lib/cmdline/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ java_library(
srcs = [
"BazelCompileContext.java",
"BazelModuleContext.java",
"IgnoredSubdirectories.java",
"Label.java",
"LabelConstants.java",
"LabelParser.java",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2024 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.cmdline;

import static com.google.common.collect.ImmutableSet.toImmutableSet;

import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.Objects;
import javax.annotation.Nullable;

/**
* A set of subdirectories to ignore during target pattern matching or globbing.
*
* <p>This is currently just a prefix, but will eventually support glob-style wildcards.
*/
public final class IgnoredSubdirectories {
public static final IgnoredSubdirectories EMPTY = new IgnoredSubdirectories(ImmutableSet.of());

private final ImmutableSet<PathFragment> prefixes;

private IgnoredSubdirectories(ImmutableSet<PathFragment> prefixes) {
for (PathFragment prefix : prefixes) {
Preconditions.checkArgument(!prefix.isAbsolute());
}
this.prefixes = prefixes;
}

public static IgnoredSubdirectories of(ImmutableSet<PathFragment> prefixes) {
if (prefixes.isEmpty()) {
return EMPTY;
} else {
return new IgnoredSubdirectories(prefixes);
}
}

public IgnoredSubdirectories withPrefix(PathFragment prefix) {
ImmutableSet<PathFragment> prefixed =
prefixes.stream().map(prefix::getRelative).collect(toImmutableSet());
return new IgnoredSubdirectories(prefixed);
}

public IgnoredSubdirectories union(IgnoredSubdirectories other) {
return new IgnoredSubdirectories(
ImmutableSet.<PathFragment>builder().addAll(prefixes).addAll(other.prefixes).build());
}

/** Filters out entries that cannot match anything under {@code directory}. */
public IgnoredSubdirectories filterForDirectory(PathFragment directory) {
ImmutableSet<PathFragment> filteredPrefixes =
prefixes.stream().filter(p -> p.startsWith(directory)).collect(toImmutableSet());

return new IgnoredSubdirectories(filteredPrefixes);
}

public ImmutableSet<PathFragment> prefixes() {
return prefixes;
}

public boolean isEmpty() {
return this.prefixes.isEmpty();
}

/**
* Checks whether every path in this instance can conceivably match something under {@code
* directory}.
*/
public boolean allPathsAreUnder(PathFragment directory) {
for (PathFragment prefix : prefixes) {
if (!prefix.startsWith(directory)) {
return false;
}

if (prefix.equals(directory)) {
return false;
}
}

return true;
}

/** Returns the entry that matches a given directory or {@code null} if none. */
@Nullable
public PathFragment matchingEntry(PathFragment directory) {
for (PathFragment prefix : prefixes) {
if (directory.startsWith(prefix)) {
return prefix;
}
}

return null;
}

@Override
public boolean equals(Object other) {
if (!(other instanceof IgnoredSubdirectories)) {
return false;
}

IgnoredSubdirectories that = (IgnoredSubdirectories) other;
return Objects.equals(this.prefixes, that.prefixes);
}

@Override
public int hashCode() {
return prefixes.hashCode();
}

@Override
public String toString() {
return MoreObjects.toStringHelper("IgnoredSubdirectories").add("prefixes", prefixes).toString();
}
}
Loading

0 comments on commit 8bfb921

Please sign in to comment.