diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 1ce97940706c..f125b8a8863a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -1468,7 +1468,16 @@ public final class BuildManager implements Disposable { } if (ProjectUtilCore.isExternalStorageEnabled(project)) { - cmdLine.addPathParameter("-D" + GlobalOptions.EXTERNAL_PROJECT_CONFIG + '=', ProjectUtil.getExternalConfigurationDir(project)); + Path externalProjectConfig = ProjectUtil.getExternalConfigurationDir(project); + String pathToExternalStorage; + if (canUseEel() && !EelPathUtils.isProjectLocal(project)) { + pathToExternalStorage = cmdLine.copyPathToHostIfRequired(externalProjectConfig); + cmdLine.addParameter("-D" + GlobalOptions.EXTERNAL_PROJECT_CONFIG + '=' + pathToExternalStorage); + } + else { + pathToExternalStorage = externalProjectConfig.toString(); + cmdLine.addPathParameter("-D" + GlobalOptions.EXTERNAL_PROJECT_CONFIG + '=', pathToExternalStorage); + } } cmdLine.addParameter("-D" + GlobalOptions.COMPILE_PARALLEL_OPTION + '=' + projectConfig.isParallelCompilationEnabled()); diff --git a/java/compiler/impl/src/com/intellij/compiler/server/EelBuildCommandLineBuilder.kt b/java/compiler/impl/src/com/intellij/compiler/server/EelBuildCommandLineBuilder.kt index 54e02d4e1da4..f83bf42c8f2f 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/EelBuildCommandLineBuilder.kt +++ b/java/compiler/impl/src/com/intellij/compiler/server/EelBuildCommandLineBuilder.kt @@ -16,6 +16,7 @@ import kotlinx.coroutines.future.asCompletableFuture import java.nio.charset.Charset import java.nio.file.FileSystems import java.nio.file.Path +import kotlin.io.path.isDirectory import kotlin.io.path.name class EelBuildCommandLineBuilder(val project: Project, exePath: Path) : BuildCommandLineBuilder { @@ -59,7 +60,15 @@ class EelBuildCommandLineBuilder(val project: Project, exePath: Path) : BuildCom } override fun copyPathToTargetIfRequired(path: Path): Path { - return EelPathUtils.transferContentsIfNonLocal(eel, path, workingDirectory.resolve("build-cache").resolve(path.name)) + if (path.getEelDescriptor() != LocalEelDescriptor) return path + val remotePath = workingDirectory.resolve("build-cache").resolve(path.name) + if (path.isDirectory()) { + EelPathUtils.transferContentsIfNonLocal(eel, path, remotePath) + } + else if (path.getEelDescriptor() == LocalEelDescriptor) { + EelPathUtils.transferLocalContentToRemotePathIfNeeded(path, remotePath) + } + return remotePath } override fun copyPathToHostIfRequired(path: Path): String { diff --git a/platform/eel-provider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt b/platform/eel-provider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt index 2861d1b3e00d..843708925153 100644 --- a/platform/eel-provider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt +++ b/platform/eel-provider/src/com/intellij/platform/eel/provider/utils/eelPathUtils.kt @@ -10,10 +10,7 @@ import com.intellij.platform.eel.* import com.intellij.platform.eel.fs.EelFileSystemApi import com.intellij.platform.eel.fs.EelFileSystemApi.CreateTemporaryEntryOptions import com.intellij.platform.eel.path.EelPath -import com.intellij.platform.eel.provider.LocalEelDescriptor -import com.intellij.platform.eel.provider.asEelPath -import com.intellij.platform.eel.provider.asNioPath -import com.intellij.platform.eel.provider.getEelDescriptor +import com.intellij.platform.eel.provider.* import com.intellij.util.awaitCancellationAndInvoke import com.intellij.util.concurrency.annotations.RequiresBackgroundThread import kotlinx.coroutines.* @@ -219,31 +216,34 @@ object EelPathUtils { } } + @JvmStatic + fun transferLocalContentToRemotePathIfNeeded(source: Path, remotePath: Path) { + val sourceDescriptor = source.getEelDescriptor() + + check(sourceDescriptor is LocalEelDescriptor) + + val sourceHash = calculateFileHash(source) + + val remoteHash = if (Files.exists(remotePath)) { + calculateFileHash(remotePath) + } + else { + "" + } + if (sourceHash != remoteHash) { + if (remoteHash.isNotEmpty()) { + Files.delete(remotePath) + } + transferContentsIfNonLocal(remotePath.getEelDescriptor().upgradeBlocking(), source, remotePath) + } + } + @Service private class TransferredContentHolder(private val scope: CoroutineScope) { // eel descriptor -> source path string ->> source hash -> transferred file private val cache = ConcurrentHashMap, Deferred>>() - private fun calculateFileHash(path: Path): String { - val digest = MessageDigest.getInstance("SHA-256") - val attributes = Files.readAttributes(path, BasicFileAttributes::class.java) - val fileSize = attributes.size() - val lastModified = attributes.lastModifiedTime().toMillis() - digest.update(fileSize.toString().toByteArray()) - digest.update(lastModified.toString().toByteArray()) - - FileChannel.open(path, StandardOpenOption.READ).use { channel -> - val buffer = java.nio.ByteBuffer.allocateDirect(1024 * 1024) - while (channel.read(buffer) > 0) { - buffer.flip() - digest.update(buffer) - buffer.clear() - } - } - - return digest.digest().joinToString("") { "%02x".format(it) } - } @OptIn(ExperimentalCoroutinesApi::class) suspend fun transferIfNeeded(eel: EelApi, source: Path): Path { @@ -278,6 +278,27 @@ object EelPathUtils { } } + private fun calculateFileHash(path: Path): String { + val digest = MessageDigest.getInstance("SHA-256") + val attributes = Files.readAttributes(path, BasicFileAttributes::class.java) + val fileSize = attributes.size() + val lastModified = attributes.lastModifiedTime().toMillis() + + digest.update(fileSize.toString().toByteArray()) + digest.update(lastModified.toString().toByteArray()) + + FileChannel.open(path, StandardOpenOption.READ).use { channel -> + val buffer = java.nio.ByteBuffer.allocateDirect(1024 * 1024) + while (channel.read(buffer) > 0) { + buffer.flip() + digest.update(buffer) + buffer.clear() + } + } + + return digest.digest().joinToString("") { "%02x".format(it) } + } + @JvmStatic fun getHomePath(descriptor: EelDescriptor): Path { // usually eel is already initialized to this moment