blob: 1c597021c7008b46c88aea707eb12f1ada7f9d2a [file] [log] [blame]
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -08001/*
2 * Copyright 2000-2013 JetBrains s.r.o.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Tor Norbye6739a8f2013-08-07 11:11:08 -070017import org.jetbrains.jps.gant.JpsGantTool
18import org.jetbrains.jps.gant.TeamCityBuildInfoPrinter
19import org.jetbrains.jps.model.java.JavaSourceRootType
20import org.jetbrains.jps.model.module.JpsModule
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080021
Tor Norbye6739a8f2013-08-07 11:11:08 -070022includeTool << JpsGantTool
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080023
24binding.setVariable("p", {String key ->
25 return getProperty(key) as String
26})
27
28binding.setVariable("guessJdk", {
29 String javaHome = p("java.home")
30
31 if (new File(javaHome).getName() == "jre") {
32 javaHome = new File(javaHome).getParent()
33 }
34
35 return javaHome
36})
37
38binding.setVariable("includeFile", {String filePath ->
39 Script s = groovyShell.parse(new File(filePath))
40 s.setBinding(binding)
41 s
42})
43
44binding.setVariable("isMac", {
45 return System.getProperty("os.name").toLowerCase().startsWith("mac")
46})
47
48binding.setVariable("isWin", {
49 return System.getProperty("os.name").toLowerCase().startsWith("windows")
50})
51
52binding.setVariable("isEap", {
53 return "true" == p("component.version.eap")
54})
55
Tor Norbyec1ace1f2013-07-08 11:26:24 -070056binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=64m")
57binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=96m")
58binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
59 "-XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080060
61binding.setVariable("vmOptions", { "$common_vmoptions ${isEap() ? '-XX:+HeapDumpOnOutOfMemoryError' : ''}".trim() })
62binding.setVariable("vmOptions32", { "$mem32 ${vmOptions()}".trim() })
63binding.setVariable("vmOptions64", { "$mem64 ${vmOptions()}".trim() })
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070064
65binding.setVariable("yjpOptions", { String systemSelector, String platformSuffix = "" ->
Tor Norbyec1ace1f2013-07-08 11:26:24 -070066 "-agentlib:yjpagent$platformSuffix=disablej2ee,disablealloc,disabletracing,onlylocal,builtinprobes=none,disableexceptiontelemetry,delay=10000,sessionname=$systemSelector".trim()
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070067})
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080068binding.setVariable("vmOptions32yjp", { String systemSelector ->
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070069 "${vmOptions32()} ${yjpOptions(systemSelector)}".trim()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080070})
71binding.setVariable("vmOptions64yjp", { String systemSelector ->
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -070072 "${vmOptions64()} ${yjpOptions(systemSelector, "64")}".trim()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -080073})
74
75binding.setVariable("isDefined", {String key ->
76 try {
77 this[key]
78 return true
79 }
80 catch (MissingPropertyException ignored) {
81 return false
82 }
83})
84
85private String require(String key) {
86 try {
87 this[key]
88 }
89 catch (MissingPropertyException ignored) {
90 projectBuilder.error("Property $key is required")
91 }
92}
93
94private String require(String key, String defaultValue) {
95 try {
96 this[key]
97 }
98 catch (MissingPropertyException ignored) {
99 projectBuilder.info("$key is not defined. Defaulting to $defaultValue")
100 this[key] = defaultValue
101 }
102}
103
104binding.setVariable("requireProperty", {String key, String defaultValue = null ->
105 if (defaultValue == null) {
106 require(key)
107 }
108 else {
109 require(key, defaultValue)
110 }
111})
112
113binding.setVariable("guessHome", {
114 // Current file is supposed to be at build/scripts/release.gant path
115 new File(requireProperty("gant.file").substring("file:".length())).getParentFile().getParentFile().getParent()
116})
117
118binding.setVariable("loadProject", {
119 requireProperty("jdkHome", guessJdk())
120 def mac = isMac()
121 jdk("IDEA jdk", jdkHome) {
122 if (!mac) {
123 classpath "$jdkHome/lib/tools.jar"
124 }
125 }
Tor Norbye6739a8f2013-08-07 11:11:08 -0700126 projectBuilder.dataStorageRoot = new File("$home/.jps-build-data")
127 loadProjectFromPath(home)
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800128})
129
Tor Norbye6739a8f2013-08-07 11:11:08 -0700130boolean hasSourceRoots(JpsModule module) {
131 return module.getSourceRoots(JavaSourceRootType.SOURCE).iterator().hasNext()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800132}
133
134binding.setVariable("findModule", {String name ->
Tor Norbye6739a8f2013-08-07 11:11:08 -0700135 project.modules.find { it.name == name }
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800136})
137
138binding.setVariable("allModules", {
Tor Norbye6739a8f2013-08-07 11:11:08 -0700139 return project.modules
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800140})
141
142binding.setVariable("printUnusedModules", {Set<String> usedModules ->
Tor Norbye6739a8f2013-08-07 11:11:08 -0700143 allModules().each {JpsModule m ->
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800144 if (!usedModules.contains(m.name) && hasSourceRoots(m)) {
145 projectBuilder.warning("Module $m.name is not used in project layout")
146 }
147 }
148})
149
150requireProperty("home", guessHome())
151
152String readSnapshotBuild() {
153 def file = new File("$home/community/build.txt")
154 if (!file.exists()) {
155 file = new File("$home/build.txt")
156 }
157
158 return file.readLines().get(0)
159}
160
161binding.setVariable("snapshot", readSnapshotBuild())
162
Tor Norbye6739a8f2013-08-07 11:11:08 -0700163projectBuilder.buildInfoPrinter = new TeamCityBuildInfoPrinter()
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800164projectBuilder.compressJars = false
165
166binding.setVariable("notifyArtifactBuilt", { String artifactPath ->
167 if (!artifactPath.startsWith(home)) {
168 projectBuilder.error("Artifact path $artifactPath should start with $home")
169 }
170 def relativePath = artifactPath.substring(home.length())
171 if (relativePath.startsWith("/")) {
172 relativePath = relativePath.substring(1)
173 }
174 def file = new File(artifactPath)
175 if (file.isDirectory()) {
176 relativePath += "=>" + file.name
177 }
178 projectBuilder.info("##teamcity[publishArtifacts '$relativePath']")
179})
180
181def suspendUntilDebuggerConnect = System.getProperty("debug.suspend") ?: "n"
182def debugPort = System.getProperty("debug.port") ?: 5555
183if (suspendUntilDebuggerConnect == 'y') {
184 println """\
185------------->----------- This process is suspended until remote debugger connects to the port $debugPort ----<----
Tor Norbye8fb00212013-05-01 12:55:43 -0700186-------------------------------------------^------^------^------^------^------^------^-----------------------
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800187"""
188}
189
190binding.setVariable("patchFiles", { List files, Map args, String marker = "__" ->
191 files.each { file ->
192 args.each { arg ->
193 ant.replace(file: file, token: "${marker}${arg.key}${marker}", value: arg.value)
194 }
195 }
196})
197
198binding.setVariable("copyAndPatchFile", { String file, String target, Map args, String marker = "__" ->
199 ant.copy(file: file, tofile: target, overwrite: "true") {
200 filterset(begintoken: marker, endtoken: marker) {
201 args.each {
202 filter(token: it.key, value: it.value)
203 }
204 }
205 }
206})
207
208binding.setVariable("copyAndPatchFiles", { Closure files, String target, Map args, String marker = "__" ->
209 ant.copy(todir: target, overwrite: "true") {
210 files()
211
212 filterset(begintoken: marker, endtoken: marker) {
213 args.each {
214 filter(token: it.key, value: it.value)
215 }
216 }
217 }
218})
219
220binding.setVariable("wireBuildDate", { String buildNumber, String appInfoFile ->
221 ant.tstamp()
222 patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP])
223})
224
225binding.setVariable("commonJvmArgs", {
226 return [
227 "-ea",
228 "-Didea.home.path=$home",
229 "-Xbootclasspath/p:${projectBuilder.moduleOutput(findModule("boot"))}",
230 "-XX:+HeapDumpOnOutOfMemoryError",
231 "-Didea.system.path=${p("teamcity.build.tempDir")}/system",
232 "-Didea.config.path=${p("teamcity.build.tempDir")}/config",
233 "-Xdebug",
234 "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"]
235})
236
237binding.setVariable("classPathLibs", [
238 "bootstrap.jar",
239 "extensions.jar",
240 "util.jar",
241 "jdom.jar",
242 "log4j.jar",
243 "trove4j.jar",
244 "jna.jar"
245])
246
247binding.setVariable("platformApiModules", [
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700248 "analysis-api",
249 "core-api",
Tor Norbyec7f983b2013-09-05 16:07:26 -0700250 "editor-ui-api",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700251 "external-system-api",
252 "indexing-api",
253 "jps-model-api",
254 "lang-api",
255 "lvcs-api",
256 "projectModel-api",
257 "platform-api",
258 "usageView",
259 "vcs-api",
Tor Norbye32218cc2013-10-08 09:48:09 -0700260 "vcs-log-api",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700261 "xdebugger-api",
Tor Norbye3a2425a2013-11-04 10:16:08 -0800262 "xml-analysis-api",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700263 "xml-openapi",
264 "xml-psi-api",
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800265])
266
267
268binding.setVariable("platformImplementationModules", [
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700269 "analysis-impl",
270 "core-impl",
271 "dvcs",
Tor Norbyea28de542013-09-11 15:53:32 -0700272 "editor-ui-ex",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700273 "images",
274 "indexing-impl",
275 "jps-model-impl",
276 "jps-model-serialization",
277 "lang-impl",
278 "lvcs-impl",
279 "projectModel-impl",
280 "platform-impl",
281 "vcs-impl",
Tor Norbye32218cc2013-10-08 09:48:09 -0700282 "vcs-log-graph",
283 "vcs-log-impl",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700284 "testRunner",
285 "smRunner",
286 "relaxng",
287 "RegExpSupport",
288 "spellchecker",
289 "xdebugger-impl",
290 "xml",
Tor Norbye3a2425a2013-11-04 10:16:08 -0800291 "xml-analysis-impl",
Tor Norbyeec3fb1e2013-05-31 07:45:51 -0700292 "xml-psi-impl",
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800293])
294
295binding.setVariable("layoutMacApp", { String path, String ch, Map args ->
296 ant.copy(todir: "$path/bin") {
297 fileset(dir: "$ch/bin/mac")
298 }
299
300 ant.copy(todir: path) {
301 fileset(dir: "$ch/build/conf/mac")
302 }
303
304 ant.tstamp() {
305 format(property: "todayYear", pattern: "yyyy")
306 }
307
308 String executable = args.executable != null ? args.executable : p("component.names.product").toLowerCase()
309 String helpId = args.help_id != null ? args.help_id : "IJ"
310 String icns = "idea.icns"
311 String helpIcns = "$path/Contents/Resources/${helpId}.help/Contents/Resources/Shared/product.icns"
312 if (args.icns != null) {
313 ant.delete(file: "$path/Contents/Resources/idea.icns")
314 ant.copy(file: args.icns, todir: "$path/Contents/Resources")
315 ant.copy(file: args.icns, tofile: helpIcns)
316 icns = new File((String)args.icns).getName();
317 } else {
318 ant.copy(file: "$path/Contents/Resources/idea.icns", tofile: helpIcns)
319 }
320
321 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
322
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700323 String vmOptions = "-Dfile.encoding=UTF-8 ${vmOptions()} -Xverify:none"
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800324 if (isEap() && !args.mac_no_yjp) {
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700325 vmOptions += " ${yjpOptions(args.system_selector)}"
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800326 }
327
328 String minor = p("component.version.minor")
329 String version = isEap() && !minor.contains("RC") && !minor.contains("Beta") ? "EAP $args.buildNumber" : "${p("component.version.major")}.${minor}"
330
331 Map properties = readIdeaProperties(args)
332
333 def coreKeys = ["idea.platform.prefix", "idea.paths.selector"]
334
335 String coreProperties = submapToXml(properties, coreKeys);
336
337 StringBuilder effectiveProperties = new StringBuilder()
338 properties.each { k, v ->
339 if (!coreKeys.contains(k)) {
340 effectiveProperties.append("$k=$v\n");
341 }
342 }
343
344 new File("$path/bin/idea.properties").text = effectiveProperties.toString()
345 new File("$path/bin/idea.vmoptions").text = "$mem64 -XX:+UseCompressedOops".split(" ").join("\n")
346
347 String classPath = classPathLibs.collect {"\$APP_PACKAGE/lib/${it}" }.join(":")
348
Jean-Baptiste Queru1d526b12013-02-27 09:41:48 -0800349 String urlSchemes = ""
350 if (args.urlSchemes != null) {
351 urlSchemes += """
352 <key>CFBundleURLTypes</key>
353 <array>
354 <dict>
355 <key>CFBundleTypeRole</key>
356 <string>Editor</string>
357 <key>CFBundleURLName</key>
358 <string>Stacktrace</string>
359 <key>CFBundleURLSchemes</key>
360 <array>
361"""
362 args.urlSchemes.each { scheme ->
363 urlSchemes += " <string>${scheme}</string>"
364 }
365 urlSchemes += """
366 </array>
367 </dict>
368 </array>
369"""
370 }
371
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800372 ant.replace(file: "$path/Contents/Info.plist") {
373 replacefilter(token: "@@build@@", value: args.buildNumber)
374 replacefilter(token: "@@doc_types@@", value: ifNull(args.doc_types, ""))
375 replacefilter(token: "@@executable@@", value: executable)
376 replacefilter(token: "@@icns@@", value: icns)
377 replacefilter(token: "@@bundle_name@@", value: fullName)
378 replacefilter(token: "@@bundle_identifier@@", value: args.bundleIdentifier)
379 replacefilter(token: "@@year@@", value: "$todayYear")
380 replacefilter(token: "@@version@@", value: version)
381 replacefilter(token: "@@vmoptions@@", value: vmOptions)
382 replacefilter(token: "@@idea_properties@@", value: coreProperties)
383 replacefilter(token: "@@class_path@@", value: classPath)
384 replacefilter(token: "@@help_id@@", value: helpId)
Jean-Baptiste Queru1d526b12013-02-27 09:41:48 -0800385 replacefilter(token: "@@url_schemes@@", value: urlSchemes)
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800386 }
387
388 if (executable != "idea") {
389 ant.move(file: "$path/Contents/MacOS/idea", tofile: "$path/Contents/MacOS/$executable")
390 }
391
392 ant.replace(file: "$path/bin/inspect.sh") {
393 replacefilter(token: "@@product_full@@", value: fullName)
394 replacefilter(token: "@@script_name@@", value: executable)
395 }
396 if (args.inspect_script != null && args.inspect_script != "inspect") {
397 ant.move(file: "$path/bin/inspect.sh", tofile: "$path/bin/${args.inspect_script}.sh")
398 }
399})
400
401binding.setVariable("winScripts", { String target, String home, String name, Map args ->
402 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
403 String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
404 String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase()}.exe"
405 if (vm_options.endsWith(".exe")) {
406 vm_options = vm_options.replace(".exe", "%BITS%.exe")
407 }
408 else {
409 vm_options = vm_options + "%BITS%"
410 }
411
412 String classPath = "SET CLASS_PATH=%IDE_HOME%\\lib\\${classPathLibs[0]}\n"
413 classPath += classPathLibs[1..-1].collect {"SET CLASS_PATH=%CLASS_PATH%;%IDE_HOME%\\lib\\${it}"}.join("\n")
414 if (args.tools_jar) classPath += "\nSET CLASS_PATH=%CLASS_PATH%;%JDK%\\lib\\tools.jar"
415
416 ant.copy(todir: "$target/bin") {
417 fileset(dir: "$home/bin/scripts/win")
418
419 filterset(begintoken: "@@", endtoken: "@@") {
420 filter(token: "product_full", value: fullName)
421 filter(token: "product_uc", value: product_uc)
422 filter(token: "vm_options", value: vm_options)
423 filter(token: "isEap", value: isEap())
424 filter(token: "system_selector", value: args.system_selector)
425 filter(token: "ide_jvm_args", value: ifNull(args.ide_jvm_args, ""))
426 filter(token: "class_path", value: classPath)
427 filter(token: "script_name", value: name)
428 }
429 }
430
431 if (name != "idea.bat") {
432 ant.move(file: "$target/bin/idea.bat", tofile: "$target/bin/$name")
433 }
434 if (args.inspect_script != null && args.inspect_script != "inspect") {
435 ant.move(file: "$target/bin/inspect.bat", tofile: "$target/bin/${args.inspect_script}.bat")
436 }
437
438 ant.fixcrlf(srcdir: "$target/bin", includes: "*.bat", eol: "dos")
439})
440
441private ifNull(v, defVal) { v != null ? v : defVal }
442
443binding.setVariable("unixScripts", { String target, String home, String name, Map args ->
444 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
445 String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
446 String vm_options = args.vm_options != null ? args.vm_options : p("component.names.product").toLowerCase()
447
448 String classPath = "CLASSPATH=\"\$IDE_HOME/lib/${classPathLibs[0]}\"\n"
449 classPath += classPathLibs[1..-1].collect {"CLASSPATH=\"\$CLASSPATH:\$IDE_HOME/lib/${it}\""}.join("\n")
450 if (args.tools_jar) classPath += "\nCLASSPATH=\"\$CLASSPATH:\$JDK/lib/tools.jar\""
451
452 ant.copy(todir: "$target/bin") {
453 fileset(dir: "$home/bin/scripts/unix")
454
455 filterset(begintoken: "@@", endtoken: "@@") {
456 filter(token: "product_full", value: fullName)
457 filter(token: "product_uc", value: product_uc)
458 filter(token: "vm_options", value: vm_options)
459 filter(token: "isEap", value: isEap())
460 filter(token: "system_selector", value: args.system_selector)
461 filter(token: "ide_jvm_args", value: ifNull(args.ide_jvm_args, ""))
462 filter(token: "class_path", value: classPath)
463 filter(token: "script_name", value: name)
464 }
465 }
466
467 if (name != "idea.sh") {
468 ant.move(file: "$target/bin/idea.sh", tofile: "$target/bin/$name")
469 }
470 if (args.inspect_script != null && args.inspect_script != "inspect") {
471 ant.move(file: "$target/bin/inspect.sh", tofile: "$target/bin/${args.inspect_script}.sh")
472 }
473
474 ant.fixcrlf(srcdir: "$target/bin", includes: "*.sh", eol: "unix")
475})
476
477binding.setVariable("winVMOptions", { String target, String system_selector, String name, String name64 = null ->
478 def options = isEap() && system_selector != null ? vmOptions32yjp(system_selector) : vmOptions32()
479 ant.echo(file: "$target/bin/${name}.vmoptions", message: options.replace(' ', '\n'))
480
481 if (name64 != null) {
482 options = isEap() && system_selector != null ? vmOptions64yjp(system_selector) : vmOptions64()
483 ant.echo(file: "$target/bin/${name64}.vmoptions", message: options.replace(' ', '\n'))
484 }
485
486 ant.fixcrlf(srcdir: "$target/bin", includes: "*.vmoptions", eol: "dos")
487})
488
489binding.setVariable("unixVMOptions", { String target, String name ->
Tor Norbyec1ace1f2013-07-08 11:26:24 -0700490 ant.echo(file: "$target/bin/${name}.vmoptions", message: "${vmOptions32()} -Dawt.useSystemAAFontSettings=lcd".trim().replace(' ', '\n'))
491 ant.echo(file: "$target/bin/${name}64.vmoptions", message: "${vmOptions64()} -Dawt.useSystemAAFontSettings=lcd".trim().replace(' ', '\n'))
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800492 ant.fixcrlf(srcdir: "$target/bin", includes: "*.vmoptions", eol: "unix")
493})
494
495binding.setVariable("unixReadme", { String target, String home, Map args ->
496 String fullName = args.fullName != null ? args.fullName : p("component.names.fullname")
497 String settings_dir = args.system_selector.replaceFirst("\\d+", "")
498 copyAndPatchFile("$home/build/Install-Linux-tar.txt", "$target/Install-Linux-tar.txt",
499 ["product_full": fullName,
500 "product": p("component.names.product").toLowerCase(),
501 "system_selector": args.system_selector,
502 "settings_dir": settings_dir], "@@")
503 ant.fixcrlf(file: "$target/bin/Install-Linux-tar.txt", eol: "unix")
504})
505
506binding.setVariable("forceDelete", { String dirPath ->
507 // if wasn't deleted - retry several times
508 attempt = 1
509 while (attempt < 21 && (new File(dirPath).exists())) {
510 if (attempt > 1) {
511 ant.echo "Deleting $dirPath ... (attempt=$attempt)"
512
513 // let's wait a bit and try again - may be help
514 // in some cases on our windows 7 agents
515 sleep(2000)
516 }
517
518 ant.delete(failonerror: false, dir: dirPath)
519
520 attempt++
521 }
522
523 if (new File(dirPath).exists()) {
524 ant.project.log ("Cannot delete directory: $dirPath" )
525 System.exit (1)
526 }
527})
528
529binding.setVariable("patchPropertiesFile", { String target, Map args = [:] ->
530 String file = "$target/bin/idea.properties"
531
532 if (args.appendices != null) {
533 ant.concat(destfile: file, append: true) {
534 args.appendices.each {
535 fileset(file: it)
536 }
537 }
538 }
539
540 String product_uc = args.product_uc != null ? args.product_uc : p("component.names.product").toUpperCase()
541 String settings_dir = args.system_selector.replaceFirst("\\d+", "")
542 ant.replace(file: file) {
543 replacefilter(token: "@@product_uc@@", value: product_uc)
544 replacefilter(token: "@@settings_dir@@", value: settings_dir)
545 }
546
547 String message = (isEap() ? """
548#-----------------------------------------------------------------------
549# Change to 'disabled' if you don't want to receive instant visual notifications
550# about fatal errors that happen to an IDE or plugins installed.
551#-----------------------------------------------------------------------
552idea.fatal.error.notification=enabled
553"""
554 : """
555#-----------------------------------------------------------------------
556# Change to 'enabled' if you want to receive instant visual notifications
557# about fatal errors that happen to an IDE or plugins installed.
558#-----------------------------------------------------------------------
559idea.fatal.error.notification=disabled
560""")
561 ant.echo(file: file, append: true, message: message)
562})
563
564binding.setVariable("zipSources", { String home, String targetDir ->
565 String sources = "$targetDir/sources.zip"
566 projectBuilder.stage("zip sources to $sources")
567
568 ant.mkdir(dir: targetDir)
569 ant.delete(file: sources)
570 ant.zip(destfile: sources) {
571 fileset(dir: home) {
572 ["java", "groovy", "ipr", "iml", "form", "xml", "properties"].each {
573 include(name: "**/*.$it")
574 }
575 exclude(name: "**/testData/**")
576 }
577 }
578
579 notifyArtifactBuilt(sources)
580})
581
582/**
583 * E.g.
584 *
585 * Load all properties from file:
586 * readIdeaProperties("idea.properties.path" : "$home/ruby/build/idea.properties")
587 *
588 * Load all properties except "idea.cycle.buffer.size", change "idea.max.intellisense.filesize" to 3000
589 * and enable "idea.is.internal" mode:
590 * readIdeaProperties("idea.properties.path" : "$home/ruby/build/idea.properties",
591 * "idea.properties" : ["idea.max.intellisense.filesize" : 3000,
592 * "idea.cycle.buffer.size" : null,
593 * "idea.is.internal" : true ])
594 * @param args
595 * @return text xml properties description in xml
596 */
597private Map readIdeaProperties(Map args) {
598 String ideaPropertiesPath = args == null ? null : args.get("idea.properties.path")
599 if (ideaPropertiesPath == null) {
600 return [:]
601 }
602
603 // read idea.properties file
604 Properties ideaProperties = new Properties();
605 FileInputStream ideaPropertiesFile = new FileInputStream(ideaPropertiesPath);
606 ideaProperties.load(ideaPropertiesFile);
607 ideaPropertiesFile.close();
608
609 def defaultProperties = ["CVS_PASSFILE": "~/.cvspass",
610 "com.apple.mrj.application.live-resize": "false",
611 "idea.paths.selector": args.system_selector,
612 "java.endorsed.dirs": "",
613 "idea.smooth.progress": "false",
614 "apple.laf.useScreenMenuBar": "true",
615 "apple.awt.graphics.UseQuartz": "true",
616 "apple.awt.fullscreencapturealldisplays": "false"]
617 if (args.platform_prefix != null) {
618 defaultProperties.put("idea.platform.prefix", args.platform_prefix)
619 }
620
621 Map properties = defaultProperties
622 def customProperties = args.get("idea.properties")
623 if (customProperties != null) {
624 properties += customProperties
625 }
626
627 properties.each {k, v ->
628 if (v == null) {
629 // if overridden with null - ignore property
630 ideaProperties.remove(k)
631 } else {
632 // if property is overridden in args map - use new value
633 ideaProperties.put(k, v)
634 }
635 }
636
637 return ideaProperties;
638}
639
640private String submapToXml(Map properties, List keys) {
641// generate properties description for Info.plist
642 StringBuilder buff = new StringBuilder()
643
644 keys.each { key ->
645 String value = properties[key]
646 if (value != null) {
647 String string =
648 """
649 <key>$key</key>
650 <string>$value</string>
651"""
652 buff.append(string)
653 }
654 }
655 return buff.toString()
656}
657
658binding.setVariable("buildWinZip", { String zipPath, List paths ->
659 projectBuilder.stage(".win.zip")
660
661 fixIdeaPropertiesEol(paths, "dos")
662
663 ant.zip(zipfile: zipPath) {
664 paths.each {
665 fileset(dir: it)
666 }
667 }
668
669 notifyArtifactBuilt(zipPath)
670})
671
672binding.setVariable("buildMacZip", { String zipRoot, String zipPath, List paths, String macPath, List extraBins = [] ->
673 projectBuilder.stage(".mac.zip")
674
675 allPaths = paths + [macPath]
676 ant.zip(zipfile: zipPath) {
677 allPaths.each {
678 zipfileset(dir: it, prefix: zipRoot) {
679 exclude(name: "bin/*.sh")
Tor Norbye32218cc2013-10-08 09:48:09 -0700680 exclude(name: "bin/*.py")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800681 exclude(name: "bin/fsnotifier")
Jean-Baptiste Queru9edc8f62013-02-08 15:14:04 -0800682 exclude(name: "bin/restarter")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800683 exclude(name: "Contents/MacOS/*")
684 extraBins.each {
685 exclude(name: it)
686 }
687 exclude(name: "bin/idea.properties")
688 }
689 }
690
691 allPaths.each {
692 zipfileset(dir: it, filemode: "755", prefix: zipRoot) {
693 include(name: "bin/*.sh")
Tor Norbye32218cc2013-10-08 09:48:09 -0700694 include(name: "bin/*.py")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800695 include(name: "bin/fsnotifier")
Jean-Baptiste Queru9edc8f62013-02-08 15:14:04 -0800696 include(name: "bin/restarter")
Jean-Baptiste Querub56ea2a2013-01-08 11:11:20 -0800697 include(name: "Contents/MacOS/*")
698 extraBins.each {
699 include(name: it)
700 }
701 }
702 }
703
704 zipfileset(file: "$macPath/bin/idea.properties", prefix: "$zipRoot/bin")
705 }
706})
707
708binding.setVariable("buildTarGz", { String tarRoot, String tarPath, List paths ->
709 projectBuilder.stage(".tar.gz")
710
711 fixIdeaPropertiesEol(paths, "unix")
712
713 ant.tar(tarfile: tarPath, longfile: "gnu") {
714 paths.each {
715 tarfileset(dir: it, prefix: tarRoot) {
716 exclude(name: "bin/*.sh")
717 exclude(name: "bin/fsnotifier*")
718 type(type: "file")
719 }
720 }
721
722 paths.each {
723 tarfileset(dir: it, filemode: "755", prefix: tarRoot) {
724 include(name: "bin/*.sh")
725 include(name: "bin/fsnotifier*")
726 type(type: "file")
727 }
728 }
729 }
730
731 String gzPath = "${tarPath}.gz"
732 ant.gzip(src: tarPath, zipfile: gzPath)
733 ant.delete(file: tarPath)
734 notifyArtifactBuilt(gzPath)
735})
736
737private void fixIdeaPropertiesEol(List paths, String eol) {
738 paths.each {
739 String file = "$it/bin/idea.properties"
740 if (new File(file).exists()) {
741 ant.fixcrlf(file: file, eol: eol)
742 }
743 }
744}
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700745
Tor Norbyec1ace1f2013-07-08 11:26:24 -0700746binding.setVariable("buildWinLauncher", { String ch, String inputPath, String outputPath, String appInfo,
747 String launcherProperties, String pathsSelector, List resourcePaths ->
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700748 projectBuilder.stage("winLauncher")
749
Tor Norbyed1a59a02013-04-03 16:27:26 -0700750 File launcherPropertiesTempFile = null;
751 if (pathsSelector != null) {
752 String propertiesContent = new File(launcherProperties).text
753 if (propertiesContent.contains("__PRODUCT_PATHS_SELECTOR__")) {
754 propertiesContent = propertiesContent.replace("__PRODUCT_PATHS_SELECTOR__", pathsSelector)
755 launcherPropertiesTempFile = File.createTempFile("launcher", ".properties")
756 launcherPropertiesTempFile.write(propertiesContent)
757 launcherProperties = launcherPropertiesTempFile.getAbsolutePath()
758 }
759 }
760
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700761 ant.java(classname: "com.pme.launcher.LauncherGeneratorMain", fork: "true") {
762 arg(value: inputPath)
763 arg(value: appInfo)
764 arg(value: "$ch/native/WinLauncher/WinLauncher/resource.h")
765 arg(value: launcherProperties)
766 arg(value: outputPath)
767 classpath {
768 pathelement(location: "$ch/build/lib/launcher-generator.jar")
769 fileset(dir: "$ch/lib") {
770 include(name: "guava*.jar")
771 include(name: "jdom.jar")
772 include(name: "sanselan*.jar")
773 }
774 resourcePaths.each {
775 pathelement(location: it)
776 }
777 }
778 }
Tor Norbyed1a59a02013-04-03 16:27:26 -0700779
780 if (launcherPropertiesTempFile != null) {
781 launcherPropertiesTempFile.delete()
782 }
Jean-Baptiste Queru2bd2b7c2013-04-01 14:41:51 -0700783})
Tor Norbyebeca9832013-09-19 12:39:22 -0700784
Tor Norbyef7998d02013-09-27 10:19:19 -0700785binding.setVariable("collectUsedJars", { List modules, List approvedJars, List forbiddenJars, List modulesToBuild ->
Tor Norbyebeca9832013-09-19 12:39:22 -0700786 def usedJars = new HashSet();
787
Tor Norbyebeca9832013-09-19 12:39:22 -0700788 modules.each {
789 def module = findModule(it)
790 if (module != null) {
791 projectBuilder.moduleRuntimeClasspath(module, false).each {
792 File file = new File(it)
793 if (file.exists()) {
794 String path = file.canonicalPath.replace('\\', '/')
795 if (path.endsWith(".jar") && approvedJars.any { path.startsWith(it) } && !forbiddenJars.any { path.contains(it) }) {
796 if (usedJars.add(path)) {
797 projectBuilder.info("\tADDED: $path for ${module.getName()}")
798 }
799 }
800 }
801 }
Tor Norbyef7998d02013-09-27 10:19:19 -0700802 if (modulesToBuild != null) {
803 modulesToBuild << module
804 }
Tor Norbyebeca9832013-09-19 12:39:22 -0700805 }
806 else {
807 projectBuilder.warning("$it is not a module")
808 }
809 }
Tor Norbyef7998d02013-09-27 10:19:19 -0700810
811 return usedJars
812})
813
814binding.setVariable("buildModulesAndCollectUsedJars", { List modules, List approvedJars, List forbiddenJars ->
815 def modulesToBuild = []
816 def usedJars = collectUsedJars(modules, approvedJars, forbiddenJars, modulesToBuild)
817 projectBuilder.cleanOutput()
Tor Norbyebeca9832013-09-19 12:39:22 -0700818 projectBuilder.buildModules(modulesToBuild)
819
820 return usedJars
821})
822
823binding.setVariable("buildSearchableOptions", { String target, List licenses, Closure cp, String jvmArgs = null,
824 def paths = getProperty("paths") ->
825 projectBuilder.stage("Building searchable options")
826
827 String targetFile = "${target}/searchableOptions.xml"
828 ant.delete(file: targetFile)
829
830 licenses.each {
831 ant.copy(file: it, todir: paths.ideaSystem)
832 }
833
834 ant.path(id: "searchable.options.classpath") { cp() }
835 String classpathFile = "${paths.sandbox}/classpath.txt"
836 ant.echo(file: classpathFile, append: false, message: "\${toString:searchable.options.classpath}")
837 ant.replace(file: classpathFile, token: File.pathSeparator, value: "\n")
838
839 ant.java(classname: "com.intellij.rt.execution.CommandLineWrapper", fork: true, failonerror: true) {
840 jvmarg(line: "-Xbootclasspath/a:${projectBuilder.moduleOutput(findModule("boot"))} -ea -Xmx500m -XX:MaxPermSize=200m")
841 jvmarg(line: "-Didea.home.path=$home -Didea.system.path=${paths.ideaSystem} -Didea.config.path=${paths.ideaConfig}")
842 if (jvmArgs != null) {
843 jvmarg(line: jvmArgs)
844 }
845
846 arg(line: "${classpathFile} com.intellij.idea.Main traverseUI ${target}/searchableOptions.xml")
847
848 classpath() {
849 pathelement(location: "${projectBuilder.moduleOutput(findModule("java-runtime"))}")
850 }
851 }
852
853 ant.available(file: targetFile, property: "searchable.options.exists");
854 ant.fail(unless: "searchable.options.exists", message: "Searchable options were not built.")
855})