track classpath structure and content digests of all external deps

GitOrigin-RevId: 1b412b4d2d5ec7742bc0508e97c5b0e08f3f1359
This commit is contained in:
Eugene Zhuravlev
2025-05-03 22:02:16 +00:00
committed by intellij-monorepo-bot
parent 4fa28423b3
commit a231b49f8f
3 changed files with 24 additions and 13 deletions
@@ -54,6 +54,7 @@ public class BazelIncBuilder {
public ExitCode build(BuildContext context) {
// todo: support cancellation checks
// todo: additional diagnostics, if necessary
GraphUpdater graphUpdater = new GraphUpdater(context.getTargetName());
DiagnosticSink diagnostic = context;
@@ -69,8 +70,7 @@ public class BazelIncBuilder {
else {
ConfigurationState pastState = loadConfigurationState(context);
snapshotDelta = new SourceSnapshotDeltaImpl(pastState.getSourceSnapshot(), context.getSources());
if (!snapshotDelta.isRecompileAll() && !pastState.getDepsDigest().equals(presentState.getDepsDigest())) {
// todo: diagnostic?
if (!snapshotDelta.isRecompileAll() && !pastState.getClasspathStructureDigest().equals(presentState.getClasspathStructureDigest())) {
snapshotDelta.markRecompileAll();
}
}
@@ -260,7 +260,7 @@ public class BazelIncBuilder {
private static void saveConfigurationState(BuildContext context, ConfigurationState state) {
Path snapshotPath = getSourceSnapshotStoreFile(context);
try (var stream = new DataOutputStream(new DeflaterOutputStream(Files.newOutputStream(snapshotPath), new Deflater(Deflater.BEST_SPEED)))) {
stream.writeUTF(state.getDepsDigest());
stream.writeUTF(state.getClasspathStructureDigest());
state.getSourceSnapshot().write(new GraphDataOutputImpl(stream));
}
catch (Throwable e) {
@@ -288,6 +288,10 @@ public class BazelIncBuilder {
return context.getDataDir().resolve(DEP_GRAPH_FILE_NAME);
}
private static boolean isAbiJar(Path path) {
return path.toString().endsWith("-abi.jar"); // todo: better criterion?
}
private static void safeClose(Closeable cl, DiagnosticSink diagnostic) {
if (cl == null) {
return;
@@ -304,11 +308,12 @@ public class BazelIncBuilder {
ConfigurationState EMPTY = create(SourceSnapshot.EMPTY, "");
SourceSnapshot getSourceSnapshot();
String getDepsDigest();
// tracks names and order of classpath entries as well as content digests of all third-party dependencies
String getClasspathStructureDigest();
default ConfigurationState derive(SourceSnapshot snapshot) {
return create(snapshot, getDepsDigest());
return create(snapshot, getClasspathStructureDigest());
}
static ConfigurationState create(SourceSnapshot snapshot, String depsDigest) {
@@ -319,7 +324,7 @@ public class BazelIncBuilder {
}
@Override
public String getDepsDigest() {
public String getClasspathStructureDigest() {
return depsDigest;
}
};
@@ -327,7 +332,12 @@ public class BazelIncBuilder {
static ConfigurationState create(BuildContext context) {
PathSnapshot deps = context.getBinaryDependencies();
return create(context.getSources(), Utils.digest(map(deps.getElements(), deps::getDigest)));
// digest name, count and order of classpath entries as well as content digests of all non-abi deps
Function<@NotNull Path, Iterable<String>> digestMapper =
path -> isAbiJar(path)? List.of(path.toString()) : List.of(path.toString(), deps.getDigest(path));
return create(context.getSources(), Utils.digest(flat(map(deps.getElements(), digestMapper))));
}
}
}
@@ -5,13 +5,14 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.bazel.PathSnapshot;
import java.nio.file.Path;
import java.util.Collections;
import java.util.Map;
public class PathSnapshotImpl implements PathSnapshot {
private final Map<Path, String> myPaths;
public PathSnapshotImpl(Map<Path, String> digestPaths) {
myPaths = Map.copyOf(digestPaths);
myPaths = Collections.unmodifiableMap(digestPaths); // keep all properties of the passed map, i.e. iteration order
}
@Override
@@ -26,13 +26,13 @@ public class Utils {
return Long.toHexString(stream.getAsLong());
}
public static String digest(File file) {
return digest(file.toPath(), null);
public static String timestampDigest(File file) {
return timestampDigest(file.toPath(), null);
}
public static String digest(Path path, @Nullable BasicFileAttributes attrs) {
public static String timestampDigest(Path path, @Nullable BasicFileAttributes attrs) {
try {
return Long.toHexString((attrs != null? attrs.lastModifiedTime().toMillis() : Files.getLastModifiedTime(path).toMillis())); // todo
return Long.toHexString((attrs != null? attrs.lastModifiedTime().toMillis() : Files.getLastModifiedTime(path).toMillis()));
}
catch (IOException ignored) {
return "";