| /* | |
| * Copyright 2000-2014 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. | |
| */ | |
| import org.jetbrains.jps.gant.JpsGantTool | |
| import org.jetbrains.jps.gant.TeamCityBuildInfoPrinter | |
| import org.jetbrains.jps.model.java.JavaSourceRootType | |
| import org.jetbrains.jps.model.module.JpsModule | |
| includeTool << JpsGantTool | |
| binding.setVariable("p", {String key -> | |
| return getProperty(key) as String | |
| }) | |
| binding.setVariable("guessJdk", { | |
| String javaHome = p("java.home") | |
| if (new File(javaHome).getName() == "jre") { | |
| javaHome = new File(javaHome).getParent() | |
| } | |
| return javaHome | |
| }) | |
| binding.setVariable("includeFile", {String filePath -> | |
| Script s = groovyShell.parse(new File(filePath)) | |
| s.setBinding(binding) | |
| s | |
| }) | |
| binding.setVariable("isMac", { | |
| return System.getProperty("os.name").toLowerCase().startsWith("mac") | |
| }) | |
| binding.setVariable("isWin", { | |
| return System.getProperty("os.name").toLowerCase().startsWith("windows") | |
| }) | |
| binding.setVariable("isEap", { | |
| return "true" == p("component.version.eap") | |
| }) | |
| binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=64m") | |
| binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=96m") | |
| binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " + | |
| "-Didea.project.structure.max.errors.to.show=0 " + | |
| "-XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50") | |
| binding.setVariable("vmOptions", { "$common_vmoptions ${isEap() ? '-XX:+HeapDumpOnOutOfMemoryError' : ''}".trim() }) | |
| binding.setVariable("vmOptions32", { "$mem32 ${vmOptions()}".trim() }) | |
| binding.setVariable("vmOptions64", { "$mem64 ${vmOptions()}".trim() }) | |
| binding.setVariable("yjpOptions", { String systemSelector, String platformSuffix = "" -> | |
| "-agentlib:yjpagent$platformSuffix=disablej2ee,disablealloc,disabletracing,onlylocal,builtinprobes=none,disableexceptiontelemetry,delay=10000,sessionname=$systemSelector".trim() | |
| }) | |
| binding.setVariable("vmOptions32yjp", { String systemSelector -> | |
| "${vmOptions32()} ${yjpOptions(systemSelector)}".trim() | |
| }) | |
| binding.setVariable("vmOptions64yjp", { String systemSelector -> | |
| "${vmOptions64()} ${yjpOptions(systemSelector, "64")}".trim() | |
| }) | |
| binding.setVariable("isDefined", {String key -> | |
| try { | |
| this[key] | |
| return true | |
| } | |
| catch (MissingPropertyException ignored) { | |
| return false | |
| } | |
| }) | |
| private String require(String key) { | |
| try { | |
| this[key] | |
| } | |
| catch (MissingPropertyException ignored) { | |
| projectBuilder.error("Property $key is required") | |
| } | |
| } | |
| private String require(String key, String defaultValue) { | |
| try { | |
| this[key] | |
| } | |
| catch (MissingPropertyException ignored) { | |
| projectBuilder.info("$key is not defined. Defaulting to $defaultValue") | |
| this[key] = defaultValue | |
| } | |
| } | |
| binding.setVariable("requireProperty", {String key, String defaultValue = null -> | |
| if (defaultValue == null) { | |
| require(key) | |
| } | |
| else { | |
| require(key, defaultValue) | |
| } | |
| }) | |
| binding.setVariable("guessHome", { | |
| // Current file is supposed to be at build/scripts/release.gant path | |
| new File(requireProperty("gant.file").substring("file:".length())).getParentFile().getParentFile().getParent() | |
| }) | |
| binding.setVariable("loadProject", { | |
| requireProperty("jdkHome", guessJdk()) | |
| def mac = isMac() | |
| jdk("IDEA jdk", jdkHome) { | |
| if (!mac) { | |
| classpath "$jdkHome/lib/tools.jar" | |
| } | |
| } | |
| projectBuilder.dataStorageRoot = new File("$home/.jps-build-data") | |
| loadProjectFromPath(home) | |
| }) | |
| boolean hasSourceRoots(JpsModule module) { | |
| return module.getSourceRoots(JavaSourceRootType.SOURCE).iterator().hasNext() | |
| } | |
| binding.setVariable("findModule", {String name -> | |
| project.modules.find { it.name == name } | |
| }) | |
| binding.setVariable("allModules", { | |
| return project.modules | |
| }) | |
| binding.setVariable("printUnusedModules", {Set<String> usedModules -> | |
| allModules().each {JpsModule m -> | |
| if (!usedModules.contains(m.name) && hasSourceRoots(m)) { | |
| projectBuilder.warning("Module $m.name is not used in project layout") | |
| } | |
| } | |
| }) | |
| requireProperty("home", guessHome()) | |
| String readSnapshotBuild() { | |
| def file = new File("$home/community/build.txt") | |
| if (!file.exists()) { | |
| file = new File("$home/build.txt") | |
| } | |
| return file.readLines().get(0) | |
| } | |
| binding.setVariable("snapshot", readSnapshotBuild()) | |
| projectBuilder.buildInfoPrinter = new TeamCityBuildInfoPrinter() | |
| projectBuilder.compressJars = false | |
| binding.setVariable("notifyArtifactBuilt", { String artifactPath -> | |
| if (!artifactPath.startsWith(home)) { | |
| // AndroidStudio: make this to be just an info as the out folder is typically | |
| // not in the home folder | |
| projectBuilder.info("Artifact path $artifactPath should start with $home") | |
| return | |
| } | |
| def relativePath = artifactPath.substring(home.length()) | |
| if (relativePath.startsWith("/")) { | |
| relativePath = relativePath.substring(1) | |
| } | |
| def file = new File(artifactPath) | |
| if (file.isDirectory()) { | |
| relativePath += "=>" + file.name | |
| } | |
| projectBuilder.info("##teamcity[publishArtifacts '$relativePath']") | |
| }) | |
| def suspendUntilDebuggerConnect = System.getProperty("debug.suspend") ?: "n" | |
| def debugPort = System.getProperty("debug.port") ?: 5555 | |
| if (suspendUntilDebuggerConnect == 'y') { | |
| println """\ | |
| ------------->----------- This process is suspended until remote debugger connects to the port $debugPort ----<---- | |
| -------------------------------------------^------^------^------^------^------^------^----------------------- | |
| """ | |
| } | |
| binding.setVariable("patchFiles", { List files, Map args, String marker = "__" -> | |
| files.each { file -> | |
| args.each { arg -> | |
| ant.replace(file: file, token: "${marker}${arg.key}${marker}", value: arg.value) | |
| } | |
| } | |
| }) | |
| binding.setVariable("copyAndPatchFile", { String file, String target, Map args, String marker = "__" -> | |
| ant.copy(file: file, tofile: target, overwrite: "true") { | |
| filterset(begintoken: marker, endtoken: marker) { | |
| args.each { | |
| filter(token: it.key, value: it.value) | |
| } | |
| } | |
| } | |
| }) | |
| binding.setVariable("copyAndPatchFiles", { Closure files, String target, Map args, String marker = "__" -> | |
| ant.copy(todir: target, overwrite: "true") { | |
| files() | |
| filterset(begintoken: marker, endtoken: marker) { | |
| args.each { | |
| filter(token: it.key, value: it.value) | |
| } | |
| } | |
| } | |
| }) | |
| binding.setVariable("wireBuildDate", { String buildNumber, String appInfoFile -> | |
| ant.tstamp() | |
| patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP, | |
| "PACKAGE_CODE": buildNumber.substring(0, buildNumber.indexOf('-'))]) | |
| }) | |
| binding.setVariable("commonJvmArgs", { | |
| return [ | |
| "-ea", | |
| "-Didea.home.path=$home", | |
| "-Xbootclasspath/p:${projectBuilder.moduleOutput(findModule("boot"))}", | |
| "-XX:+HeapDumpOnOutOfMemoryError", | |
| "-Didea.system.path=${p("teamcity.build.tempDir")}/system", | |
| "-Didea.config.path=${p("teamcity.build.tempDir")}/config", | |
| "-Xdebug", | |
| "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"] | |
| }) | |
| binding.setVariable("classPathLibs", [ | |
| "bootstrap.jar", | |
| "extensions.jar", | |
| "util.jar", | |
| "jdom.jar", | |
| "log4j.jar", | |
| "trove4j.jar", | |
| "jna.jar" | |
| ]) | |
| binding.setVariable("platformApiModules", [ | |
| "analysis-api", | |
| "core-api", | |
| "editor-ui-api", | |
| "external-system-api", | |
| "indexing-api", | |
| "jps-model-api", | |
| "lang-api", | |
| "lvcs-api", | |
| "projectModel-api", | |
| "platform-api", | |
| "structure-view-api", | |
| "usageView", | |
| "vcs-api", | |
| "vcs-log-api", | |
| "xdebugger-api", | |
| "xml-analysis-api", | |
| "xml-openapi", | |
| "xml-psi-api", | |
| "xml-structure-view-api", | |
| ]) | |
| binding.setVariable("platformImplementationModules", [ | |
| "analysis-impl", | |
| "core-impl", | |
| "dvcs", | |
| "editor-ui-ex", | |
| "images", | |
| "indexing-impl", | |
| "jps-model-impl", | |
| "jps-model-serialization", | |
| "lang-impl", | |
| "lvcs-impl", | |
| "projectModel-impl", | |
| "platform-impl", | |
| "structure-view-impl", | |
| "vcs-impl", | |
| "vcs-log-graph", | |
| "vcs-log-impl", | |
| "testRunner", | |
| "smRunner", | |
| "relaxng", | |
| "RegExpSupport", | |
| "spellchecker", | |
| "xdebugger-impl", | |
| "xml", | |
| "xml-analysis-impl", | |
| "xml-psi-impl", | |
| "xml-structure-view-impl", | |
| ]) | |
| binding.setVariable("layoutMacApp", { String path, String ch, Map args -> | |
| ant.copy(todir: "$path/bin") { | |
| fileset(dir: "$ch/bin/mac") | |
| } | |
| ant.copy(todir: path) { | |
| fileset(dir: "$ch/build/conf/mac") | |
| } | |
| ant.tstamp() { | |
| format(property: "todayYear", pattern: "yyyy") | |
| } | |
| String executable = args.executable != null ? args.executable : p("component.names.product").toLowerCase() | |
| String helpId = args.help_id != null ? args.help_id : "IJ" | |
| String icns = "idea.icns" | |
| String helpIcns = "$path/Contents/Resources/${helpId}.help/Contents/Resources/Shared/product.icns" | |
| if (args.icns != null) { | |
| ant.delete(file: "$path/Contents/Resources/idea.icns") | |
| ant.copy(file: args.icns, todir: "$path/Contents/Resources") | |
| ant.copy(file: args.icns, tofile: helpIcns) | |
| icns = new File((String)args.icns).getName(); | |
| } else { | |
| ant.copy(file: "$path/Contents/Resources/idea.icns", tofile: helpIcns) | |
| } | |
| String fullName = args.fullName != null ? args.fullName : p("component.names.fullname") | |
| String vmOptions = "-Dfile.encoding=UTF-8 ${vmOptions()} -Xverify:none" | |
| if (isEap() && !args.mac_no_yjp) { | |
| vmOptions += " ${yjpOptions(args.system_selector)}" | |
| } | |
| String minor = p("component.version.minor") | |
| String version = isEap() && !minor.contains("RC") && !minor.contains("Beta") ? "EAP $args.buildNumber" : "${p("component.version.major")}.${minor}" | |
| Map properties = readIdeaProperties(args) | |
| def coreKeys = ["idea.platform.prefix", "idea.paths.selector"] | |
| String coreProperties = submapToXml(properties, coreKeys); | |
| StringBuilder effectiveProperties = new StringBuilder() | |
| properties.each { k, v -> | |
| if (!coreKeys.contains(k)) { | |
| effectiveProperties.append("$k=$v\n"); | |
| } | |
| } | |
| new File("$path/bin/idea.properties").text = effectiveProperties.toString() | |
| new File("$path/bin/idea.vmoptions").text = "$mem64 -XX:+UseCompressedOops".split(" ").join("\n") | |
| String classPath = classPathLibs.collect {"\$APP_PACKAGE/lib/${it}" }.join(":") | |
| String archs = """ | |
| <key>LSArchitecturePriority</key> | |
| <array>""" | |
| (args.archs != null ? args.archs : ["64_x86", "i386"]).each { | |
| archs += "<string>${it}</string>" | |
| } | |
| archs +="</array>\n" | |
| String urlSchemes = "" | |
| if (args.urlSchemes != null) { | |
| urlSchemes += """ | |
| <key>CFBundleURLTypes</key> | |
| <array> | |
| <dict> | |
| <key>CFBundleTypeRole</key> | |
| <string>Editor</string> | |
| <key>CFBundleURLName</key> | |
| <string>Stacktrace</string> | |
| <key>CFBundleURLSchemes</key> | |
| <array> | |
| """ | |
| args.urlSchemes.each { scheme -> | |
| urlSchemes += " <string>${scheme}</string>" | |
| } | |
| urlSchemes += """ | |
| </array> | |
| </dict> | |
| </array> | |
| """ | |
| } | |
| ant.replace(file: "$path/Contents/Info.plist") { | |
| replacefilter(token: "@@build@@", value: args.buildNumber) | |
| replacefilter(token: "@@doc_types@@", value: ifNull(args.doc_types, "")) | |
| replacefilter(token: "@@executable@@", value: executable) | |
| replacefilter(token: "@@icns@@", value: icns) | |
| replacefilter(token: "@@bundle_name@@", value: fullName) | |
| replacefilter(token: "@@bundle_identifier@@", value: args.bundleIdentifier) | |
| replacefilter(token: "@@year@@", value: "$todayYear") | |
| replacefilter(token: "@@company_name@@", value: args.companyName) | |
| replacefilter(token: "@@min_year@@", value: "2013") | |
| replacefilter(token: "@@max_year@@", value: "$todayYear") | |
| replacefilter(token: "@@version@@", value: version) | |
| replacefilter(token: "@@vmoptions@@", value: vmOptions) | |
| replacefilter(token: "@@idea_properties@@", value: coreProperties) | |
| replacefilter(token: "@@class_path@@", value: classPath) | |
| replacefilter(token: "@@help_id@@", value: helpId) | |
| replacefilter(token: "@@url_schemes@@", value: urlSchemes) | |
| replacefilter(token: "@@archs@@", value: archs) | |
| } | |
| if (executable != "idea") { | |
| ant.move(file: "$path/Contents/MacOS/idea", tofile: "$path/Contents/MacOS/$executable") | |
| } | |
| ant.replace(file: "$path/bin/inspect.sh") { | |
| replacefilter(token: "@@product_full@@", value: fullName) | |
| replacefilter(token: "@@script_name@@", value: executable) | |
| } | |
| if (args.inspect_script != null && args.inspect_script != "inspect") { | |
| ant.move(file: "$path/bin/inspect.sh", tofile: "$path/bin/${args.inspect_script}.sh") | |
| } | |
| ant.fixcrlf(srcdir: "$path/bin", includes: "*.sh", eol: "unix") | |
| }) | |
| binding.setVariable("winScripts", { String target, String home, String name, Map args -> | |
| String fullName = args.fullName != null ? args.fullName : p("component.names.fullname") | |
| String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase().replace(" ", "_") | |
| String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase().replace(" ", "-")}.exe" | |
| if (vm_options.endsWith(".exe")) { | |
| vm_options = vm_options.replace(".exe", "%BITS%.exe") | |
| } | |
| else { | |
| vm_options = vm_options + "%BITS%" | |
| } | |
| String classPath = "SET CLASS_PATH=%IDE_HOME%\\lib\\${classPathLibs[0]}\n" | |
| classPath += classPathLibs[1..-1].collect {"SET CLASS_PATH=%CLASS_PATH%;%IDE_HOME%\\lib\\${it}"}.join("\n") | |
| if (args.tools_jar) classPath += "\nSET CLASS_PATH=%CLASS_PATH%;%JDK%\\lib\\tools.jar" | |
| ant.copy(todir: "$target/bin") { | |
| fileset(dir: "$home/bin/scripts/win") | |
| filterset(begintoken: "@@", endtoken: "@@") { | |
| filter(token: "product_full", value: fullName) | |
| filter(token: "product_uc", value: product_uc) | |
| filter(token: "vm_options", value: vm_options) | |
| filter(token: "isEap", value: isEap()) | |
| filter(token: "system_selector", value: args.system_selector) | |
| filter(token: "ide_jvm_args", value: ifNull(args.ide_jvm_args, "")) | |
| filter(token: "class_path", value: classPath) | |
| filter(token: "script_name", value: name) | |
| } | |
| } | |
| if (name != "idea.bat") { | |
| ant.move(file: "$target/bin/idea.bat", tofile: "$target/bin/$name") | |
| } | |
| if (args.inspect_script != null && args.inspect_script != "inspect") { | |
| ant.move(file: "$target/bin/inspect.bat", tofile: "$target/bin/${args.inspect_script}.bat") | |
| } | |
| ant.fixcrlf(srcdir: "$target/bin", includes: "*.bat", eol: "dos") | |
| }) | |
| private ifNull(v, defVal) { v != null ? v : defVal } | |
| binding.setVariable("unixScripts", { String target, String home, String name, Map args -> | |
| String fullName = args.fullName != null ? args.fullName : p("component.names.fullname") | |
| String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase() | |
| String vm_options = args.vm_options != null ? args.vm_options : p("component.names.product").toLowerCase() | |
| String classPath = "CLASSPATH=\"\$IDE_HOME/lib/${classPathLibs[0]}\"\n" | |
| classPath += classPathLibs[1..-1].collect {"CLASSPATH=\"\$CLASSPATH:\$IDE_HOME/lib/${it}\""}.join("\n") | |
| if (args.tools_jar) classPath += "\nCLASSPATH=\"\$CLASSPATH:\$JDK/lib/tools.jar\"" | |
| ant.copy(todir: "$target/bin") { | |
| fileset(dir: "$home/bin/scripts/unix") | |
| filterset(begintoken: "@@", endtoken: "@@") { | |
| filter(token: "product_full", value: fullName) | |
| filter(token: "product_uc", value: product_uc) | |
| filter(token: "vm_options", value: vm_options) | |
| filter(token: "isEap", value: isEap()) | |
| filter(token: "system_selector", value: args.system_selector) | |
| filter(token: "ide_jvm_args", value: ifNull(args.ide_jvm_args, "")) | |
| filter(token: "class_path", value: classPath) | |
| filter(token: "script_name", value: name) | |
| } | |
| } | |
| if (name != "idea.sh") { | |
| ant.move(file: "$target/bin/idea.sh", tofile: "$target/bin/$name") | |
| } | |
| if (args.inspect_script != null && args.inspect_script != "inspect") { | |
| ant.move(file: "$target/bin/inspect.sh", tofile: "$target/bin/${args.inspect_script}.sh") | |
| } | |
| ant.fixcrlf(srcdir: "$target/bin", includes: "*.sh", eol: "unix") | |
| }) | |
| binding.setVariable("winVMOptions", { String target, Map args, String name, String name64 = null -> | |
| if (name != null) { | |
| def options = vmOptions32() | |
| options = options.replace(" -XX:+UseCodeCacheFlushing", "") | |
| options += " -Didea.platform.prefix=" + args.platform_prefix | |
| options += " -Didea.paths.selector=" + args.system_selector | |
| ant.echo(file: "$target/bin/${name}.vmoptions", message: options.replace(' ', '\n')) | |
| } | |
| if (name64 != null) { | |
| def options = vmOptions64() | |
| options += " -Didea.platform.prefix=" + args.platform_prefix | |
| options += " -Didea.paths.selector=" + args.system_selector | |
| ant.echo(file: "$target/bin/${name64}.vmoptions", message: options.replace(' ', '\n')) | |
| } | |
| ant.fixcrlf(srcdir: "$target/bin", includes: "*.vmoptions", eol: "dos") | |
| }) | |
| binding.setVariable("unixVMOptions", { String target, String name, String name64 = (name + "64") -> | |
| if (name != null) { | |
| ant.echo(file: "$target/bin/${name}.vmoptions", message: "${vmOptions32()} -Dawt.useSystemAAFontSettings=lcd".trim().replace(' ', '\n')) | |
| } | |
| if (name64 != null) { | |
| ant.echo(file: "$target/bin/${name64}.vmoptions", message: "${vmOptions64()} -Dawt.useSystemAAFontSettings=lcd".trim().replace(' ', '\n')) | |
| } | |
| ant.fixcrlf(srcdir: "$target/bin", includes: "*.vmoptions", eol: "unix") | |
| }) | |
| binding.setVariable("unixReadme", { String target, String home, Map args -> | |
| String fullName = args.fullName != null ? args.fullName : p("component.names.fullname") | |
| String settings_dir = args.system_selector.replaceFirst("\\d+", "") | |
| copyAndPatchFile("$home/build/Install-Linux-tar.txt", "$target/Install-Linux-tar.txt", | |
| ["product_full": fullName, | |
| "product": p("component.names.product").toLowerCase(), | |
| "system_selector": args.system_selector, | |
| "script_name" : args.script_name, | |
| "settings_dir": settings_dir], "@@") | |
| ant.fixcrlf(file: "$target/bin/Install-Linux-tar.txt", eol: "unix") | |
| }) | |
| binding.setVariable("forceDelete", { String dirPath -> | |
| // if wasn't deleted - retry several times | |
| attempt = 1 | |
| while (attempt < 21 && (new File(dirPath).exists())) { | |
| if (attempt > 1) { | |
| ant.echo "Deleting $dirPath ... (attempt=$attempt)" | |
| // let's wait a bit and try again - may be help | |
| // in some cases on our windows 7 agents | |
| sleep(2000) | |
| } | |
| ant.delete(failonerror: false, dir: dirPath) | |
| attempt++ | |
| } | |
| if (new File(dirPath).exists()) { | |
| ant.project.log ("Cannot delete directory: $dirPath" ) | |
| System.exit (1) | |
| } | |
| }) | |
| binding.setVariable("patchPropertiesFile", { String target, Map args = [:] -> | |
| String file = "$target/bin/idea.properties" | |
| if (args.appendices != null) { | |
| ant.concat(destfile: file, append: true) { | |
| args.appendices.each { | |
| fileset(file: it) | |
| } | |
| } | |
| } | |
| String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase() | |
| String settings_dir = args.system_selector.replaceFirst("\\d+", "") | |
| ant.replace(file: file) { | |
| replacefilter(token: "@@product_uc@@", value: product_uc) | |
| replacefilter(token: "@@settings_dir@@", value: settings_dir) | |
| } | |
| String message = (isEap() ? """ | |
| #----------------------------------------------------------------------- | |
| # Change to 'disabled' if you don't want to receive instant visual notifications | |
| # about fatal errors that happen to an IDE or plugins installed. | |
| #----------------------------------------------------------------------- | |
| idea.fatal.error.notification=enabled | |
| """ | |
| : """ | |
| #----------------------------------------------------------------------- | |
| # Change to 'enabled' if you want to receive instant visual notifications | |
| # about fatal errors that happen to an IDE or plugins installed. | |
| #----------------------------------------------------------------------- | |
| idea.fatal.error.notification=disabled | |
| """) | |
| ant.echo(file: file, append: true, message: message) | |
| }) | |
| binding.setVariable("zipSources", { String home, String targetDir -> | |
| String sources = "$targetDir/sources.zip" | |
| projectBuilder.stage("zip sources to $sources") | |
| ant.mkdir(dir: targetDir) | |
| ant.delete(file: sources) | |
| ant.zip(destfile: sources) { | |
| fileset(dir: home) { | |
| ["java", "groovy", "ipr", "iml", "form", "xml", "properties"].each { | |
| include(name: "**/*.$it") | |
| } | |
| exclude(name: "**/testData/**") | |
| } | |
| } | |
| notifyArtifactBuilt(sources) | |
| }) | |
| /** | |
| * E.g. | |
| * | |
| * Load all properties from file: | |
| * readIdeaProperties("idea.properties.path" : "$home/ruby/build/idea.properties") | |
| * | |
| * Load all properties except "idea.cycle.buffer.size", change "idea.max.intellisense.filesize" to 3000 | |
| * and enable "idea.is.internal" mode: | |
| * readIdeaProperties("idea.properties.path" : "$home/ruby/build/idea.properties", | |
| * "idea.properties" : ["idea.max.intellisense.filesize" : 3000, | |
| * "idea.cycle.buffer.size" : null, | |
| * "idea.is.internal" : true ]) | |
| * @param args | |
| * @return text xml properties description in xml | |
| */ | |
| private Map readIdeaProperties(Map args) { | |
| String ideaPropertiesPath = args == null ? null : args.get("idea.properties.path") | |
| if (ideaPropertiesPath == null) { | |
| return [:] | |
| } | |
| // read idea.properties file | |
| Properties ideaProperties = new Properties(); | |
| FileInputStream ideaPropertiesFile = new FileInputStream(ideaPropertiesPath); | |
| ideaProperties.load(ideaPropertiesFile); | |
| ideaPropertiesFile.close(); | |
| def defaultProperties = ["CVS_PASSFILE": "~/.cvspass", | |
| "com.apple.mrj.application.live-resize": "false", | |
| "idea.paths.selector": args.system_selector, | |
| "java.endorsed.dirs": "", | |
| "idea.smooth.progress": "false", | |
| "apple.laf.useScreenMenuBar": "true", | |
| "apple.awt.graphics.UseQuartz": "true", | |
| "apple.awt.fullscreencapturealldisplays": "false"] | |
| if (args.platform_prefix != null) { | |
| defaultProperties.put("idea.platform.prefix", args.platform_prefix) | |
| } | |
| Map properties = defaultProperties | |
| def customProperties = args.get("idea.properties") | |
| if (customProperties != null) { | |
| properties += customProperties | |
| } | |
| properties.each {k, v -> | |
| if (v == null) { | |
| // if overridden with null - ignore property | |
| ideaProperties.remove(k) | |
| } else { | |
| // if property is overridden in args map - use new value | |
| ideaProperties.put(k, v) | |
| } | |
| } | |
| return ideaProperties; | |
| } | |
| private String submapToXml(Map properties, List keys) { | |
| // generate properties description for Info.plist | |
| StringBuilder buff = new StringBuilder() | |
| keys.each { key -> | |
| String value = properties[key] | |
| if (value != null) { | |
| String string = | |
| """ | |
| <key>$key</key> | |
| <string>$value</string> | |
| """ | |
| buff.append(string) | |
| } | |
| } | |
| return buff.toString() | |
| } | |
| binding.setVariable("buildWinZip", { String zipRoot, String zipPath, List paths -> | |
| projectBuilder.stage(".win.zip") | |
| fixIdeaPropertiesEol(paths, "dos") | |
| ant.zip(zipfile: zipPath) { | |
| paths.each { | |
| zipfileset(dir: it, prefix: zipRoot) | |
| } | |
| } | |
| notifyArtifactBuilt(zipPath) | |
| }) | |
| binding.setVariable("buildMacZip", { String zipRoot, String zipPath, List paths, String macPath, List extraBins = [] -> | |
| projectBuilder.stage(".mac.zip") | |
| allPaths = paths + [macPath] | |
| ant.zip(zipfile: zipPath) { | |
| allPaths.each { | |
| zipfileset(dir: it, prefix: zipRoot) { | |
| exclude(name: "bin/*.sh") | |
| exclude(name: "bin/*.py") | |
| exclude(name: "bin/fsnotifier") | |
| exclude(name: "bin/restarter") | |
| exclude(name: "Contents/MacOS/*") | |
| extraBins.each { | |
| exclude(name: it) | |
| } | |
| exclude(name: "bin/idea.properties") | |
| } | |
| } | |
| allPaths.each { | |
| zipfileset(dir: it, filemode: "755", prefix: zipRoot) { | |
| include(name: "bin/*.sh") | |
| include(name: "bin/*.py") | |
| include(name: "bin/fsnotifier") | |
| include(name: "bin/restarter") | |
| include(name: "Contents/MacOS/*") | |
| extraBins.each { | |
| include(name: it) | |
| } | |
| } | |
| } | |
| zipfileset(file: "$macPath/bin/idea.properties", prefix: "$zipRoot/bin") | |
| } | |
| }) | |
| binding.setVariable("buildTarGz", { String tarRoot, String tarPath, List paths, List extraBins = [] -> | |
| projectBuilder.stage(".tar.gz") | |
| fixIdeaPropertiesEol(paths, "unix") | |
| ant.tar(tarfile: tarPath, longfile: "gnu") { | |
| paths.each { | |
| tarfileset(dir: it, prefix: tarRoot) { | |
| exclude(name: "bin/*.sh") | |
| exclude(name: "bin/fsnotifier*") | |
| extraBins.each { | |
| exclude(name: it) | |
| } | |
| type(type: "file") | |
| } | |
| } | |
| paths.each { | |
| tarfileset(dir: it, filemode: "755", prefix: tarRoot) { | |
| include(name: "bin/*.sh") | |
| include(name: "bin/fsnotifier*") | |
| extraBins.each { | |
| include(name: it) | |
| } | |
| type(type: "file") | |
| } | |
| } | |
| } | |
| String gzPath = "${tarPath}.gz" | |
| ant.gzip(src: tarPath, zipfile: gzPath) | |
| ant.delete(file: tarPath) | |
| notifyArtifactBuilt(gzPath) | |
| }) | |
| private void fixIdeaPropertiesEol(List paths, String eol) { | |
| paths.each { | |
| String file = "$it/bin/idea.properties" | |
| if (new File(file).exists()) { | |
| ant.fixcrlf(file: file, eol: eol) | |
| } | |
| } | |
| } | |
| binding.setVariable("buildWinLauncher", { String ch, String inputPath, String outputPath, String appInfo, | |
| String launcherProperties, String pathsSelector, List resourcePaths -> | |
| projectBuilder.stage("winLauncher") | |
| if (pathsSelector != null) { | |
| def paths = getProperty("paths") | |
| def launcherPropertiesTemp = "${paths.sandbox}/launcher.properties" | |
| copyAndPatchFile(launcherProperties, launcherPropertiesTemp, ["PRODUCT_PATHS_SELECTOR": pathsSelector]) | |
| launcherProperties = launcherPropertiesTemp | |
| } | |
| ant.java(classname: "com.pme.launcher.LauncherGeneratorMain", fork: "true") { | |
| sysproperty(key: "java.awt.headless", value: "true") | |
| arg(value: inputPath) | |
| arg(value: appInfo) | |
| arg(value: "$ch/native/WinLauncher/WinLauncher/resource.h") | |
| arg(value: launcherProperties) | |
| arg(value: outputPath) | |
| classpath { | |
| pathelement(location: "$ch/build/lib/launcher-generator.jar") | |
| fileset(dir: "$ch/lib") { | |
| include(name: "guava*.jar") | |
| include(name: "jdom.jar") | |
| include(name: "sanselan*.jar") | |
| } | |
| resourcePaths.each { | |
| pathelement(location: it) | |
| } | |
| } | |
| } | |
| }) | |
| binding.setVariable("layoutUpdater", { String target, String jarName = "updater.jar" -> | |
| layout(target) { | |
| jar(jarName) { | |
| module("updater") | |
| } | |
| } | |
| }) | |
| binding.setVariable("collectUsedJars", { List modules, List approvedJars, List forbiddenJars, List modulesToBuild -> | |
| def usedJars = new HashSet(); | |
| modules.each { | |
| def module = findModule(it) | |
| if (module != null) { | |
| projectBuilder.moduleRuntimeClasspath(module, false).each { | |
| File file = new File(it) | |
| if (file.exists()) { | |
| String path = file.canonicalPath.replace('\\', '/') | |
| if (path.endsWith(".jar") && approvedJars.any { path.startsWith(it) } && !forbiddenJars.any { path.contains(it) }) { | |
| if (usedJars.add(path)) { | |
| projectBuilder.info("\tADDED: $path for ${module.getName()}") | |
| } | |
| } | |
| } | |
| } | |
| if (modulesToBuild != null) { | |
| modulesToBuild << module | |
| } | |
| } | |
| else { | |
| projectBuilder.warning("$it is not a module") | |
| } | |
| } | |
| return usedJars | |
| }) | |
| binding.setVariable("buildModulesAndCollectUsedJars", { List modules, List approvedJars, List forbiddenJars -> | |
| def modulesToBuild = [] | |
| def usedJars = collectUsedJars(modules, approvedJars, forbiddenJars, modulesToBuild) | |
| projectBuilder.cleanOutput() | |
| projectBuilder.buildModules(modulesToBuild) | |
| return usedJars | |
| }) | |
| binding.setVariable("buildSearchableOptions", { String target, List licenses, Closure cp, String jvmArgs = null, | |
| def paths = getProperty("paths") -> | |
| projectBuilder.stage("Building searchable options") | |
| String targetFile = "${target}/searchableOptions.xml" | |
| ant.delete(file: targetFile) | |
| licenses.each { | |
| ant.copy(file: it, todir: paths.ideaSystem) | |
| } | |
| ant.path(id: "searchable.options.classpath") { cp() } | |
| String classpathFile = "${paths.sandbox}/classpath.txt" | |
| ant.echo(file: classpathFile, append: false, message: "\${toString:searchable.options.classpath}") | |
| ant.replace(file: classpathFile, token: File.pathSeparator, value: "\n") | |
| ant.java(classname: "com.intellij.rt.execution.CommandLineWrapper", fork: true, failonerror: true) { | |
| jvmarg(line: "-Xbootclasspath/a:${projectBuilder.moduleOutput(findModule("boot"))} -ea -Xmx500m -XX:MaxPermSize=200m") | |
| jvmarg(line: "-Didea.home.path=$home -Didea.system.path=${paths.ideaSystem} -Didea.config.path=${paths.ideaConfig}") | |
| if (jvmArgs != null) { | |
| jvmarg(line: jvmArgs) | |
| } | |
| arg(line: "${classpathFile} com.intellij.idea.Main traverseUI ${target}/searchableOptions.xml") | |
| classpath() { | |
| pathelement(location: "${projectBuilder.moduleOutput(findModule("java-runtime"))}") | |
| } | |
| } | |
| ant.available(file: targetFile, property: "searchable.options.exists"); | |
| ant.fail(unless: "searchable.options.exists", message: "Searchable options were not built.") | |
| }) |