mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
artifact builder for compile server: honor order of element when several files copied to the same output file
This commit is contained in:
+1
-1
@@ -31,7 +31,7 @@ import java.util.Set;
|
||||
*/
|
||||
public class ArtifactCompilerPersistentData {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.generic.ArtifactCompilerPersistentData");
|
||||
private static final int VERSION = 0;
|
||||
private static final int VERSION = 1;
|
||||
private File myFile;
|
||||
private Map<String, Integer> myArtifact2Id = new HashMap<String, Integer>();
|
||||
private TIntHashSet myUsedIds = new TIntHashSet();
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
package org.jetbrains.jps.incremental.artifacts;
|
||||
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.jps.incremental.storage.AbstractStateStorage;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stores source paths for each output path. If a source file or an output file is located in a jar file the full path is stored
|
||||
* using '!/' to separate path to the jar file from path to file inside the jar.
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactOutputToSourceMapping extends AbstractStateStorage<String, List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex>> {
|
||||
public static DataExternalizer<List<SourcePathAndRootIndex>> EXTERNALIZER = new DataExternalizer<List<SourcePathAndRootIndex>>() {
|
||||
private final byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
|
||||
|
||||
@Override
|
||||
public void save(DataOutput out, List<SourcePathAndRootIndex> value) throws IOException {
|
||||
for (SourcePathAndRootIndex pair : value) {
|
||||
IOUtil.writeUTFFast(myBuffer, out, pair.myPath);
|
||||
out.writeInt(pair.getRootIndex());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SourcePathAndRootIndex> read(DataInput in) throws IOException {
|
||||
List<SourcePathAndRootIndex> result = new SmartList<SourcePathAndRootIndex>();
|
||||
final DataInputStream stream = (DataInputStream)in;
|
||||
while (stream.available() > 0) {
|
||||
final String path = IOUtil.readUTFFast(myBuffer, stream);
|
||||
final int index = stream.readInt();
|
||||
result.add(new SourcePathAndRootIndex(path, index));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
public ArtifactOutputToSourceMapping(@NonNls File storePath) throws IOException {
|
||||
super(storePath, new EnumeratorStringDescriptor(), EXTERNALIZER);
|
||||
}
|
||||
|
||||
public static class SourcePathAndRootIndex {
|
||||
private final String myPath;
|
||||
private final int myRootIndex;
|
||||
|
||||
public SourcePathAndRootIndex(String path, int rootIndex) {
|
||||
myPath = path;
|
||||
myRootIndex = rootIndex;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return myPath;
|
||||
}
|
||||
|
||||
public int getRootIndex() {
|
||||
return myRootIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
-34
@@ -2,6 +2,7 @@ package org.jetbrains.jps.incremental.artifacts;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.IntArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.Project;
|
||||
import org.jetbrains.jps.ProjectPaths;
|
||||
@@ -13,11 +14,7 @@ import org.jetbrains.jps.incremental.artifacts.instructions.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -28,12 +25,13 @@ public class ArtifactSourceFilesState {
|
||||
private final int myArtifactId;
|
||||
private final ModuleRootsIndex myRootsIndex;
|
||||
private final ArtifactSourceTimestampStorage myTimestampStorage;
|
||||
private Set<String> myChangedFiles = new HashSet<String>();
|
||||
private Map<String, IntArrayList> myChangedFiles = new HashMap<String, IntArrayList>();
|
||||
private Set<String> myDeletedFiles = new HashSet<String>();
|
||||
private ArtifactInstructionsBuilder myInstructionsBuilder;
|
||||
private ArtifactSourceToOutputMapping myMapping;
|
||||
private final AtomicBoolean myInitialized = new AtomicBoolean();
|
||||
private final File myMappingsFile;
|
||||
private ArtifactSourceToOutputMapping mySrcOutMapping;
|
||||
private ArtifactOutputToSourceMapping myOutSrcMapping;
|
||||
private final File mySrcOutMappingsFile;
|
||||
private File myOutSrcMappingsFile;
|
||||
|
||||
public ArtifactSourceFilesState(Artifact artifact, int artifactId, Project project,
|
||||
ModuleRootsIndex rootsIndex,
|
||||
@@ -44,23 +42,34 @@ public class ArtifactSourceFilesState {
|
||||
myRootsIndex = rootsIndex;
|
||||
myTimestampStorage = timestampStorage;
|
||||
myArtifactId = artifactId;
|
||||
myMappingsFile = new File(new File(mappingsDir, String.valueOf(artifactId)), "src-out");
|
||||
mySrcOutMappingsFile = new File(new File(mappingsDir, String.valueOf(artifactId)), "src-out");
|
||||
myOutSrcMappingsFile = new File(new File(mappingsDir, String.valueOf(artifactId)), "out-src");
|
||||
}
|
||||
|
||||
public ArtifactSourceToOutputMapping getOrCreateMapping() throws IOException {
|
||||
if (myMapping == null) {
|
||||
myMapping = new ArtifactSourceToOutputMapping(myMappingsFile);
|
||||
public ArtifactSourceToOutputMapping getOrCreateSrcOutMapping() throws IOException {
|
||||
if (mySrcOutMapping == null) {
|
||||
mySrcOutMapping = new ArtifactSourceToOutputMapping(mySrcOutMappingsFile);
|
||||
}
|
||||
return myMapping;
|
||||
return mySrcOutMapping;
|
||||
}
|
||||
|
||||
public ArtifactOutputToSourceMapping getOrCreateOutSrcMapping() throws IOException {
|
||||
if (myOutSrcMapping == null) {
|
||||
myOutSrcMapping = new ArtifactOutputToSourceMapping(myOutSrcMappingsFile);
|
||||
}
|
||||
return myOutSrcMapping;
|
||||
}
|
||||
|
||||
public void clean() {
|
||||
if (myMapping != null) {
|
||||
myMapping.wipe();
|
||||
if (mySrcOutMapping != null) {
|
||||
mySrcOutMapping.wipe();
|
||||
}
|
||||
if (myOutSrcMapping != null) {
|
||||
myOutSrcMapping.wipe();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<String> getChangedFiles() {
|
||||
public Map<String, IntArrayList> getChangedFiles() {
|
||||
return myChangedFiles;
|
||||
}
|
||||
|
||||
@@ -69,25 +78,19 @@ public class ArtifactSourceFilesState {
|
||||
}
|
||||
|
||||
public void initState() throws IOException {
|
||||
/*
|
||||
if (!myInitialized.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
|
||||
final Set<String> currentPaths = new HashSet<String>();
|
||||
myChangedFiles.clear();
|
||||
myDeletedFiles.clear();
|
||||
getOrCreateInstructions().processRoots(new ArtifactRootProcessor() {
|
||||
@Override
|
||||
public void process(ArtifactSourceRoot root, Collection<DestinationInfo> destinations) throws IOException {
|
||||
public void process(ArtifactSourceRoot root, int rootIndex, Collection<DestinationInfo> destinations) throws IOException {
|
||||
final File rootFile = root.getRootFile();
|
||||
if (rootFile.exists()) {
|
||||
processRecursively(rootFile, root.getFilter(), currentPaths);
|
||||
processRecursively(rootFile, rootIndex, root.getFilter(), currentPaths);
|
||||
}
|
||||
}
|
||||
});
|
||||
final ArtifactSourceToOutputMapping mapping = getOrCreateMapping();
|
||||
final ArtifactSourceToOutputMapping mapping = getOrCreateSrcOutMapping();
|
||||
final Iterator<String> iterator = mapping.getKeysIterator();
|
||||
while (iterator.hasNext()) {
|
||||
String path = iterator.next();
|
||||
@@ -97,7 +100,7 @@ public class ArtifactSourceFilesState {
|
||||
}
|
||||
}
|
||||
|
||||
private void processRecursively(File file, SourceFileFilter filter, Set<String> currentPaths) throws IOException {
|
||||
private void processRecursively(File file, int rootIndex, SourceFileFilter filter, Set<String> currentPaths) throws IOException {
|
||||
final String filePath = FileUtil.toSystemIndependentName(FileUtil.toCanonicalPath(file.getPath()));
|
||||
if (!filter.accept(filePath)) return;
|
||||
|
||||
@@ -105,7 +108,7 @@ public class ArtifactSourceFilesState {
|
||||
final File[] children = file.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
processRecursively(child, filter, currentPaths);
|
||||
processRecursively(child, rootIndex, filter, currentPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -123,7 +126,12 @@ public class ArtifactSourceFilesState {
|
||||
}
|
||||
if (!upToDate) {
|
||||
myDeletedFiles.remove(filePath);
|
||||
myChangedFiles.add(filePath);
|
||||
IntArrayList list = myChangedFiles.get(filePath);
|
||||
if (list == null) {
|
||||
list = new IntArrayList(1);
|
||||
myChangedFiles.put(filePath, list);
|
||||
}
|
||||
list.add(rootIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,7 +164,7 @@ public class ArtifactSourceFilesState {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String filePath : myChangedFiles) {
|
||||
for (String filePath : myChangedFiles.keySet()) {
|
||||
final ArtifactSourceTimestampStorage.PerArtifactTimestamp[] state = myTimestampStorage.getState(filePath);
|
||||
File file = new File(FileUtil.toSystemDependentName(filePath));
|
||||
final long timestamp = file.lastModified();
|
||||
@@ -185,14 +193,20 @@ public class ArtifactSourceFilesState {
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
if (myMapping != null) {
|
||||
myMapping.close();
|
||||
if (mySrcOutMapping != null) {
|
||||
mySrcOutMapping.close();
|
||||
}
|
||||
if (myOutSrcMapping != null) {
|
||||
myOutSrcMapping.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void flush(boolean memoryCachesOnly) {
|
||||
if (myMapping != null) {
|
||||
myMapping.flush(memoryCachesOnly);
|
||||
if (mySrcOutMapping != null) {
|
||||
mySrcOutMapping.flush(memoryCachesOnly);
|
||||
}
|
||||
if (myOutSrcMapping != null) {
|
||||
myOutSrcMapping.flush(memoryCachesOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-17
@@ -1,47 +1,57 @@
|
||||
package org.jetbrains.jps.incremental.artifacts;
|
||||
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.EnumeratorStringDescriptor;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.jps.incremental.storage.AbstractStateStorage;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Stores output paths for each source file path. If a source file is located inside a jar the path to the jar file is stored.
|
||||
* If an output file is located in a jar file the path to the jar file with '!/' suffix is stored.
|
||||
* Stores output paths for each source file path. If a source file or an output file is located inside a jar the path to the jar file is stored.
|
||||
* //If an output file is located in a jar file the full path is stored using '!/' to separate path to the jar file from path to file inside the jar.
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactSourceToOutputMapping extends AbstractStateStorage<String, String[]> {
|
||||
private static DataExternalizer<String[]> STRING_ARRAY_EXTERNALIZER = new DataExternalizer<String[]>() {
|
||||
public class ArtifactSourceToOutputMapping extends AbstractStateStorage<String, List<String>> {
|
||||
private static DataExternalizer<List<String>> STRING_LIST_EXTERNALIZER = new DataExternalizer<List<String>>() {
|
||||
private final byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
|
||||
|
||||
@Override
|
||||
public void save(DataOutput out, String[] value) throws IOException {
|
||||
out.writeInt(value.length);
|
||||
public void save(DataOutput out, List<String> value) throws IOException {
|
||||
for (String path : value) {
|
||||
IOUtil.writeUTFFast(myBuffer, out, path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] read(DataInput in) throws IOException {
|
||||
final int size = in.readInt();
|
||||
String[] result = new String[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
final String path = IOUtil.readUTFFast(myBuffer, in);
|
||||
result[i] = path;
|
||||
public List<String> read(DataInput in) throws IOException {
|
||||
List<String> result = new SmartList<String>();
|
||||
final DataInputStream stream = (DataInputStream)in;
|
||||
while (stream.available() > 0) {
|
||||
result.add(IOUtil.readUTFFast(myBuffer, stream));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
public ArtifactSourceToOutputMapping(@NonNls File storePath) throws IOException {
|
||||
super(storePath, new EnumeratorStringDescriptor(), STRING_ARRAY_EXTERNALIZER);
|
||||
super(storePath, new EnumeratorStringDescriptor(), STRING_LIST_EXTERNALIZER);
|
||||
}
|
||||
|
||||
public void removeValue(String sourcePath, String outputPath) throws IOException {
|
||||
final List<String> outputPaths = getState(sourcePath);
|
||||
if (outputPaths != null) {
|
||||
outputPaths.remove(outputPath);
|
||||
if (outputPaths.isEmpty()) {
|
||||
remove(sourcePath);
|
||||
}
|
||||
else {
|
||||
update(sourcePath, outputPaths);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jps.incremental.artifacts;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.jps.Project;
|
||||
import org.jetbrains.jps.artifacts.Artifact;
|
||||
@@ -14,6 +15,7 @@ import java.util.Map;
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactsBuildData {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.artifacts.ArtifactsBuildData");
|
||||
private Map<Artifact, ArtifactSourceFilesState> myArtifactState;
|
||||
private final ArtifactSourceTimestampStorage myTimestampStorage;
|
||||
private ArtifactCompilerPersistentData myPersistentData;
|
||||
@@ -26,6 +28,11 @@ public class ArtifactsBuildData {
|
||||
myArtifactState = new HashMap<Artifact, ArtifactSourceFilesState>();
|
||||
myPersistentData = new ArtifactCompilerPersistentData(artifactsDataDir);
|
||||
myMappingsDir = new File(myArtifactsDataDir, "mappings");
|
||||
if (myPersistentData.isVersionChanged()) {
|
||||
myTimestampStorage.wipe();
|
||||
FileUtil.delete(myMappingsDir);
|
||||
//todo[nik] clear artifacts outputs
|
||||
}
|
||||
}
|
||||
|
||||
public ArtifactSourceFilesState getOrCreateState(Artifact artifact, Project project, ModuleRootsIndex index) {
|
||||
@@ -60,6 +67,7 @@ public class ArtifactsBuildData {
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
myPersistentData.save();
|
||||
myTimestampStorage.close();
|
||||
for (ArtifactSourceFilesState state : myArtifactState.values()) {
|
||||
state.close();
|
||||
@@ -67,6 +75,12 @@ public class ArtifactsBuildData {
|
||||
}
|
||||
|
||||
public void flush(boolean memoryCachesOnly) {
|
||||
try {
|
||||
myPersistentData.save();
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
myTimestampStorage.flush(memoryCachesOnly);
|
||||
for (ArtifactSourceFilesState state : myArtifactState.values()) {
|
||||
state.flush(memoryCachesOnly);
|
||||
|
||||
+94
-61
@@ -2,10 +2,10 @@ package org.jetbrains.jps.incremental.artifacts;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.IntArrayList;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.jps.artifacts.Artifact;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.ProjectBuildException;
|
||||
@@ -74,54 +74,92 @@ public class IncArtifactBuilder extends ProjectLevelBuilder {
|
||||
context.getProject(), context.getRootsIndex());
|
||||
state.initState();
|
||||
final Set<String> deletedFiles = state.getDeletedFiles();
|
||||
final Set<String> changedFiles = state.getChangedFiles();
|
||||
final Map<String,IntArrayList> changedFiles = state.getChangedFiles();
|
||||
if (deletedFiles.isEmpty() && changedFiles.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.processMessage(new ProgressMessage("Building artifact '" + artifact.getName() + "'..."));
|
||||
final ArtifactSourceToOutputMapping mapping = state.getOrCreateMapping();
|
||||
final Set<String> deletedJars = deleteOutdatedFiles(deletedFiles, context, mapping);
|
||||
final ArtifactInstructionsBuilder instructions = state.getOrCreateInstructions();
|
||||
final Set<JarInfo> changedJars = new THashSet<JarInfo>();
|
||||
for (String deletedJar : deletedJars) {
|
||||
ContainerUtil.addIfNotNull(instructions.getJarInfo(deletedJar), changedJars);
|
||||
final ArtifactSourceToOutputMapping srcOutMapping = state.getOrCreateSrcOutMapping();
|
||||
final ArtifactOutputToSourceMapping outSrcMapping = state.getOrCreateOutSrcMapping();
|
||||
|
||||
final TIntObjectHashMap<Set<String>> filesToProcess = new TIntObjectHashMap<Set<String>>();
|
||||
MultiMap<String, String> filesToDelete = new MultiMap<String, String>();
|
||||
for (String sourcePath : deletedFiles) {
|
||||
final List<String> outputPaths = srcOutMapping.getState(sourcePath);
|
||||
if (outputPaths != null) {
|
||||
for (String outputPath : outputPaths) {
|
||||
filesToDelete.putValue(outputPath, sourcePath);
|
||||
final List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex> sources = outSrcMapping.getState(outputPath);
|
||||
if (sources != null) {
|
||||
for (ArtifactOutputToSourceMapping.SourcePathAndRootIndex source : sources) {
|
||||
addFileToProcess(filesToProcess, source.getRootIndex(), source.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, String[]> updatedMappings = new HashMap<String, String[]>();
|
||||
for (final String filePath : changedFiles) {
|
||||
final List<String> outputs = new SmartList<String>();
|
||||
instructions.processContainingRoots(filePath, new ArtifactRootProcessor() {
|
||||
@Override
|
||||
public void process(ArtifactSourceRoot root, Collection<DestinationInfo> destinations) throws IOException {
|
||||
Set<String> changedOutputPaths = new THashSet<String>();
|
||||
for (Map.Entry<String, IntArrayList> entry : changedFiles.entrySet()) {
|
||||
final IntArrayList roots = entry.getValue();
|
||||
final String sourcePath = entry.getKey();
|
||||
for (int i = 0; i < roots.size(); i++) {
|
||||
addFileToProcess(filesToProcess, roots.get(i), sourcePath);
|
||||
}
|
||||
final List<String> outputPaths = srcOutMapping.getState(sourcePath);
|
||||
if (outputPaths != null) {
|
||||
changedOutputPaths.addAll(outputPaths);
|
||||
for (String outputPath : outputPaths) {
|
||||
final List<ArtifactOutputToSourceMapping.SourcePathAndRootIndex> sources = outSrcMapping.getState(outputPath);
|
||||
if (sources != null) {
|
||||
for (ArtifactOutputToSourceMapping.SourcePathAndRootIndex source : sources) {
|
||||
addFileToProcess(filesToProcess, source.getRootIndex(), source.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String sourcePath : changedFiles.keySet()) {
|
||||
srcOutMapping.remove(sourcePath);
|
||||
}
|
||||
for (String outputPath : changedOutputPaths) {
|
||||
outSrcMapping.remove(outputPath);
|
||||
}
|
||||
|
||||
deleteOutdatedFiles(filesToDelete, context, srcOutMapping, outSrcMapping);
|
||||
|
||||
final ArtifactInstructionsBuilder instructions = state.getOrCreateInstructions();
|
||||
final Set<JarInfo> changedJars = new THashSet<JarInfo>();
|
||||
instructions.processRoots(new ArtifactRootProcessor() {
|
||||
@Override
|
||||
public void process(ArtifactSourceRoot root, int rootIndex, Collection<DestinationInfo> destinations) throws IOException {
|
||||
final Set<String> sourcePaths = filesToProcess.get(rootIndex);
|
||||
if (sourcePaths == null) return;
|
||||
|
||||
for (String sourcePath : sourcePaths) {
|
||||
if (!root.containsFile(sourcePath)) continue;//todo[nik] this seems to be unnecessary
|
||||
|
||||
for (DestinationInfo destination : destinations) {
|
||||
if (destination instanceof ExplodedDestinationInfo) {
|
||||
context.getLoggingManager().getArtifactBuilderLogger().fileCopied(filePath);
|
||||
root.copyFromRoot(filePath, destination.getOutputPath(), outputs);
|
||||
root.copyFromRoot(sourcePath, rootIndex, destination.getOutputPath(), context, srcOutMapping, outSrcMapping);
|
||||
}
|
||||
else {
|
||||
outputs.add(destination.getOutputFilePath() + JarPathUtil.JAR_SEPARATOR);
|
||||
else if (outSrcMapping.getState(destination.getOutputFilePath()) == null) {
|
||||
outSrcMapping.update(destination.getOutputFilePath(), Collections.<ArtifactOutputToSourceMapping.SourcePathAndRootIndex>emptyList());
|
||||
changedJars.add(((JarDestinationInfo)destination).getJarInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
updatedMappings.put(filePath, ArrayUtil.toStringArray(outputs));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
JarsBuilder builder = new JarsBuilder(changedJars, null, context);
|
||||
final boolean processed = builder.buildJars(new THashSet<String>());
|
||||
JarsBuilder builder = new JarsBuilder(changedJars, context, srcOutMapping, outSrcMapping, instructions);
|
||||
final boolean processed = builder.buildJars();
|
||||
if (!processed) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.updateTimestamps();
|
||||
for (String filePath : deletedFiles) {
|
||||
mapping.remove(filePath);
|
||||
}
|
||||
for (Map.Entry<String, String[]> entry : updatedMappings.entrySet()) {
|
||||
mapping.update(entry.getKey(), entry.getValue());
|
||||
}
|
||||
state.markUpToDate();
|
||||
context.processMessage(UptoDateFilesSavedEvent.INSTANCE);
|
||||
}
|
||||
@@ -130,48 +168,45 @@ public class IncArtifactBuilder extends ProjectLevelBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> deleteOutdatedFiles(Set<String> deletedFiles, CompileContext context,
|
||||
ArtifactSourceToOutputMapping mapping) throws IOException {
|
||||
if (deletedFiles.isEmpty()) return Collections.emptySet();
|
||||
private static void addFileToProcess(TIntObjectHashMap<Set<String>> filesToProcess, final int rootIndex, final String path) {
|
||||
Set<String> paths = filesToProcess.get(rootIndex);
|
||||
if (paths == null) {
|
||||
paths = new THashSet<String>();
|
||||
filesToProcess.put(rootIndex, paths);
|
||||
}
|
||||
paths.add(path);
|
||||
}
|
||||
|
||||
private static void deleteOutdatedFiles(MultiMap<String, String> filesToDelete, CompileContext context,
|
||||
ArtifactSourceToOutputMapping srcOutMapping,
|
||||
ArtifactOutputToSourceMapping outSrcMapping) throws IOException {
|
||||
if (filesToDelete.isEmpty()) return;
|
||||
|
||||
context.processMessage(new ProgressMessage("Deleting outdated files..."));
|
||||
Set<String> pathsToDelete = new THashSet<String>();
|
||||
for (String path : deletedFiles) {
|
||||
final String[] outputPaths = mapping.getState(path);
|
||||
Collections.addAll(pathsToDelete, outputPaths);
|
||||
}
|
||||
|
||||
int notDeletedFilesCount = 0;
|
||||
final THashSet<String> notDeletedJars = new THashSet<String>();
|
||||
final THashSet<String> deletedJars = new THashSet<String>();
|
||||
final THashSet<String> notDeletedPaths = new THashSet<String>();
|
||||
final THashSet<String> deletedPaths = new THashSet<String>();
|
||||
|
||||
for (String fullPath : pathsToDelete) {
|
||||
int end = fullPath.indexOf(JarPathUtil.JAR_SEPARATOR);
|
||||
boolean isJar = end != -1;
|
||||
String filePath = isJar ? fullPath.substring(0, end) : fullPath;
|
||||
boolean deleted = false;
|
||||
if (isJar) {
|
||||
if (notDeletedJars.contains(filePath)) {
|
||||
continue;
|
||||
}
|
||||
deleted = deletedJars.contains(filePath);
|
||||
for (String filePath : filesToDelete.keySet()) {
|
||||
if (notDeletedPaths.contains(filePath)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
File file = new File(FileUtil.toSystemDependentName(filePath));
|
||||
boolean deleted = deletedPaths.contains(filePath);
|
||||
if (!deleted) {
|
||||
deleted = FileUtil.delete(file);
|
||||
deleted = FileUtil.delete(new File(FileUtil.toSystemDependentName(filePath)));
|
||||
}
|
||||
|
||||
if (deleted) {
|
||||
context.getLoggingManager().getArtifactBuilderLogger().fileDeleted(filePath);
|
||||
if (isJar) {
|
||||
deletedJars.add(filePath);
|
||||
outSrcMapping.remove(filePath);
|
||||
deletedPaths.add(filePath);
|
||||
for (String sourcePath : filesToDelete.get(filePath)) {
|
||||
srcOutMapping.removeValue(sourcePath, filePath);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isJar) {
|
||||
notDeletedJars.add(filePath);
|
||||
}
|
||||
notDeletedPaths.add(filePath);
|
||||
if (notDeletedFilesCount++ > 50) {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.WARNING, "Deletion of outdated files stopped because too many files cannot be deleted"));
|
||||
break;
|
||||
@@ -179,8 +214,6 @@ public class IncArtifactBuilder extends ProjectLevelBuilder {
|
||||
context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.WARNING, "Cannot delete file '" + filePath + "'"));
|
||||
}
|
||||
}
|
||||
|
||||
return deletedJars;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+8
-4
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.jps.incremental.artifacts.impl;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.jps.incremental.artifacts.instructions.DestinationInfo;
|
||||
import org.jetbrains.jps.incremental.artifacts.instructions.JarDestinationInfo;
|
||||
import org.jetbrains.jps.incremental.artifacts.instructions.JarInfo;
|
||||
|
||||
@@ -31,11 +32,14 @@ public class DependentJarsEvaluator {
|
||||
|
||||
public void addJarWithDependencies(final JarInfo jarInfo) {
|
||||
if (myJars.add(jarInfo)) {
|
||||
for (JarDestinationInfo destination : jarInfo.getJarDestinations()) {
|
||||
addJarWithDependencies(destination.getJarInfo());
|
||||
final DestinationInfo destination = jarInfo.getDestination();
|
||||
if (destination instanceof JarDestinationInfo) {
|
||||
addJarWithDependencies(((JarDestinationInfo)destination).getJarInfo());
|
||||
}
|
||||
for (Pair<String, JarInfo> pair : jarInfo.getPackedJars()) {
|
||||
addJarWithDependencies(pair.getSecond());
|
||||
for (Pair<String, Object> pair : jarInfo.getContent()) {
|
||||
if (pair.getSecond() instanceof JarInfo) {
|
||||
addJarWithDependencies((JarInfo)pair.getSecond());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+67
-58
@@ -32,6 +32,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.PathUtil;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactBuilderLogger;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactSourceToOutputMapping;
|
||||
import org.jetbrains.jps.incremental.artifacts.IncArtifactBuilder;
|
||||
import org.jetbrains.jps.incremental.artifacts.instructions.*;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
@@ -50,21 +52,28 @@ import java.util.zip.ZipOutputStream;
|
||||
public class JarsBuilder {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.packagingCompiler.JarsBuilder");
|
||||
private final Set<JarInfo> myJarsToBuild;
|
||||
private final FileFilter myFileFilter;
|
||||
private final CompileContext myContext;
|
||||
private Map<JarInfo, File> myBuiltJars;
|
||||
private final ArtifactSourceToOutputMapping mySrcOutMapping;
|
||||
private final ArtifactOutputToSourceMapping myOutSrcMapping;
|
||||
private final ArtifactInstructionsBuilder myInstructions;
|
||||
|
||||
public JarsBuilder(Set<JarInfo> jarsToBuild, FileFilter fileFilter, CompileContext context) {
|
||||
public JarsBuilder(Set<JarInfo> jarsToBuild,
|
||||
CompileContext context,
|
||||
ArtifactSourceToOutputMapping srcOutMapping,
|
||||
ArtifactOutputToSourceMapping outSrcMapping, ArtifactInstructionsBuilder instructions) {
|
||||
mySrcOutMapping = srcOutMapping;
|
||||
myOutSrcMapping = outSrcMapping;
|
||||
myInstructions = instructions;
|
||||
DependentJarsEvaluator evaluator = new DependentJarsEvaluator();
|
||||
for (JarInfo jarInfo : jarsToBuild) {
|
||||
evaluator.addJarWithDependencies(jarInfo);
|
||||
}
|
||||
myJarsToBuild = evaluator.getJars();
|
||||
myFileFilter = fileFilter;
|
||||
myContext = context;
|
||||
}
|
||||
|
||||
public boolean buildJars(Set<String> writtenPaths) throws IOException {
|
||||
public boolean buildJars() throws IOException {
|
||||
myContext.processMessage(new ProgressMessage("Building archives..."));
|
||||
|
||||
final JarInfo[] sortedJars = sortJars();
|
||||
@@ -79,7 +88,7 @@ public class JarsBuilder {
|
||||
}
|
||||
|
||||
myContext.processMessage(new ProgressMessage("Copying archives..."));
|
||||
copyJars(writtenPaths);
|
||||
copyJars();
|
||||
}
|
||||
finally {
|
||||
deleteTemporaryJars();
|
||||
@@ -95,33 +104,18 @@ public class JarsBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private void copyJars(final Set<String> writtenPaths) throws IOException {
|
||||
private void copyJars() throws IOException {
|
||||
for (Map.Entry<JarInfo, File> entry : myBuiltJars.entrySet()) {
|
||||
File fromFile = entry.getValue();
|
||||
boolean first = true;
|
||||
for (DestinationInfo destination : entry.getKey().getAllDestinations()) {
|
||||
if (destination instanceof ExplodedDestinationInfo) {
|
||||
File toFile = new File(FileUtil.toSystemDependentName(destination.getOutputPath()));
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
renameFile(fromFile, toFile, writtenPaths);
|
||||
fromFile = toFile;
|
||||
}
|
||||
else {
|
||||
FileUtil.copyContent(fromFile, toFile);
|
||||
}
|
||||
|
||||
}
|
||||
final JarInfo jarInfo = entry.getKey();
|
||||
DestinationInfo destination = jarInfo.getDestination();
|
||||
if (destination instanceof ExplodedDestinationInfo) {
|
||||
File toFile = new File(FileUtil.toSystemDependentName(destination.getOutputPath()));
|
||||
FileUtil.rename(fromFile, toFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void renameFile(final File fromFile, final File toFile, final Set<String> writtenPaths) throws IOException {
|
||||
FileUtil.rename(fromFile, toFile);
|
||||
writtenPaths.add(toFile.getPath());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JarInfo[] sortJars() {
|
||||
final DFSTBuilder<JarInfo> builder = new DFSTBuilder<JarInfo>(GraphGenerator.create(CachingSemiGraph.create(new JarsGraph())));
|
||||
@@ -139,12 +133,8 @@ public class JarsBuilder {
|
||||
return jars;
|
||||
}
|
||||
|
||||
public Set<JarInfo> getJarsToBuild() {
|
||||
return myJarsToBuild;
|
||||
}
|
||||
|
||||
private void buildJar(final JarInfo jar) throws IOException {
|
||||
if (jar.getPackedJars().isEmpty() && jar.getPackedRoots().isEmpty()) {
|
||||
if (jar.getContent().isEmpty()) {
|
||||
final String message = "Archive '" + jar.getPresentableDestination() + "' has no files so it won't be created";
|
||||
myContext.processMessage(new CompilerMessage(IncArtifactBuilder.BUILDER_NAME, BuildMessage.Kind.WARNING, message));
|
||||
return;
|
||||
@@ -157,27 +147,38 @@ public class JarsBuilder {
|
||||
FileUtil.createParentDirs(jarFile);
|
||||
final JarOutputStream jarOutputStream = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(jarFile)));
|
||||
|
||||
final String targetJarPath = jar.getDestination().getOutputFilePath();
|
||||
try {
|
||||
final THashSet<String> writtenPaths = new THashSet<String>();
|
||||
for (Pair<String, ArtifactSourceRoot> pair : jar.getPackedRoots()) {
|
||||
final ArtifactSourceRoot root = pair.getSecond();
|
||||
final ArtifactBuilderLogger logger = myContext.getLoggingManager().getArtifactBuilderLogger();
|
||||
if (root instanceof FileBasedArtifactSourceRoot) {
|
||||
addFileToJar(jarOutputStream, jarFile, root.getRootFile(), root.getFilter(), pair.getFirst(), writtenPaths);
|
||||
for (Pair<String, Object> pair : jar.getContent()) {
|
||||
final String relativePath = pair.getFirst();
|
||||
if (pair.getSecond() instanceof ArtifactSourceRoot) {
|
||||
final ArtifactSourceRoot root = (ArtifactSourceRoot)pair.getSecond();
|
||||
final int rootIndex = myInstructions.getRootIndex(root);
|
||||
LOG.assertTrue(rootIndex != -1, root + " not found in instructions");
|
||||
final ArtifactBuilderLogger logger = myContext.getLoggingManager().getArtifactBuilderLogger();
|
||||
if (root instanceof FileBasedArtifactSourceRoot) {
|
||||
addFileToJar(jarOutputStream, jarFile, root.getRootFile(), root.getFilter(), relativePath, targetJarPath, writtenPaths,
|
||||
rootIndex);
|
||||
}
|
||||
else {
|
||||
final String filePath = FileUtil.toSystemIndependentName(root.getRootFile().getAbsolutePath());
|
||||
logger.fileCopied(filePath);
|
||||
mySrcOutMapping.appendData(filePath, Collections.singletonList(targetJarPath));
|
||||
myOutSrcMapping.appendData(targetJarPath, Collections
|
||||
.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
|
||||
extractFileAndAddToJar(jarOutputStream, (JarBasedArtifactSourceRoot)root, relativePath, writtenPaths);
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.fileCopied(FileUtil.toSystemIndependentName(root.getRootFile().getAbsolutePath()));
|
||||
extractFileAndAddToJar(jarOutputStream, (JarBasedArtifactSourceRoot)root, pair.getFirst(), writtenPaths);
|
||||
}
|
||||
}
|
||||
|
||||
for (Pair<String, JarInfo> nestedJar : jar.getPackedJars()) {
|
||||
File nestedJarFile = myBuiltJars.get(nestedJar.getSecond());
|
||||
if (nestedJarFile != null) {
|
||||
addFileToJar(jarOutputStream, jarFile, nestedJarFile, SourceFileFilter.ALL, nestedJar.getFirst(), writtenPaths);
|
||||
}
|
||||
else {
|
||||
LOG.debug("nested jar file " + nestedJar.getFirst() + " for " + jar.getPresentableDestination() + " not found");
|
||||
JarInfo nestedJar = (JarInfo)pair.getSecond();
|
||||
File nestedJarFile = myBuiltJars.get(nestedJar);
|
||||
if (nestedJarFile != null) {
|
||||
addFileToJar(jarOutputStream, jarFile, nestedJarFile, SourceFileFilter.ALL, relativePath, targetJarPath, writtenPaths, -1);
|
||||
}
|
||||
else {
|
||||
LOG.debug("nested jar file " + relativePath + " for " + jar.getPresentableDestination() + " not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -211,21 +212,23 @@ public class JarsBuilder {
|
||||
}
|
||||
|
||||
private void addFileToJar(final @NotNull JarOutputStream jarOutputStream, final @NotNull File jarFile, @NotNull File file,
|
||||
SourceFileFilter filter, @NotNull String relativePath, final @NotNull Set<String> writtenPaths) throws IOException {
|
||||
SourceFileFilter filter, @NotNull String relativePath, String targetJarPath,
|
||||
final @NotNull Set<String> writtenPaths, final int rootIndex) throws IOException {
|
||||
if (!file.exists() || FileUtil.isAncestor(file, jarFile, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
relativePath = addParentDirectories(jarOutputStream, writtenPaths, relativePath);
|
||||
addFileOrDirRecursively(jarOutputStream, file, filter, relativePath, writtenPaths);
|
||||
addFileOrDirRecursively(jarOutputStream, file, filter, relativePath, targetJarPath, writtenPaths, rootIndex);
|
||||
}
|
||||
|
||||
private void addFileOrDirRecursively(@NotNull ZipOutputStream jarOutputStream,
|
||||
@NotNull File file,
|
||||
SourceFileFilter filter,
|
||||
@NotNull String relativePath,
|
||||
@NotNull Set<String> writtenItemRelativePaths) throws IOException {
|
||||
if (!filter.accept(FileUtil.toSystemIndependentName(file.getAbsolutePath()))) {
|
||||
String targetJarPath, @NotNull Set<String> writtenItemRelativePaths, int rootIndex) throws IOException {
|
||||
final String filePath = FileUtil.toSystemIndependentName(file.getAbsolutePath());
|
||||
if (!filter.accept(filePath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -237,15 +240,20 @@ public class JarsBuilder {
|
||||
final File[] children = file.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
addFileOrDirRecursively(jarOutputStream, child, filter, directoryPath + child.getName(), writtenItemRelativePaths);
|
||||
addFileOrDirRecursively(jarOutputStream, child, filter, directoryPath + child.getName(), targetJarPath, writtenItemRelativePaths,
|
||||
rootIndex);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean added = ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenItemRelativePaths, myFileFilter);
|
||||
if (added) {
|
||||
myContext.getLoggingManager().getArtifactBuilderLogger().fileCopied(FileUtil.toSystemIndependentName(file.getAbsolutePath()));
|
||||
final boolean added = ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenItemRelativePaths, null);
|
||||
if (rootIndex != -1) {
|
||||
myOutSrcMapping.appendData(targetJarPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
|
||||
if (added) {
|
||||
mySrcOutMapping.appendData(filePath, Collections.singletonList(targetJarPath));
|
||||
myContext.getLoggingManager().getArtifactBuilderLogger().fileCopied(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,8 +291,9 @@ public class JarsBuilder {
|
||||
|
||||
public Iterator<JarInfo> getIn(final JarInfo n) {
|
||||
Set<JarInfo> ins = new HashSet<JarInfo>();
|
||||
for (JarDestinationInfo destination : n.getJarDestinations()) {
|
||||
ins.add(destination.getJarInfo());
|
||||
final DestinationInfo destination = n.getDestination();
|
||||
if (destination instanceof JarDestinationInfo) {
|
||||
ins.add(((JarDestinationInfo)destination).getJarInfo());
|
||||
}
|
||||
return ins.iterator();
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
package org.jetbrains.jps.incremental.artifacts.instructions;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -10,8 +11,8 @@ import java.io.IOException;
|
||||
public interface ArtifactInstructionsBuilder {
|
||||
void processRoots(ArtifactRootProcessor processor) throws IOException;
|
||||
|
||||
void processContainingRoots(String filePath, ArtifactRootProcessor processor) throws IOException;
|
||||
|
||||
@Nullable
|
||||
JarInfo getJarInfo(String outputPath);
|
||||
|
||||
int getRootIndex(@NotNull ArtifactSourceRoot root);
|
||||
}
|
||||
|
||||
+15
-27
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.jps.incremental.artifacts.instructions;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.containers.LinkedMultiMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -17,7 +18,6 @@ import java.util.Map;
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactInstructionsBuilderImpl implements ArtifactInstructionsBuilder {
|
||||
private final Map<String, ArtifactSourceRoot> mySourceByOutput;
|
||||
private final Map<String, JarInfo> myJarByPath;
|
||||
private final MultiMap<ArtifactSourceRoot, DestinationInfo> myInstructions;
|
||||
private final ModuleRootsIndex myRootsIndex;
|
||||
@@ -26,9 +26,8 @@ public class ArtifactInstructionsBuilderImpl implements ArtifactInstructionsBuil
|
||||
public ArtifactInstructionsBuilderImpl(ModuleRootsIndex rootsIndex, IgnoredFilePatterns patterns) {
|
||||
myRootsIndex = rootsIndex;
|
||||
myIgnoredFilePatterns = patterns;
|
||||
mySourceByOutput = new HashMap<String, ArtifactSourceRoot>();
|
||||
myJarByPath = new HashMap<String, JarInfo>();
|
||||
myInstructions = new MultiMap<ArtifactSourceRoot, DestinationInfo>();
|
||||
myInstructions = new LinkedMultiMap<ArtifactSourceRoot, DestinationInfo>();
|
||||
}
|
||||
|
||||
public IgnoredFilePatterns getIgnoredFilePatterns() {
|
||||
@@ -41,28 +40,14 @@ public class ArtifactInstructionsBuilderImpl implements ArtifactInstructionsBuil
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkOutputPath(destinationInfo.getOutputPath(), root)) {
|
||||
myInstructions.putValue(root, destinationInfo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
myInstructions.putValue(root, destinationInfo);
|
||||
return true;
|
||||
}
|
||||
|
||||
public ModuleRootsIndex getRootsIndex() {
|
||||
return myRootsIndex;
|
||||
}
|
||||
|
||||
public boolean checkOutputPath(final String outputPath, final ArtifactSourceRoot sourceFile) {
|
||||
//todo[nik] combine intersecting roots
|
||||
//ArtifactSourceRoot old = mySourceByOutput.get(outputPath);
|
||||
//if (old == null) {
|
||||
// mySourceByOutput.put(outputPath, sourceFile);
|
||||
// return true;
|
||||
//}
|
||||
//todo[nik] show warning?
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean registerJarFile(@NotNull JarInfo jarInfo, @NotNull String outputPath) {
|
||||
if (myJarByPath.containsKey(outputPath)) {
|
||||
return false;
|
||||
@@ -78,20 +63,23 @@ public class ArtifactInstructionsBuilderImpl implements ArtifactInstructionsBuil
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processRoots(ArtifactRootProcessor processor) throws IOException {
|
||||
public int getRootIndex(@NotNull ArtifactSourceRoot root) {
|
||||
int i = 0;
|
||||
for (Map.Entry<ArtifactSourceRoot, Collection<DestinationInfo>> entry : myInstructions.entrySet()) {
|
||||
processor.process(entry.getKey(), entry.getValue());
|
||||
if (entry.getKey().equals(root)) {
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processContainingRoots(String filePath, ArtifactRootProcessor processor) throws IOException {
|
||||
//todo[nik] improve?
|
||||
public void processRoots(ArtifactRootProcessor processor) throws IOException {
|
||||
int i = 0;
|
||||
for (Map.Entry<ArtifactSourceRoot, Collection<DestinationInfo>> entry : myInstructions.entrySet()) {
|
||||
final ArtifactSourceRoot root = entry.getKey();
|
||||
if (root.containsFile(filePath)) {
|
||||
processor.process(root, entry.getValue());
|
||||
}
|
||||
processor.process(entry.getKey(), i, entry.getValue());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,5 +7,5 @@ import java.util.Collection;
|
||||
* @author nik
|
||||
*/
|
||||
public interface ArtifactRootProcessor {
|
||||
void process(ArtifactSourceRoot root, Collection<DestinationInfo> destinations) throws IOException;
|
||||
void process(ArtifactSourceRoot root, int rootIndex, Collection<DestinationInfo> destinations) throws IOException;
|
||||
}
|
||||
|
||||
+7
-2
@@ -1,10 +1,12 @@
|
||||
package org.jetbrains.jps.incremental.artifacts.instructions;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactSourceToOutputMapping;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -21,7 +23,10 @@ public abstract class ArtifactSourceRoot {
|
||||
|
||||
public abstract boolean containsFile(String filePath);
|
||||
|
||||
public abstract void copyFromRoot(String filePath, String outputPath, List<String> outputs) throws IOException;
|
||||
public abstract void copyFromRoot(String filePath,
|
||||
int rootIndex, String outputPath,
|
||||
CompileContext context, ArtifactSourceToOutputMapping srcOutMapping,
|
||||
ArtifactOutputToSourceMapping outSrcMapping) throws IOException;
|
||||
|
||||
public SourceFileFilter getFilter() {
|
||||
return myFilter;
|
||||
|
||||
+2
-3
@@ -45,12 +45,11 @@ public class CopyToDirectoryInstructionCreator extends ArtifactCompilerInstructi
|
||||
|
||||
public ArtifactCompilerInstructionCreator archive(@NotNull String archiveFileName) {
|
||||
String jarOutputPath = myOutputPath + "/" + archiveFileName;
|
||||
final JarInfo jarInfo = new JarInfo();
|
||||
final ExplodedDestinationInfo destination = new ExplodedDestinationInfo(jarOutputPath);
|
||||
final JarInfo jarInfo = new JarInfo(destination);
|
||||
if (!myInstructionsBuilder.registerJarFile(jarInfo, jarOutputPath)) {
|
||||
return new SkipAllInstructionCreator(myInstructionsBuilder);
|
||||
}
|
||||
final ExplodedDestinationInfo destination = new ExplodedDestinationInfo(jarOutputPath);
|
||||
jarInfo.addDestination(destination);
|
||||
return new PackIntoArchiveInstructionCreator(myInstructionsBuilder, jarInfo, "", destination);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,8 +25,8 @@ public abstract class DestinationInfo {
|
||||
private final String myOutputFilePath;
|
||||
|
||||
protected DestinationInfo(@NotNull final String outputPath, @NotNull String outputFilePath) {
|
||||
myOutputFilePath = outputFilePath;
|
||||
myOutputPath = outputPath;
|
||||
myOutputFilePath = outputFilePath;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+17
-5
@@ -3,10 +3,13 @@ package org.jetbrains.jps.incremental.artifacts.instructions;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.PathUtil;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactSourceToOutputMapping;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -49,8 +52,12 @@ public class FileBasedArtifactSourceRoot extends ArtifactSourceRoot {
|
||||
return 31 * super.hashCode() + myFile.hashCode();
|
||||
}
|
||||
|
||||
public void copyFromRoot(String filePath, String outputPath, List<String> outputs) throws IOException {
|
||||
public void copyFromRoot(String filePath,
|
||||
int rootIndex, String outputPath,
|
||||
CompileContext context, ArtifactSourceToOutputMapping srcOutMapping,
|
||||
ArtifactOutputToSourceMapping outSrcMapping) throws IOException {
|
||||
final File file = new File(FileUtil.toSystemDependentName(filePath));
|
||||
if (!file.exists()) return;
|
||||
String targetPath;
|
||||
if (!file.equals(getRootFile())) {
|
||||
final String relativePath = FileUtil.getRelativePath(FileUtil.toSystemIndependentName(getRootFile().getPath()), filePath, '/');
|
||||
@@ -59,8 +66,13 @@ public class FileBasedArtifactSourceRoot extends ArtifactSourceRoot {
|
||||
else {
|
||||
targetPath = outputPath;
|
||||
}
|
||||
final File targetFile = new File(FileUtil.toSystemDependentName(targetPath));
|
||||
FileUtil.copyContent(file, targetFile);
|
||||
outputs.add(targetPath);
|
||||
|
||||
if (outSrcMapping.getState(targetPath) == null) {
|
||||
context.getLoggingManager().getArtifactBuilderLogger().fileCopied(filePath);
|
||||
final File targetFile = new File(FileUtil.toSystemDependentName(targetPath));
|
||||
FileUtil.copyContent(file, targetFile);
|
||||
srcOutMapping.appendData(filePath, Collections.singletonList(targetPath));
|
||||
}
|
||||
outSrcMapping.appendData(targetPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
|
||||
}
|
||||
}
|
||||
|
||||
+22
-11
@@ -5,11 +5,14 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.PathUtil;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactOutputToSourceMapping;
|
||||
import org.jetbrains.jps.incremental.artifacts.ArtifactSourceToOutputMapping;
|
||||
import org.jetbrains.jps.incremental.artifacts.JarPathUtil;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@@ -82,7 +85,11 @@ public class JarBasedArtifactSourceRoot extends ArtifactSourceRoot {
|
||||
}
|
||||
}
|
||||
|
||||
public void copyFromRoot(String filePath, final String outputPath, final List<String> outputs) throws IOException {
|
||||
public void copyFromRoot(final String filePath,
|
||||
final int rootIndex, final String outputPath,
|
||||
CompileContext context, final ArtifactSourceToOutputMapping srcOutMapping,
|
||||
final ArtifactOutputToSourceMapping outSrcMapping) throws IOException {
|
||||
context.getLoggingManager().getArtifactBuilderLogger().fileCopied(filePath);
|
||||
processEntries(new EntryProcessor() {
|
||||
@Override
|
||||
public void process(@Nullable InputStream inputStream, @NotNull String relativePath) throws IOException {
|
||||
@@ -94,17 +101,21 @@ public class JarBasedArtifactSourceRoot extends ArtifactSourceRoot {
|
||||
outputFile.mkdir();
|
||||
}
|
||||
else {
|
||||
final BufferedInputStream from = new BufferedInputStream(inputStream);
|
||||
final BufferedOutputStream to = new BufferedOutputStream(new FileOutputStream(outputFile));
|
||||
try {
|
||||
FileUtil.copy(from, to);
|
||||
}
|
||||
finally {
|
||||
from.close();
|
||||
to.close();
|
||||
String fullSourcePath = filePath + JarPathUtil.JAR_SEPARATOR + relativePath;
|
||||
if (outSrcMapping.getState(fullOutputPath) == null) {
|
||||
final BufferedInputStream from = new BufferedInputStream(inputStream);
|
||||
final BufferedOutputStream to = new BufferedOutputStream(new FileOutputStream(outputFile));
|
||||
try {
|
||||
FileUtil.copy(from, to);
|
||||
}
|
||||
finally {
|
||||
from.close();
|
||||
to.close();
|
||||
}
|
||||
srcOutMapping.appendData(filePath, Collections.singletonList(fullOutputPath));
|
||||
}
|
||||
outSrcMapping.appendData(fullOutputPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(fullSourcePath, rootIndex)));
|
||||
}
|
||||
outputs.add(fullOutputPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+14
-34
@@ -17,60 +17,40 @@
|
||||
package org.jetbrains.jps.incremental.artifacts.instructions;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class JarInfo {
|
||||
private final List<Pair<String, ArtifactSourceRoot>> myPackedRoots;
|
||||
private final LinkedHashSet<Pair<String, JarInfo>> myPackedJars;
|
||||
private final List<DestinationInfo> myDestinations;
|
||||
private final List<Pair<String, Object>> myContent;
|
||||
private final DestinationInfo myDestination;
|
||||
|
||||
public JarInfo() {
|
||||
myDestinations = new ArrayList<DestinationInfo>();
|
||||
myPackedRoots = new ArrayList<Pair<String, ArtifactSourceRoot>>();
|
||||
myPackedJars = new LinkedHashSet<Pair<String, JarInfo>>();
|
||||
}
|
||||
|
||||
public void addDestination(DestinationInfo info) {
|
||||
myDestinations.add(info);
|
||||
if (info instanceof JarDestinationInfo) {
|
||||
JarDestinationInfo destinationInfo = (JarDestinationInfo)info;
|
||||
destinationInfo.getJarInfo().myPackedJars.add(Pair.create(destinationInfo.getPathInJar(), this));
|
||||
}
|
||||
public JarInfo(@NotNull DestinationInfo destination) {
|
||||
myDestination = destination;
|
||||
myContent = new ArrayList<Pair<String, Object>>();
|
||||
}
|
||||
|
||||
public void addContent(String pathInJar, ArtifactSourceRoot sourceFile) {
|
||||
myPackedRoots.add(Pair.create(pathInJar, sourceFile));
|
||||
myContent.add(Pair.create(pathInJar, (Object)sourceFile));
|
||||
}
|
||||
|
||||
public List<Pair<String, ArtifactSourceRoot>> getPackedRoots() {
|
||||
return myPackedRoots;
|
||||
public void addJar(String pathInJar, JarInfo jarInfo) {
|
||||
myContent.add(Pair.create(pathInJar, (Object)jarInfo));
|
||||
}
|
||||
|
||||
public LinkedHashSet<Pair<String, JarInfo>> getPackedJars() {
|
||||
return myPackedJars;
|
||||
public List<Pair<String, Object>> getContent() {
|
||||
return myContent;
|
||||
}
|
||||
|
||||
public List<JarDestinationInfo> getJarDestinations() {
|
||||
final ArrayList<JarDestinationInfo> list = new ArrayList<JarDestinationInfo>();
|
||||
for (DestinationInfo destination : myDestinations) {
|
||||
if (destination instanceof JarDestinationInfo) {
|
||||
list.add((JarDestinationInfo)destination);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<DestinationInfo> getAllDestinations() {
|
||||
return myDestinations;
|
||||
public DestinationInfo getDestination() {
|
||||
return myDestination;
|
||||
}
|
||||
|
||||
public String getPresentableDestination() {
|
||||
return !myDestinations.isEmpty() ? myDestinations.get(0).getOutputPath() : "";
|
||||
return myDestination.getOutputPath();
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.jetbrains.jps.incremental.artifacts.instructions;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
@@ -59,13 +60,13 @@ public class PackIntoArchiveInstructionCreator extends ArtifactCompilerInstructi
|
||||
}
|
||||
|
||||
public ArtifactCompilerInstructionCreator archive(@NotNull String archiveFileName) {
|
||||
final JarInfo jarInfo = new JarInfo();
|
||||
final JarDestinationInfo destination = new JarDestinationInfo(childPathInJar(archiveFileName), myJarInfo, myJarDestination);
|
||||
final JarInfo jarInfo = new JarInfo(destination);
|
||||
final String outputPath = myJarDestination.getOutputPath() + "/" + archiveFileName;
|
||||
if (!myInstructionsBuilder.registerJarFile(jarInfo, outputPath)) {
|
||||
return new SkipAllInstructionCreator(myInstructionsBuilder);
|
||||
}
|
||||
final JarDestinationInfo destination = new JarDestinationInfo(childPathInJar(archiveFileName), myJarInfo, myJarDestination);
|
||||
jarInfo.addDestination(destination);
|
||||
myJarInfo.addJar(destination.getPathInJar(), jarInfo);
|
||||
return new PackIntoArchiveInstructionCreator(myInstructionsBuilder, jarInfo, "", destination);
|
||||
}
|
||||
}
|
||||
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
package org.jetbrains.jps.incremental.artifacts;
|
||||
|
||||
import org.jetbrains.jps.artifacts.Artifact;
|
||||
|
||||
import static com.intellij.util.io.TestFileSystemBuilder.fs;
|
||||
import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase {
|
||||
public void testOverwriteArchives() {
|
||||
final String aFile = createFile("aaa.txt", "a");
|
||||
final String bFile = createFile("bbb.txt", "b");
|
||||
final Artifact a = addArtifact(
|
||||
root()
|
||||
.archive("x.jar").fileCopy(aFile).end()
|
||||
.archive("x.jar")
|
||||
.fileCopy(bFile));
|
||||
buildAll();
|
||||
assertOutput(a, fs()
|
||||
.archive("x.jar")
|
||||
.file("aaa.txt", "a")
|
||||
);
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(aFile, "a2");
|
||||
buildAll();
|
||||
assertCopied("aaa.txt");
|
||||
assertOutput(a, fs().archive("x.jar").file("aaa.txt", "a2"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(bFile, "b2");
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
delete(bFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
}
|
||||
|
||||
public void testOverwriteNestedArchive() {
|
||||
final String cFile = createFile("c.txt", "c");
|
||||
final String eFile = createFile("e.txt", "e");
|
||||
final Artifact a = addArtifact(
|
||||
root()
|
||||
.archive("a.jar").archive("b.jar").fileCopy(cFile).end().end()
|
||||
.archive("a.jar").archive("d.jar").fileCopy(eFile));
|
||||
buildAll();
|
||||
assertOutput(a, fs().archive("a.jar").archive("b.jar").file("c.txt", "c"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(eFile, "e2");
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(cFile, "c2");
|
||||
buildAll();
|
||||
assertCopied("c.txt");
|
||||
assertOutput(a, fs().archive("a.jar").archive("b.jar").file("c.txt", "c2"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
delete(eFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
}
|
||||
|
||||
public void testOverwriteFileByArchive() {
|
||||
final String xFile = createFile("x.txt", "1");
|
||||
final String jarFile = createFile("junit.jar", "123");
|
||||
Artifact a = addArtifact(root()
|
||||
.archive("junit.jar").fileCopy(xFile).end()
|
||||
.fileCopy(jarFile));
|
||||
buildAll();
|
||||
assertOutput(a, fs().archive("junit.jar").file("x.txt", "1"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(xFile, "2");
|
||||
buildAll();
|
||||
assertCopied("x.txt");
|
||||
assertOutput(a, fs().archive("junit.jar").file("x.txt", "2"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(jarFile, "321");
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
delete(jarFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
}
|
||||
|
||||
public void testOverwriteArchiveByFile() {
|
||||
final String xFile = createFile("x.txt", "1");
|
||||
final String jarFile = createFile("jdom.jar", "123");
|
||||
Artifact a = addArtifact(root()
|
||||
.fileCopy(jarFile)
|
||||
.archive("jdom.jar").fileCopy(xFile));
|
||||
buildAll();
|
||||
assertOutput(a, fs().file("jdom.jar", "123"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(xFile, "2");
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(jarFile, "321");
|
||||
buildAll();
|
||||
assertCopied("jdom.jar");
|
||||
assertOutput(a, fs().file("jdom.jar", "321"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
delete(xFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
}
|
||||
|
||||
public void testFileOrder() {
|
||||
final String firstFile = createFile("d1/xxx.txt", "first");
|
||||
final String secondFile = createFile("d2/xxx.txt", "second");
|
||||
final String fooFile = createFile("d3/xxx.txt", "foo");
|
||||
final Artifact a = addArtifact(
|
||||
root().dir("ddd")
|
||||
.fileCopy(firstFile)
|
||||
.fileCopy(fooFile)
|
||||
.fileCopy(secondFile).end()
|
||||
);
|
||||
buildAll();
|
||||
assertOutput(a, fs().dir("ddd").file("xxx.txt", "first"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(firstFile, "first2");
|
||||
buildAll();
|
||||
assertCopied("d1/xxx.txt");
|
||||
assertOutput(a, fs().dir("ddd").file("xxx.txt", "first2"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(secondFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
change(fooFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
delete(fooFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
delete(secondFile);
|
||||
buildAllAndAssertUpToDate();
|
||||
}
|
||||
|
||||
public void testDeleteOverwritingFiles() {
|
||||
final String firstFile = createFile("d1/xxx.txt", "1");
|
||||
final String secondFile = createFile("d2/xxx.txt", "2");
|
||||
final Artifact a = addArtifact("a",
|
||||
root().dir("ddd").fileCopy(firstFile).fileCopy(secondFile).fileCopy(createFile("y.txt"))
|
||||
);
|
||||
buildAll();
|
||||
assertOutput(a, fs().dir("ddd").file("xxx.txt", "1").file("y.txt"));
|
||||
|
||||
delete(firstFile);
|
||||
buildAll();
|
||||
assertDeletedAndCopied("out/artifacts/a/ddd/xxx.txt", "d2/xxx.txt");
|
||||
assertOutput(a, fs().dir("ddd").file("xxx.txt", "2").file("y.txt"));
|
||||
buildAllAndAssertUpToDate();
|
||||
|
||||
delete(secondFile);
|
||||
buildAll();
|
||||
assertDeleted("out/artifacts/a/ddd/xxx.txt");
|
||||
assertOutput(a, fs().dir("ddd").file("y.txt"));
|
||||
}
|
||||
}
|
||||
-63
@@ -131,51 +131,6 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase {
|
||||
);
|
||||
}
|
||||
|
||||
public void testOverwriteArchives() {
|
||||
final Artifact included = addArtifact("included",
|
||||
root().archive("x.jar").fileCopy(createFile("aaa.class")));
|
||||
final Artifact a = addArtifact(
|
||||
root()
|
||||
.artifact(included)
|
||||
.archive("x.jar")
|
||||
.fileCopy(createFile("bbb.class")));
|
||||
buildAll();
|
||||
assertOutput(a, fs()
|
||||
.archive("x.jar")
|
||||
.file("aaa.class")
|
||||
);
|
||||
}
|
||||
|
||||
public void testOverwriteNestedArchive() {
|
||||
final Artifact included = addArtifact("included", root().archive("a.jar").archive("b.jar").fileCopy(createFile("c.class")));
|
||||
final Artifact a = addArtifact(
|
||||
root()
|
||||
.artifact(included)
|
||||
.archive("a.jar").archive("d.jar").fileCopy(createFile("e.class")));
|
||||
buildAll();
|
||||
assertOutput(a, fs().archive("a.jar").archive("b.jar").file("c.class"));
|
||||
}
|
||||
|
||||
public void testOverwriteFileByArchive() {
|
||||
final Library library = addProjectLibrary("lib", getJUnitJarPath());
|
||||
Artifact included = addArtifact("included", root().archive("junit.jar").fileCopy(createFile("x.class")));
|
||||
Artifact a = addArtifact(root()
|
||||
.artifact(included)
|
||||
.lib(library));
|
||||
buildAll();
|
||||
assertOutput(a, fs().archive("junit.jar").file("x.class"));
|
||||
}
|
||||
|
||||
//todo[nik] fix ordering
|
||||
public void _testOverwriteArchiveByFile() {
|
||||
Artifact included = addArtifact("included", root().archive("jdom.jar").fileCopy(createFile("x.class")));
|
||||
Artifact a = addArtifact(root()
|
||||
.fileCopy(createFile("jdom.jar", "123"))
|
||||
.artifact(included));
|
||||
buildAll();
|
||||
assertOutput(a, fs().file("jdom.jar", "123"));
|
||||
}
|
||||
|
||||
public void testCopyLibrary() {
|
||||
final Library library = addProjectLibrary("lib", getJUnitJarPath());
|
||||
final Artifact a = addArtifact(root().lib(library));
|
||||
@@ -183,24 +138,6 @@ public class ArtifactBuilderTest extends ArtifactBuilderTestCase {
|
||||
assertOutput(a, fs().file("junit.jar"));
|
||||
}
|
||||
|
||||
//todo[nik] fix ordering
|
||||
public void _testFileOrder() {
|
||||
final Artifact a1 = addArtifact("included1",
|
||||
root().dir("ddd").fileCopy(createFile("d1/xxx.txt", "first")));
|
||||
final Artifact a2 = addArtifact("included2",
|
||||
root().dir("ddd").fileCopy(createFile("d2/xxx.txt", "second")));
|
||||
final Artifact a = addArtifact(
|
||||
root()
|
||||
.artifact(a1)
|
||||
.dir("ddd")
|
||||
.fileCopy(createFile("d3/xxx.txt", "foo"))
|
||||
.end()
|
||||
.artifact(a2)
|
||||
);
|
||||
buildAll();
|
||||
assertOutput(a, fs().dir("ddd").file("xxx.txt", "first"));
|
||||
}
|
||||
|
||||
public void testModuleOutput() {
|
||||
final String file = createFile("src/A.java", "public class A {}");
|
||||
final Module module = addModule("a", PathUtil.getParentPath(file));
|
||||
|
||||
+2
-1
@@ -262,7 +262,8 @@ public abstract class ArtifactBuilderTestCase extends UsefulTestCase {
|
||||
}
|
||||
|
||||
protected void assertUpToDate() {
|
||||
assertCopied();
|
||||
assertEmpty(myArtifactBuilderLogger.myDeletedFilePaths);
|
||||
assertEmpty(myArtifactBuilderLogger.myCopiedFilePaths);
|
||||
}
|
||||
|
||||
private String getProjectRelativePath(String path) {
|
||||
|
||||
Reference in New Issue
Block a user