diff --git a/build/build.iml b/build/build.iml index d1dd857397f0..8c1854cb3e68 100644 --- a/build/build.iml +++ b/build/build.iml @@ -4,6 +4,7 @@ + diff --git a/build/lib/NsiFiles.jar b/build/lib/NsiFiles.jar new file mode 100644 index 000000000000..1c51e070d67f Binary files /dev/null and b/build/lib/NsiFiles.jar differ diff --git a/build/src/com/intellij/internalUtilities/ant/NsiFiles.java b/build/src/com/intellij/internalUtilities/ant/NsiFiles.java new file mode 100644 index 000000000000..b19062870eb1 --- /dev/null +++ b/build/src/com/intellij/internalUtilities/ant/NsiFiles.java @@ -0,0 +1,198 @@ +package com.intellij.internalUtilities.ant; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.taskdefs.MatchingTask; +import org.apache.tools.ant.types.FileSet; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.*; + +/** + * Ant task to facilitate building NSIS installer. + * + * @author max + * @since Jan 11, 2005 + */ +@SuppressWarnings("UnusedDeclaration") +public class NsiFiles extends MatchingTask { + private File myInstFile; + private File myUnInstFile; + private File myBaseDir; + private final List myFileSets = new ArrayList(); + private final Map> myDirToFiles = new LinkedHashMap>(); + private final Map myAbsoluteToRelative = new HashMap(); + + /** + * The file to create; required + * @param nsiFile new file to generate file install list to. + */ + public void setInstFile(File nsiFile) { + myInstFile = nsiFile; + } + + /** + * The file to create; required + * @param nsiFile new file to generate file uninstall list to. + */ + public void setUninstFile(File nsiFile) { + myUnInstFile = nsiFile; + } + + /** + * ;optional + * @param fileSet to be included in processing + */ + public void addFileSet(FileSet fileSet) { + myFileSets.add(fileSet); + } + + /** + * ;optional + * @param baseDir of the files to be processed. + */ + public void setBaseDir(File baseDir) { + myBaseDir = baseDir; + } + + public void execute() throws BuildException { + if (myInstFile == null) throw new BuildException("Specify required isntFile attribute."); + if (myUnInstFile == null) throw new BuildException("Specify required unisntFile attribute."); + + if (myBaseDir == null && myFileSets.size() == 0) { + throw new BuildException("basedir attribute must be set, " + + "or at least " + + "one fileset must be given!"); + } + + try { + if (myBaseDir != null) { + FileSet fs = (FileSet) getImplicitFileSet().clone(); + fs.setDir(myBaseDir); + processFileSet(fs); + } + + for (FileSet fileSet : myFileSets) { + processFileSet(fileSet); + } + + generateInstFile(); + generateUninstFile(); + } + catch (IOException e) { + throw new BuildException(e); + } + finally { + cleanup(); + } + } + + private void generateUninstFile() throws IOException { + BufferedWriter uninstWriter = new BufferedWriter(new FileWriter(myUnInstFile)); + try { + List allFiles = new ArrayList(); + final Collection> lists = myDirToFiles.values(); + for (final List list : lists) { + allFiles.addAll(list); + } + + Collections.sort(allFiles); + for (String file : allFiles) { + uninstWriter.newLine(); + final String relPath = myAbsoluteToRelative.get(file); + uninstWriter.write("Delete \"$INSTDIR\\" + relPath + "\""); + if (relPath.endsWith(".py")) { + uninstWriter.newLine(); + uninstWriter.write("Delete \"$INSTDIR\\" + relPath + "c\""); // .pyc + } + } + + uninstWriter.newLine(); + List dirs = new ArrayList(myDirToFiles.keySet()); + Collections.sort(dirs); + for (int i = dirs.size() - 1; i >= 0; i--) { + final String dir = dirs.get(i); + if (dir.length() == 0) continue; + uninstWriter.newLine(); + uninstWriter.write("RmDir /r \"$INSTDIR\\" + dir + "\\__pycache__\""); + uninstWriter.newLine(); + uninstWriter.write("RmDir \"$INSTDIR\\" + dir + "\""); + } + uninstWriter.newLine(); + uninstWriter.write("RmDir \"$INSTDIR\""); + } + finally{ + uninstWriter.close(); + } + } + + private void generateInstFile() throws IOException { + BufferedWriter instWriter = new BufferedWriter(new FileWriter(myInstFile)); + try { + Collection dirs = myDirToFiles.keySet(); + for (String dir : dirs) { + final List files = myDirToFiles.get(dir); + if (files.size() == 0) continue; + instWriter.newLine(); + instWriter.newLine(); + if (dir.length() > 0) { + instWriter.write("SetOutPath $INSTDIR\\" + dir); + } + else { + instWriter.write("SetOutPath $INSTDIR"); + } + + for (String file : files) { + instWriter.newLine(); + instWriter.write("File \"" + file + "\""); + } + } + } + finally { + instWriter.close(); + } + } + + private void processFileSet(final FileSet fileSet) throws IOException { + final DirectoryScanner scanner = fileSet.getDirectoryScanner(getProject()); + final String[] files = scanner.getIncludedFiles(); + String base = fileSet.getDir(getProject()).getCanonicalPath() + "\\"; + for (String file : files) { + String lastDir = ""; + getDirFileList(lastDir); + int idx = -1; + do { + idx = file.indexOf('\\', idx + 1); + if (idx == -1) break; + lastDir = file.substring(0, idx); + getDirFileList(lastDir); + } + while (true); + + List fileList = getDirFileList(lastDir); + final String absolute = base + file; + fileList.add(absolute); + myAbsoluteToRelative.put(absolute, file); + } + } + + private List getDirFileList(final String dir) { + List fileList = myDirToFiles.get(dir); + if (fileList == null) { + fileList = new ArrayList(); + myDirToFiles.put(dir, fileList); + } + return fileList; + } + + private void cleanup() { + myBaseDir = null; + myInstFile = null; + myFileSets.clear(); + myDirToFiles.clear(); + myAbsoluteToRelative.clear(); + } +}