diff --git a/base/src/com/google/idea/blaze/base/sync/workspace/ExecutionRootPathResolver.java b/base/src/com/google/idea/blaze/base/sync/workspace/ExecutionRootPathResolver.java index c35fd0a2e9e..5861bc65df9 100644 --- a/base/src/com/google/idea/blaze/base/sync/workspace/ExecutionRootPathResolver.java +++ b/base/src/com/google/idea/blaze/base/sync/workspace/ExecutionRootPathResolver.java @@ -31,8 +31,9 @@ * Converts execution-root-relative paths to absolute files with a minimum of file system calls * (typically none). * - *

Files which exist both underneath the execution root and within the workspace will be resolved - * to workspace paths. + *

Files which exist both underneath the execution root and within a workspace will be resolved + * to paths within their workspace. This prevents those paths from being broken when a different + * target is built. */ public class ExecutionRootPathResolver { @@ -76,13 +77,13 @@ public File resolveExecutionRootPath(ExecutionRootPath path) { if (isInWorkspace(path)) { return workspacePathResolver.resolveToFile(path.getAbsoluteOrRelativeFile().getPath()); } - return path.getFileRootedAt(executionRoot); + return convertExternalToStable(path.getFileRootedAt(executionRoot)); } /** * This method should be used for directories. Returns all workspace files corresponding to the - * given execution-root-relative path. If the file does not exist inside the workspace (e.g. for - * blaze output files or external workspace files), returns the path rooted in the execution root. + * given execution-root-relative path. If the file does not exist inside a workspace (e.g. for + * blaze output files), returns the path rooted in the execution root. */ public ImmutableList resolveToIncludeDirectories(ExecutionRootPath path) { if (path.isAbsolute()) { @@ -97,7 +98,7 @@ public ImmutableList resolveToIncludeDirectories(ExecutionRootPath path) { return ImmutableList.of(); } } - return ImmutableList.of(path.getFileRootedAt(executionRoot)); + return ImmutableList.of(convertExternalToStable(path.getFileRootedAt(executionRoot))); } public File getExecutionRoot() { @@ -118,4 +119,19 @@ private static String getFirstPathComponent(String path) { private static boolean isExternalWorkspacePath(String firstPathComponent) { return firstPathComponent.equals("external"); } + + /** + * Converts external paths in unstable locations under execroot that may change on the next build + * to stable ones under their external workspace. + * That is, converts paths under /execroot/__main__/external/ to paths under + * /external/. + * Safe to call on all paths; non-external paths are left as they are. + * See https://github.com/bazelbuild/intellij/issues/2766 for more details. + */ + private static File convertExternalToStable(File f) { + String unstableExecrootSubpath = + f.separator + "execroot" + f.separator + "__main__" + f.separator + "external" + f.separator; + String stableExternalSubpath = f.separator + "external" + f.separator; + return new File(f.getAbsolutePath().replace(unstableExecrootSubpath, stableExternalSubpath)); + } }