Avoid removing target/classes dir during IC in Maven
#KT-21581 fixed
This commit is contained in:
+6
-5
@@ -9,7 +9,8 @@ public class IncrementalCompilationIT extends MavenITBase {
|
||||
MavenProject project = new MavenProject("kotlinSimple");
|
||||
project.exec("package")
|
||||
.succeeded()
|
||||
.compiledKotlin("src/A.kt", "src/useA.kt", "src/Dummy.kt");
|
||||
.fileExists("target/classes/test.properties")
|
||||
.compiledKotlin("src/main/kotlin/A.kt", "src/main/kotlin/useA.kt", "src/main/kotlin/Dummy.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -27,7 +28,7 @@ public class IncrementalCompilationIT extends MavenITBase {
|
||||
MavenProject project = new MavenProject("kotlinSimple");
|
||||
project.exec("package");
|
||||
|
||||
File aKt = project.file("src/A.kt");
|
||||
File aKt = project.file("src/main/kotlin/A.kt");
|
||||
String original = "class A";
|
||||
String replacement = "private class A";
|
||||
MavenTestUtils.replaceFirstInFile(aKt, original, replacement);
|
||||
@@ -39,7 +40,7 @@ public class IncrementalCompilationIT extends MavenITBase {
|
||||
MavenTestUtils.replaceFirstInFile(aKt, replacement, original);
|
||||
project.exec("package")
|
||||
.succeeded()
|
||||
.compiledKotlin("src/A.kt", "src/useA.kt");
|
||||
.compiledKotlin("src/main/kotlin/A.kt", "src/main/kotlin/useA.kt");
|
||||
|
||||
}
|
||||
|
||||
@@ -48,12 +49,12 @@ public class IncrementalCompilationIT extends MavenITBase {
|
||||
MavenProject project = new MavenProject("kotlinSimple");
|
||||
project.exec("package");
|
||||
|
||||
File aKt = project.file("src/A.kt");
|
||||
File aKt = project.file("src/main/kotlin/A.kt");
|
||||
MavenTestUtils.replaceFirstInFile(aKt, "fun foo", "internal fun foo");
|
||||
|
||||
project.exec("package")
|
||||
.succeeded()
|
||||
.compiledKotlin("src/A.kt", "src/useA.kt");
|
||||
.compiledKotlin("src/main/kotlin/A.kt", "src/main/kotlin/useA.kt");
|
||||
|
||||
// todo rebuild and compare output
|
||||
}
|
||||
|
||||
+10
@@ -110,4 +110,14 @@ class MavenExecutionResult {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
MavenExecutionResult fileExists(@NotNull final String path) throws Exception {
|
||||
return check(new Action<MavenExecutionResult>() {
|
||||
@Override
|
||||
public void run(MavenExecutionResult execResult) {
|
||||
File file = new File(workingDir, path);
|
||||
Assert.assertTrue(file + " does not exist", file.exists());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
||||
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -40,7 +42,6 @@
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
<sourceDirectory>${project.basedir}/src</sourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
example.property=101
|
||||
+32
-6
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.maven;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiJavaModule;
|
||||
import kotlin.collections.MapsKt;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugins.annotations.LifecyclePhase;
|
||||
@@ -32,15 +34,15 @@ import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments;
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector;
|
||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler;
|
||||
import org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunnerKt;
|
||||
import org.jetbrains.kotlin.maven.incremental.FileCopier;
|
||||
import org.jetbrains.kotlin.maven.incremental.MavenICReporter;
|
||||
import org.jetbrains.kotlin.maven.kapt.AnnotationProcessingManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.join;
|
||||
import static org.jetbrains.kotlin.maven.Util.filterClassPath;
|
||||
@@ -241,19 +243,43 @@ public class K2JVMCompileMojo extends KotlinCompileMojoBase<K2JVMCompilerArgumen
|
||||
File cachesDir = getCachesDir();
|
||||
//noinspection ResultOfMethodCallIgnored
|
||||
cachesDir.mkdirs();
|
||||
|
||||
String destination = arguments.getDestination();
|
||||
assert destination != null : "output is not specified!";
|
||||
File classesDir = new File(destination);
|
||||
File kotlinClassesDir = new File(cachesDir, "classes");
|
||||
File snapshotsFile = new File(cachesDir, "snapshots.bin");
|
||||
String classpath = arguments.getClasspath();
|
||||
MavenICReporter icReporter = MavenICReporter.get(getLog());
|
||||
|
||||
try {
|
||||
arguments.setDestination(kotlinClassesDir.getAbsolutePath());
|
||||
if (classpath != null) {
|
||||
List<String> filteredClasspath = new ArrayList<>();
|
||||
for (String path : classpath.split(File.pathSeparator)) {
|
||||
if (!classesDir.equals(new File(path))) {
|
||||
filteredClasspath.add(path);
|
||||
}
|
||||
}
|
||||
arguments.setClasspath(StringUtil.join(filteredClasspath, File.pathSeparator));
|
||||
}
|
||||
|
||||
IncrementalJvmCompilerRunnerKt.makeIncrementally(cachesDir, sourceRoots, arguments, messageCollector, icReporter);
|
||||
|
||||
int compiledKtFilesCount = icReporter.getCompiledKotlinFiles().size();
|
||||
getLog().info("Compiled " + icReporter.getCompiledKotlinFiles().size() + " Kotlin files using incremental compiler");
|
||||
|
||||
if (!messageCollector.hasErrors()) {
|
||||
(new FileCopier(getLog())).syncDirs(kotlinClassesDir, classesDir, snapshotsFile);
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
return ExitCode.INTERNAL_ERROR;
|
||||
}
|
||||
finally {
|
||||
arguments.setDestination(destination);
|
||||
arguments.setClasspath(classpath);
|
||||
}
|
||||
|
||||
if (messageCollector.hasErrors()) {
|
||||
return ExitCode.COMPILATION_ERROR;
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.maven.incremental;
|
||||
|
||||
import org.apache.maven.plugin.logging.Log;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class FileCopier {
|
||||
private final static int VERSION = 0;
|
||||
|
||||
private final Log log;
|
||||
|
||||
public FileCopier(Log log) {
|
||||
this.log = log;
|
||||
}
|
||||
|
||||
public void syncDirs(@NotNull File from, @NotNull File to, @NotNull File snapshotsStorageFile) {
|
||||
try {
|
||||
syncDirsImpl(from, to, snapshotsStorageFile);
|
||||
} catch (IOException e) {
|
||||
log.warn("Could not copy Kotlin files from " + from + " to " + to, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void syncDirsImpl(
|
||||
@NotNull File sourceBaseFile,
|
||||
@NotNull File targetBaseFile,
|
||||
@NotNull File snapshotsStorageFile
|
||||
) throws IOException {
|
||||
// snapshots are stored as relative paths (to source or target base)
|
||||
Map<String, FileSnapshot> previousSnapshots = readFileSnapshots(snapshotsStorageFile);
|
||||
|
||||
Path sourceBase = Paths.get(sourceBaseFile.getPath()).normalize();
|
||||
Path targetBase = Paths.get(targetBaseFile.getPath()).normalize();
|
||||
Map<String, FileSnapshot> newSnapshots = new HashMap<>();
|
||||
for (Path path : Files.walk(sourceBase).collect(Collectors.toList())) {
|
||||
if (!Files.isRegularFile(path)) continue;
|
||||
|
||||
String relativePath = sourceBase.relativize(path).toString();
|
||||
|
||||
File file = path.toFile();
|
||||
FileSnapshot snapshot = new FileSnapshot(file.lastModified(), file.length());
|
||||
|
||||
// remove current files from previousSnapshots map so only removed files would remain in previousSnapshots
|
||||
FileSnapshot prevSnapshot = previousSnapshots.remove(relativePath);
|
||||
if (!snapshot.equals(prevSnapshot)) {
|
||||
Path target = targetBase.resolve(relativePath);
|
||||
if (!Files.isDirectory(target)) {
|
||||
Files.deleteIfExists(target);
|
||||
Files.createDirectories(target.getParent());
|
||||
Files.copy(path, target);
|
||||
}
|
||||
|
||||
log.debug("Copied " + path + " to " + target);
|
||||
}
|
||||
newSnapshots.put(relativePath, snapshot);
|
||||
}
|
||||
|
||||
for (String removedPath : previousSnapshots.keySet()) {
|
||||
Path target = targetBase.resolve(removedPath);
|
||||
log.debug("Deleted " + target + " as it is no longer present in " + sourceBase);
|
||||
if (Files.isRegularFile(target)) {
|
||||
Files.delete(target);
|
||||
}
|
||||
}
|
||||
|
||||
writeFileSnapshots(newSnapshots, snapshotsStorageFile);
|
||||
}
|
||||
|
||||
private void writeFileSnapshots(@NotNull Map<String, FileSnapshot> snapshots, @NotNull File outputFile) {
|
||||
try (ObjectOutputStream output = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(outputFile)))) {
|
||||
output.writeInt(VERSION);
|
||||
output.writeInt(snapshots.size());
|
||||
for (Map.Entry<String, FileSnapshot> entry : snapshots.entrySet()) {
|
||||
String path = entry.getKey();
|
||||
output.writeUTF(path);
|
||||
FileSnapshot snapshot = entry.getValue();
|
||||
output.writeLong(snapshot.lastModified);
|
||||
output.writeLong(snapshot.size);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("Couldn't write copied files list to " + outputFile, e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<String, FileSnapshot> readFileSnapshots(@NotNull File inputFile) {
|
||||
Map<String, FileSnapshot> snapshots = new HashMap<>();
|
||||
if (!inputFile.isFile()) return snapshots;
|
||||
|
||||
try (ObjectInputStream input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(inputFile)))) {
|
||||
int version = input.readInt();
|
||||
if (version != VERSION) return snapshots;
|
||||
|
||||
int size = input.readInt();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String path = input.readUTF();
|
||||
long lastModified = input.readLong();
|
||||
long fileSize = input.readLong();
|
||||
snapshots.put(path, new FileSnapshot(lastModified, fileSize));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.debug("Couldn't read copied files list from " + inputFile, e);
|
||||
}
|
||||
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
private static class FileSnapshot {
|
||||
final long lastModified;
|
||||
final long size;
|
||||
|
||||
private FileSnapshot(long lastModified, long size) {
|
||||
this.lastModified = lastModified;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
FileSnapshot that = (FileSnapshot) o;
|
||||
|
||||
if (lastModified != that.lastModified) return false;
|
||||
return size == that.size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = (int) (lastModified ^ (lastModified >>> 32));
|
||||
result = 31 * result + (int) (size ^ (size >>> 32));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user