diff --git a/build/groovy/org/jetbrains/intellij/build/impl/NsisFileListGenerator.groovy b/build/groovy/org/jetbrains/intellij/build/impl/NsisFileListGenerator.groovy new file mode 100644 index 000000000000..5d14a9d3b5b9 --- /dev/null +++ b/build/groovy/org/jetbrains/intellij/build/impl/NsisFileListGenerator.groovy @@ -0,0 +1,113 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.intellij.build.impl + +import com.intellij.openapi.util.io.FileUtil + +import java.util.regex.Pattern +/** + * @author nik + */ +class NsisFileListGenerator { + private final Map> directoryToFiles = [:] + private final List filesRelativePaths = [] + + public void addDirectory(String directoryPath, List relativeFileExcludePatterns = []) { + def excludePatterns = relativeFileExcludePatterns.collect { Pattern.compile(FileUtil.convertAntToRegexp(it)) } + processDirectory(new File(directoryPath), "", excludePatterns) + } + + public void generateInstallerFile(File outputFile) { + outputFile.withWriter { BufferedWriter out -> + directoryToFiles.each { + if (!it.value.empty) { + out.newLine() + out.writeLine("SetOutPath \$INSTDIR${it.key.isEmpty() ? "" : "\\"}${toWinPath(it.key)}") + + it.value.each { + out.writeLine("File \"${it.absolutePath}\"") + } + } + } + } + } + + public void generateUninstallerFile(File outputFile) { + outputFile.withWriter { BufferedWriter out -> + filesRelativePaths.toSorted().each { + out.writeLine("Delete \"\$INSTDIR\\${toWinPath(it)}\"") + if (it.endsWith(".py")) { + out.writeLine("Delete \"\$INSTDIR\\${toWinPath(it)}c\"") //.pyc + } + } + + out.newLine() + + directoryToFiles.keySet().toSorted().reverseEach { + if (!it.empty) { + out.writeLine("RmDir /r \"\$INSTDIR\\${toWinPath(it)}\\__pycache__\""); + out.writeLine("RmDir \"\$INSTDIR\\${toWinPath(it)}\""); + } + } + out.writeLine("RmDir \"\$INSTDIR\"") + } + } + + private static String toWinPath(String dir) { + return dir.replace('/', '\\'); + } + + + private void processDirectory(File directory, String relativePath, List excludePatterns) { + def files = directory.listFiles() + if (files == null) { + throw new IOException("Not a directory: $directory") + } + files.sort { it.name } + for (child in files) { + String childPath = "${(relativePath.isEmpty() ? "" : "$relativePath/")}$child.name" + if (excludePatterns.any { it.matcher(childPath).matches() }) { + continue + } + if (child.isFile()) { + filesRelativePaths << childPath + directoryToFiles.get(relativePath, []) << child + } + else { + processDirectory(child, childPath, excludePatterns) + if (directoryToFiles.containsKey(childPath)) { + //register all parent directories for directories with files to ensure that they will be deleted by uninstaller + directoryToFiles.putIfAbsent(relativePath, []) + } + } + } + } +} \ No newline at end of file diff --git a/build/groovy/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.groovy b/build/groovy/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.groovy index 8167b4de9272..95f0c1643148 100644 --- a/build/groovy/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.groovy +++ b/build/groovy/org/jetbrains/intellij/build/impl/WinExeInstallerBuilder.groovy @@ -43,7 +43,6 @@ class WinExeInstallerBuilder { String communityHome = buildContext.paths.communityHome String outFileName = buildContext.productProperties.baseArtifactName(buildContext.buildNumber) buildContext.messages.progress("Building Windows installer $outFileName") - ant.taskdef(name: "nsis", classname: "com.intellij.internalUtilities.ant.NsiFiles", classpath: "$communityHome/build/lib/NsiFiles.jar") def box = "$buildContext.paths.temp/winInstaller" ant.mkdir(dir: "$box/bin") @@ -56,28 +55,26 @@ class WinExeInstallerBuilder { } ant.copy(todir: "$box/nsiconf") { - fileset(dir: "$communityHome/build/conf/nsis") { - include(name: "*") - exclude(name: "strings*") - exclude(name: "paths*") - exclude(name: "version*") - } + fileset(dir: "$communityHome/build/conf/nsis") } if (SystemInfoRt.isLinux) { File ideaNsiPath = new File(box, "nsiconf/idea.nsi") ideaNsiPath.text = BuildUtils.replaceAll(ideaNsiPath.text, ["\${IMAGES_LOCATION}\\": "\${IMAGES_LOCATION}/"], "") } - ant.nsis(instfile: "$box/nsiconf/idea_win.nsh", uninstfile: "$box/nsiconf/unidea_win.nsh") { - [buildContext.paths.distAll, winDistPath].each { - ant.fileset(dir: it, includes: "**/*") { - exclude(name: "**/idea.properties") - exclude(name: "**/*.vmoptions") - } - } + try { + def generator = new NsisFileListGenerator() + generator.addDirectory(buildContext.paths.distAll) + generator.addDirectory(winDistPath, ["**/idea.properties", "**/*.vmoptions"]) + if (bundleJre) { - ant.fileset(dir: jreDirectoryPath, includes: "jre/**/*") + generator.addDirectory(jreDirectoryPath) } + generator.generateInstallerFile(new File(box, "nsiconf/idea_win.nsh")) + generator.generateUninstallerFile(new File(box, "nsiconf/unidea_win.nsh")) + } + catch (IOException e) { + buildContext.messages.error("Failed to generated list of files for NSIS installer: $e") } prepareConfigurationFiles(box, winDistPath)