From 623c5570a35c3e1f940a4eba13460390db8ae9f9 Mon Sep 17 00:00:00 2001 From: "Dmitriy.Panov" Date: Fri, 30 Jul 2021 16:38:38 +0300 Subject: [PATCH] KTIJ-17296 JPS Portable Caches built from sources with LF line breaks cannot be used to compile sources with CRLF line breaks: fail-fast GitOrigin-RevId: 69420b35871dc07ffbf6121fdb1cc564d7471550 --- .../build/impl/compilation/Git.groovy | 34 ++++++++++++++++--- .../PortableCompilationCache.groovy | 11 +++++- .../PortableCompilationCacheDownloader.groovy | 6 ++-- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/Git.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/Git.groovy index 31ee39221a6e..8136458534e1 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/Git.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/Git.groovy @@ -2,6 +2,7 @@ package org.jetbrains.intellij.build.impl.compilation import groovy.transform.CompileStatic +import groovy.transform.Immutable import java.nio.charset.StandardCharsets import java.util.stream.Collectors @@ -24,15 +25,40 @@ class Git { return execute('git status --short --untracked-files=no --ignored=no') } - private List execute(String command) { + String lineBreaksConfig() { + def lines = maybeExecute("git config core.autocrlf").output.findAll { !it.isBlank() } + if (lines.isEmpty()) { + return "" + } + if (lines.size() != 1) { + throw new IllegalStateException("Single line output is expected but got '$lines'") + } + return lines[0] + } + + private ExecutionResult maybeExecute(String command) { def process = command.execute((List)null, dir) - def output = new BufferedReader(new InputStreamReader(process.inputStream, StandardCharsets.UTF_8)).withCloseable { + List output = new BufferedReader(new InputStreamReader(process.inputStream, StandardCharsets.UTF_8)).withCloseable { it.lines().map { it.trim() }.collect(Collectors.toList()) } process.waitForOrKill(PROCESS_TIMEOUT) if (process.exitValue() != 0) { - throw new IllegalStateException("git process failed:\n$process.errorStream.text\n$output") + output = [process.errorStream.text] + output } - return output + return new ExecutionResult(exitCode: process.exitValue(), output: output) + } + + private List execute(String command) { + ExecutionResult result = maybeExecute(command) + if (result.exitCode != 0) { + throw new IllegalStateException("git process failed with $result.exitCode:\n${result.output.join('\n')}") + } + return result.output + } + + @Immutable + private class ExecutionResult { + int exitCode + List output } } diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCache.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCache.groovy index e17d203f045b..ed886454d286 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCache.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCache.groovy @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.intellij.build.impl.compilation +import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import groovy.transform.CompileStatic @@ -76,6 +77,7 @@ final class PortableCompilationCache { } private final CompilationContext context + private final Git git /** * IntelliJ repository git remote url */ @@ -122,7 +124,7 @@ final class PortableCompilationCache { @Lazy private PortableCompilationCacheDownloader downloader = { def availableForHeadCommit = bool(AVAILABLE_FOR_HEAD_PROPERTY, false) - new PortableCompilationCacheDownloader(context, remoteCache.url, remoteGitUrl, + new PortableCompilationCacheDownloader(context, git, remoteCache.url, remoteGitUrl, availableForHeadCommit, jpsCaches.skipDownload) }() @@ -139,6 +141,7 @@ final class PortableCompilationCache { PortableCompilationCache(CompilationContext context) { this.context = context + this.git = new Git(context.paths.projectHome.trim()) } /** @@ -225,6 +228,12 @@ final class PortableCompilationCache { } private def compileProject() { + // fail-fast in case of KTIJ-17296 + if (SystemInfo.isWindows && git.lineBreaksConfig() != "input") { + context.messages.error("${getClass().simpleName} cannot be used with CRLF line breaks, " + + "please execute `git config --global core.autocrlf input` before checkout " + + "and upvote https://youtrack.jetbrains.com/issue/KTIJ-17296") + } // ensure that JBR and Kotlin compiler are downloaded before compilation CompilationContextImpl.setupCompilationDependencies(context.gradle, context.options) def jps = new JpsCompilationRunner(context) diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCacheDownloader.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCacheDownloader.groovy index ffb8d99b0f07..0b764416d940 100644 --- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCacheDownloader.groovy +++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/compilation/PortableCompilationCacheDownloader.groovy @@ -34,7 +34,7 @@ class PortableCompilationCacheDownloader implements AutoCloseable { private static final int COMMITS_COUNT = 1_000 private final GetClient getClient = new GetClient(context.messages) - private final Git git = new Git(context.paths.projectHome.trim()) + private final Git git private final CompilationContext context private final String remoteCacheUrl @@ -68,9 +68,11 @@ class PortableCompilationCacheDownloader implements AutoCloseable { new CommitsHistory(json).commitsForRemote(gitUrl) }() - PortableCompilationCacheDownloader(CompilationContext context, String remoteCacheUrl, String gitUrl, + PortableCompilationCacheDownloader(CompilationContext context, Git git, + String remoteCacheUrl, String gitUrl, boolean availableForHeadCommit, boolean downloadCompilationOutputsOnly) { this.context = context + this.git = git this.remoteCacheUrl = StringUtil.trimEnd(remoteCacheUrl, '/') this.gitUrl = gitUrl this.availableForHeadCommitForced = availableForHeadCommit