From 47abb89c2a4f09cdd3cdf9b063424403624e1d20 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 26 Sep 2025 20:48:37 +0200 Subject: [PATCH] when IC logic decides to rebuild the whole target, ensure all resources are fully copied GitOrigin-RevId: 4cf638c06264959339b1728b378e3b0a6f7d15c2 --- .../bazel/jvmIncBuilder/BazelIncBuilder.java | 26 ++++++++++++++----- .../impl/ConfigurationState.java | 7 ++++- .../jvmIncBuilder/impl/ResourceGroupImpl.java | 20 +++++++++----- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/BazelIncBuilder.java b/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/BazelIncBuilder.java index 8ba1eee4b34f..b6b9aaf5c427 100644 --- a/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/BazelIncBuilder.java +++ b/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/BazelIncBuilder.java @@ -58,7 +58,6 @@ public class BazelIncBuilder { ConfigurationState presentState = new ConfigurationState(context.getPathMapper(), context.getSources(), context.getResources(), context.getBinaryDependencies(), context.getFlags()); srcSnapshotDelta = new SnapshotDeltaImpl(pastState.getSources(), presentState.getSources()); - resourcesDelta = new ResourcesSnapshotDelta(pastState.getResources(), presentState.getResources()); if (shouldRecompileAll(srcSnapshotDelta) || pastState.getFlagsDigest() != presentState.getFlagsDigest() || pastState.getClasspathStructureDigest() != presentState.getClasspathStructureDigest()) { int changedPercent = srcSnapshotDelta.getChangedPercent(); @@ -148,6 +147,10 @@ public class BazelIncBuilder { } } } + + if (!srcSnapshotDelta.isRecompileAll()) { + resourcesDelta = new ResourcesSnapshotDelta(pastState.getResources(), presentState.getResources()); + } } List roundCompilers = collect(map(RunnerRegistry.getRoundCompilers(), f -> f.create(context, storageManager)), new ArrayList<>()); @@ -170,10 +173,10 @@ public class BazelIncBuilder { OutputSinkImpl outSink = new OutputSinkImpl(storageManager); if (isInitialRound) { - + // processing resources ZipOutputBuilder out = storageManager.getOutputBuilder(); - if (resourcesDelta == null) { + if (resourcesDelta == null || srcSnapshotDelta.isRecompileAll()) { // copy everything for (ResourceGroup group : context.getResources()) { copyResources(group, context.getPathMapper(), out); @@ -194,6 +197,15 @@ public class BazelIncBuilder { logDeletedPaths(context, cleaned); } } + else { + if (srcSnapshotDelta.isRecompileAll()) { + // After several rounds, the IC logic can decide to recompile everything + ZipOutputBuilder out = storageManager.getOutputBuilder(); + for (ResourceGroup group : context.getResources()) { + copyResources(group, context.getPathMapper(), out); + } + } + } for (CompilerRunner runner : roundCompilers) { @@ -344,17 +356,17 @@ public class BazelIncBuilder { String stripPrefix = group.getStripPrefix(); if (!stripPrefix.isEmpty()) { - if (destPath.regionMatches(!SystemInfo.isFileSystemCaseSensitive, 0, stripPrefix, 0, stripPrefix.length()) && (destPath.length() == stripPrefix.length() || destPath.charAt(stripPrefix.length()) == '/') ) { - destPath = destPath.substring(stripPrefix.length()); + if (destPath.length() > stripPrefix.length() && destPath.regionMatches(!SystemInfo.isFileSystemCaseSensitive, 0, stripPrefix, 0, stripPrefix.length()) && destPath.charAt(stripPrefix.length()) == '/' ) { + destPath = destPath.substring(stripPrefix.length() + 1); } else { - return null; + return null; // todo: emit error } } String addPrefix = group.getAddPrefix(); if (!addPrefix.isEmpty()) { - destPath = destPath.startsWith("/")? addPrefix + destPath : addPrefix + "/" + destPath; + destPath = addPrefix + "/" + destPath; } return destPath; diff --git a/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ConfigurationState.java b/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ConfigurationState.java index ce87dd742bb6..853c0d0d3f81 100644 --- a/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ConfigurationState.java +++ b/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ConfigurationState.java @@ -37,13 +37,18 @@ public class ConfigurationState { CLFlags.NON_INCREMENTAL, CLFlags.JAVA_COUNT, CLFlags.TARGET_LABEL, + CLFlags.CP, // processed separately CLFlags.OUT, CLFlags.ABI_OUT, + CLFlags.WARN, CLFlags.X_WASM_ATTACH_JS_EXCEPTION, CLFlags.ADD_EXPORT, - CLFlags.ADD_READS + CLFlags.ADD_READS, + + CLFlags.SRCS, + CLFlags.RESOURCES ); private final NodeSourcePathMapper myPathMapper; diff --git a/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ResourceGroupImpl.java b/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ResourceGroupImpl.java index 4d1968ac7864..964729e57e1f 100644 --- a/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ResourceGroupImpl.java +++ b/build/jvm-rules/jvm-inc-builder/src/com/intellij/tools/build/bazel/jvmIncBuilder/impl/ResourceGroupImpl.java @@ -1,5 +1,7 @@ package com.intellij.tools.build.bazel.jvmIncBuilder.impl; +import com.dynatrace.hash4j.hashing.HashStream64; +import com.dynatrace.hash4j.hashing.Hashing; import com.intellij.tools.build.bazel.jvmIncBuilder.ResourceGroup; import org.jetbrains.jps.dependency.DataReader; import org.jetbrains.jps.dependency.GraphDataInput; @@ -8,7 +10,6 @@ import org.jetbrains.jps.dependency.NodeSource; import java.io.File; import java.io.IOException; -import java.util.List; import java.util.Map; public class ResourceGroupImpl extends SourceSnapshotImpl implements ResourceGroup { @@ -20,16 +21,23 @@ public class ResourceGroupImpl extends SourceSnapshotImpl implements ResourceGro myStripPrefix = normalizePrefix(stripPrefix); myAddPrefix = normalizePrefix(addPrefix); - String prefixDigest = Long.toHexString(Utils.digest(List.of(myStripPrefix, myAddPrefix))); + HashStream64 hash = Hashing.xxh3_64().hashStream(); for (Map.Entry entry : digestSources.entrySet()) { - entry.setValue(prefixDigest + ":" + entry.getValue()); + entry.setValue(Long.toHexString(hash.reset().putString(myStripPrefix).putString(myAddPrefix).putString(entry.getValue()).getAsLong())); } } private static String normalizePrefix(String prefix) { - prefix = prefix.replace(File.separatorChar, '/'); - while (prefix.endsWith("/")) { - prefix = prefix.substring(0, prefix.length() - 1); + if (!prefix.isEmpty()) { + prefix = prefix.replace(File.separatorChar, '/'); + + int start = 0; + while (start < prefix.length() && prefix.charAt(start) == '/') start += 1; + + int end = prefix.length() - 1; + while (end > start && prefix.charAt(end) == '/') end -= 1; + + prefix = start <= end? prefix.substring(start, end + 1) : ""; } return prefix; }