Skip to content

Commit

Permalink
Improve performance when resolving the workspace root
Browse files Browse the repository at this point in the history
  • Loading branch information
ivyspirit authored and ilisc2 committed Jun 26, 2024
1 parent db36eed commit a76cae0
Showing 1 changed file with 78 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@
package com.google.idea.blaze.base.sync.workspace;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.idea.blaze.base.bazel.BuildSystemProvider;
import com.google.idea.blaze.base.io.FileOperationProvider;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.primitives.Label;
import com.google.idea.blaze.base.model.primitives.TargetName;
Expand All @@ -27,48 +25,64 @@
import com.google.idea.blaze.base.settings.Blaze;
import com.google.idea.blaze.base.settings.BuildSystemName;
import com.google.idea.blaze.base.sync.SyncCache;
import com.google.idea.blaze.base.sync.data.BlazeProjectDataManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;

import java.io.File;
import java.util.Arrays;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.annotation.Nullable;

/** External-workspace-aware resolution of workspace paths. */
/**
* External-workspace-aware resolution of workspace paths.
*/
public class WorkspaceHelper {

private static BlazeProjectData blazeProjectData;
private static final Logger logger = Logger.getInstance(WorkspaceHelper.class);

private static class Workspace {

private final WorkspaceRoot root;
@Nullable private final String externalWorkspaceName;
@Nullable
private final String externalWorkspaceName;

private Workspace(WorkspaceRoot root, @Nullable String externalWorkspaceName) {
this.root = root;
this.externalWorkspaceName = externalWorkspaceName;
}
}

private static synchronized BlazeProjectData getBlazeProjectData(Project project) {
if (blazeProjectData == null) {
blazeProjectData = BlazeProjectDataManager.getInstance(project).getBlazeProjectData();
}
return blazeProjectData;
}

@Nullable
public static WorkspaceRoot resolveExternalWorkspace(Project project, String workspaceName) {
Map<String, WorkspaceRoot> externalWorkspaces = getExternalWorkspaceRoots(project);
return externalWorkspaces != null ? externalWorkspaces.get(workspaceName) : null;
return getExternalWorkspaceRootsFile(workspaceName, project);
}

/** Resolves the parent blaze package corresponding to this label. */
/**
* Resolves the parent blaze package corresponding to this label.
*/
@Nullable
public static File resolveBlazePackage(Project project, Label label) {
logger.debug("resolveBlazePackage: " + label + " in project " + project.getName());
if (!label.isExternal()) {
WorkspacePathResolver pathResolver =
WorkspacePathResolverProvider.getInstance(project).getPathResolver();
return pathResolver != null ? pathResolver.resolveToFile(label.blazePackage()) : null;
}
Map<String, WorkspaceRoot> externalWorkspaces = getExternalWorkspaceRoots(project);
if (externalWorkspaces == null) {
return null;
}
WorkspaceRoot root = externalWorkspaces.get(label.externalWorkspaceName());

WorkspaceRoot root = getExternalWorkspaceRootsFile(label.externalWorkspaceName(), project);
return root != null ? root.fileForPath(label.blazePackage()) : null;
}

Expand All @@ -78,9 +92,12 @@ public static WorkspacePath resolveWorkspacePath(Project project, File absoluteF
return workspace != null ? workspace.root.workspacePathForSafe(absoluteFile) : null;
}

/** Converts a file to the corresponding BUILD label for this project, if valid. */
/**
* Converts a file to the corresponding BUILD label for this project, if valid.
*/
@Nullable
public static Label getBuildLabel(Project project, File absoluteFile) {
logger.debug("getBuildLabel for file " + absoluteFile.getAbsolutePath());
Workspace workspace = resolveWorkspace(project, absoluteFile);
if (workspace == null) {
return null;
Expand All @@ -103,21 +120,34 @@ private static Workspace resolveWorkspace(Project project, File absoluteFile) {
// try project workspace first
WorkspaceRoot root = pathResolver.findWorkspaceRoot(absoluteFile);
if (root != null) {
logger.debug("resolveWorkspace: " + root.directory().getAbsolutePath());
return new Workspace(root, null);
}

Map<String, WorkspaceRoot> externalWorkspaces = getExternalWorkspaceRoots(project);
if (externalWorkspaces == null) {
BlazeProjectData blazeProjectData = getBlazeProjectData(project);
Path bzelRootPath = Paths.get(blazeProjectData.getBlazeInfo().getOutputBase().getAbsolutePath(),
"external").normalize();
Path path = Paths.get(absoluteFile.getAbsolutePath()).normalize();

// Check if the file path starts with the root directory path
if (!path.startsWith(bzelRootPath)) {
return null;
}
for (Entry<String, WorkspaceRoot> entry : externalWorkspaces.entrySet()) {
root = entry.getValue();
WorkspacePath workspacePath = root.workspacePathForSafe(absoluteFile);
if (workspacePath != null) {
return new Workspace(root, entry.getKey());

Path relativePath = bzelRootPath.relativize(path);
if (relativePath.getNameCount() > 0) {
String firstFolder = relativePath.getName(0).toString();
try {
Path workspaceRootPath = Files.createDirectories(bzelRootPath.resolve(firstFolder));
logger.debug("resolveWorkspace: " + workspaceRootPath + " firstFolder: " + firstFolder);
return new Workspace(new WorkspaceRoot(workspaceRootPath.toFile()), firstFolder);
} catch (IOException e) {
logger.error("Error creating directories", e);
return null;
}
} else {
return null;
}
return null;
}

private static Label deriveLabel(
Expand Down Expand Up @@ -155,31 +185,36 @@ private static WorkspacePath getPackagePath(
return null;
}


@VisibleForTesting
public static File getExternalSourceRoot(BlazeProjectData projectData) {
return new File(projectData.getBlazeInfo().getOutputBase(), "external");
}

@Nullable
private static synchronized Map<String, WorkspaceRoot> getExternalWorkspaceRoots(
private static synchronized WorkspaceRoot getExternalWorkspaceRootsFile(String workspaceName,
Project project) {
if (Blaze.getBuildSystemName(project) == BuildSystemName.Blaze) {
return ImmutableMap.of();
return null;
}
return SyncCache.getInstance(project)
.get(WorkspaceHelper.class, WorkspaceHelper::enumerateExternalWorkspaces);
}
logger.debug("getExternalWorkspaceRootsFile for " + workspaceName);
File baseDir = SyncCache.getInstance(project)
.get(workspaceName, WorkspaceHelper::getWorkspaceRootDir);

@SuppressWarnings("unused")
private static Map<String, WorkspaceRoot> enumerateExternalWorkspaces(
Project project, BlazeProjectData blazeProjectData) {
FileOperationProvider provider = FileOperationProvider.getInstance();
File[] children = provider.listFiles(getExternalSourceRoot(blazeProjectData));
if (children == null) {
return ImmutableMap.of();
if (baseDir == null) {
return null;
}
return Arrays.stream(children)
.filter(provider::isDirectory)
.collect(Collectors.toMap(File::getName, WorkspaceRoot::new));
File rootFile = new File(baseDir, "external/" + workspaceName);
return rootFile.exists() ? new WorkspaceRoot(rootFile) : null;
}

@VisibleForTesting
public static File getExternalSourceRoot(BlazeProjectData projectData) {
return new File(projectData.getBlazeInfo().getOutputBase(), "external");
private static File getWorkspaceRootDir(Project project, BlazeProjectData blazeProjectData) {
if (blazeProjectData == null) {
logger.debug("the blazeProjectData is null " + project.getName());
return null;
}
File root = blazeProjectData.getBlazeInfo().getOutputBase();
return root;
}

}

0 comments on commit a76cae0

Please sign in to comment.