summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rwxr-xr-x[-rw-r--r--].idea/codeStyleSettings.xml7
-rw-r--r--.idea/compiler.xml1
-rw-r--r--.idea/copyright/aosp.xml9
-rw-r--r--.idea/copyright/profiles_settings.xml5
-rw-r--r--.idea/dictionaries/adt.xml326
-rw-r--r--.idea/inspectionProfiles/idea_default.xml8
-rw-r--r--.idea/libraries/asm_tools.xml13
-rw-r--r--.idea/libraries/bouncy_castle.xml13
-rw-r--r--.idea/libraries/builder_model.xml11
-rw-r--r--.idea/libraries/commons_compress.xml9
-rw-r--r--.idea/libraries/easymock_tools.xml13
-rw-r--r--.idea/libraries/fest.xml17
-rw-r--r--.idea/libraries/freemarker_2_3_20.xml11
-rw-r--r--.idea/libraries/google_api_java_client.xml9
-rw-r--r--.idea/libraries/guava_tools.xml11
-rw-r--r--.idea/libraries/junit3_tools.xml9
-rw-r--r--.idea/libraries/kxml2.xml13
-rw-r--r--.idea/libraries/lombok_ast.xml18
-rw-r--r--.idea/libraries/mockito.xml12
-rw-r--r--.idea/misc.xml25
-rw-r--r--.idea/modules.xml29
-rw-r--r--.idea/runConfigurations/AndroidStudio.xml25
-rw-r--r--.idea/scopes/androidplugin.xml3
-rw-r--r--.idea/scopes/aosp_code.xml3
-rw-r--r--.idea/scopes/obsoleteplugin.xml3
-rw-r--r--.idea/scopes/platform.xml3
-rw-r--r--.idea/vcs.xml3
-rw-r--r--build.xml38
-rw-r--r--build/Install-Linux-tar.txt2
-rw-r--r--build/conf/mac/Contents/Info.plist6
-rw-r--r--build/gant.xml5
-rw-r--r--build/scripts/common_tests.gant10
-rw-r--r--build/scripts/dist.gant101
-rw-r--r--build/scripts/layouts.gant383
-rw-r--r--build/scripts/tests.gant4
-rw-r--r--build/scripts/utils.gant47
-rwxr-xr-xbuild_ide_ext.sh66
-rwxr-xr-xbuild_studio.sh48
-rw-r--r--community-main.iml4
-rwxr-xr-x[-rw-r--r--]platform/bootstrap/src/com/intellij/idea/Main.java98
-rw-r--r--platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java4
-rw-r--r--platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java2
-rw-r--r--platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java5
-rw-r--r--platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java2
-rw-r--r--platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java1
-rwxr-xr-x[-rw-r--r--]platform/platform-impl/src/com/intellij/idea/StartupUtil.java1
-rw-r--r--platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java13
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java21
-rwxr-xr-x[-rw-r--r--]platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java23
-rwxr-xr-x[-rw-r--r--]platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java25
-rw-r--r--platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java29
-rw-r--r--platform/platform-resources-en/src/messages/IdeBundle.properties2
-rw-r--r--plugins/android/lib/guava-15.0.jarbin0 -> 2172168 bytes
-rw-r--r--plugins/android/lib/jarutils.jarbin0 -> 14712 bytes
-rw-r--r--plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java4
-rw-r--r--plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java3
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java9
-rw-r--r--plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java7
-rw-r--r--resources-en/src/tips/Welcome.html2
-rwxr-xr-x[-rw-r--r--]updater/src/com/intellij/updater/BaseUpdateAction.java8
-rwxr-xr-x[-rw-r--r--]updater/src/com/intellij/updater/CreateAction.java10
-rwxr-xr-x[-rw-r--r--]updater/src/com/intellij/updater/DeleteAction.java12
-rwxr-xr-x[-rw-r--r--]updater/src/com/intellij/updater/Digester.java3
-rwxr-xr-xupdater/src/com/intellij/updater/RetryException.java39
-rwxr-xr-x[-rw-r--r--]updater/src/com/intellij/updater/Runner.java78
-rwxr-xr-x[-rw-r--r--]updater/src/com/intellij/updater/SwingUpdaterUI.java99
-rwxr-xr-x[-rw-r--r--]updater/src/com/intellij/updater/Utils.java36
-rw-r--r--updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java271
-rwxr-xr-xupdater/testSrc/com/intellij/updater/UtilsTest.java73
-rw-r--r--updater/testUI/.gitignore1
-rwxr-xr-xupdater/testUI/build.gradle344
-rw-r--r--updater/testUI/gradle/wrapper/gradle-wrapper.jarbin0 -> 46670 bytes
-rw-r--r--updater/testUI/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xupdater/testUI/gradlew179
-rwxr-xr-xupdater/testUI/gradlew.bat96
-rwxr-xr-x[-rw-r--r--]updater/updater.iml0
77 files changed, 2587 insertions, 245 deletions
diff --git a/.gitignore b/.gitignore
index e1a3e405ef99..6aba63e3ef5f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,6 @@
/python/helpers/python-skeletons
/test-system
/test-config
+.jps-build-data
+/bin/build-log.xml
+/bin/build.log
diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
index c12c1c95e4a1..2faab0e8ef91 100644..100755
--- a/.idea/codeStyleSettings.xml
+++ b/.idea/codeStyleSettings.xml
@@ -51,6 +51,7 @@
<option name="USE_RELATIVE_INDENTS" value="false" />
</value>
</option>
+ <option name="LINE_SEPARATOR" value="&#10;" />
<option name="FIELD_NAME_PREFIX" value="my" />
<option name="STATIC_FIELD_NAME_PREFIX" value="our" />
<option name="RIGHT_MARGIN" value="140" />
@@ -290,9 +291,9 @@
</codeStyleSettings>
<codeStyleSettings language="jet">
<indentOptions>
- <option name="INDENT_SIZE" value="2"/>
- <option name="CONTINUATION_INDENT_SIZE" value="4"/>
- <option name="TAB_SIZE" value="2"/>
+ <option name="INDENT_SIZE" value="2" />
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ <option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="ruby">
diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index bb073aff93a9..3407e7c49c03 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -56,6 +56,7 @@
<option name="DEPRECATION" value="false" />
</component>
<component name="JavacSettings">
+ <option name="DEPRECATION" value="false" />
<option name="MAXIMUM_HEAP_SIZE" value="400" />
</component>
</project>
diff --git a/.idea/copyright/aosp.xml b/.idea/copyright/aosp.xml
new file mode 100644
index 000000000000..077aec61bbea
--- /dev/null
+++ b/.idea/copyright/aosp.xml
@@ -0,0 +1,9 @@
+<component name="CopyrightManager">
+ <copyright>
+ <option name="notice" value="Copyright (C) &amp;#36;today.year The Android Open Source Project&#10;&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10; http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License." />
+ <option name="keyword" value="Copyright" />
+ <option name="allowReplaceKeyword" value="" />
+ <option name="myName" value="aosp" />
+ <option name="myLocal" value="true" />
+ </copyright>
+</component> \ No newline at end of file
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
index 19fba7722ca2..7d505fe9c135 100644
--- a/.idea/copyright/profiles_settings.xml
+++ b/.idea/copyright/profiles_settings.xml
@@ -1,5 +1,8 @@
<component name="CopyrightManager">
- <settings default="apache 2 license">
+ <settings default="aosp">
+ <module2copyright>
+ <element module="aosp-code" copyright="aosp" />
+ </module2copyright>
<LanguageOptions name="__TEMPLATE__">
<option name="addBlankAfter" value="false" />
</LanguageOptions>
diff --git a/.idea/dictionaries/adt.xml b/.idea/dictionaries/adt.xml
new file mode 100644
index 000000000000..7be856568d17
--- /dev/null
+++ b/.idea/dictionaries/adt.xml
@@ -0,0 +1,326 @@
+<component name="ProjectDictionaryState">
+ <dictionary name="adt">
+ <words>
+ <w>&amp;amp</w>
+ <w>aapt</w>
+ <w>aarrggbb</w>
+ <w>accessors</w>
+ <w>actionbar</w>
+ <w>adb's</w>
+ <w>adbhost</w>
+ <w>addon</w>
+ <w>addons</w>
+ <w>addr</w>
+ <w>aidl</w>
+ <w>aload</w>
+ <w>androiddebugkey</w>
+ <w>anim</w>
+ <w>aosp</w>
+ <w>apkbuilder</w>
+ <w>apos</w>
+ <w>appname</w>
+ <w>areturn</w>
+ <w>argb</w>
+ <w>argv</w>
+ <w>armeabi</w>
+ <w>ast's</w>
+ <w>async</w>
+ <w>attrs</w>
+ <w>autofocus</w>
+ <w>automator</w>
+ <w>avd's</w>
+ <w>avdname</w>
+ <w>backfill</w>
+ <w>basename</w>
+ <w>basenames</w>
+ <w>bicubic</w>
+ <w>bilinear</w>
+ <w>bindir</w>
+ <w>bipush</w>
+ <w>bitcodelib</w>
+ <w>bitmask</w>
+ <w>blockquote</w>
+ <w>bluetooth</w>
+ <w>booleans</w>
+ <w>bootloader</w>
+ <w>borderless</w>
+ <w>bytecode</w>
+ <w>calloc</w>
+ <w>charsets</w>
+ <w>checkable</w>
+ <w>chksum</w>
+ <w>classfile</w>
+ <w>classname</w>
+ <w>classpathentry</w>
+ <w>clinit</w>
+ <w>clipart</w>
+ <w>closeables</w>
+ <w>codenames</w>
+ <w>combineaccessrules</w>
+ <w>compat</w>
+ <w>configurables</w>
+ <w>conv</w>
+ <w>crlf</w>
+ <w>crypto</w>
+ <w>cygpath</w>
+ <w>cygwin</w>
+ <w>dalvik</w>
+ <w>darcula</w>
+ <w>ddmlib</w>
+ <w>ddms</w>
+ <w>debuggable</w>
+ <w>densityless</w>
+ <w>designtime</w>
+ <w>dest</w>
+ <w>dexdump</w>
+ <w>digester</w>
+ <w>dimen</w>
+ <w>dirname</w>
+ <w>disp</w>
+ <w>donottranslate</w>
+ <w>dpad</w>
+ <w>drawables</w>
+ <w>dropdown</w>
+ <w>dumpsys</w>
+ <w>eabi</w>
+ <w>easymock</w>
+ <w>emdash</w>
+ <w>endian</w>
+ <w>enqueued</w>
+ <w>errno</w>
+ <w>executables</w>
+ <w>expectedly</w>
+ <w>filenames</w>
+ <w>filepath</w>
+ <w>fixme</w>
+ <w>fqcn</w>
+ <w>framebuffer</w>
+ <w>frameworkdir</w>
+ <w>froyo</w>
+ <w>fwvga</w>
+ <w>gbdserver</w>
+ <w>gdbserver</w>
+ <w>genkey</w>
+ <w>getenv</w>
+ <w>getfield</w>
+ <w>getprop</w>
+ <w>getstatic</w>
+ <w>globbing</w>
+ <w>goto</w>
+ <w>gradle</w>
+ <w>guide's</w>
+ <w>guillemets</w>
+ <w>hardcode</w>
+ <w>hardcoding</w>
+ <w>hashcode</w>
+ <w>hdpi</w>
+ <w>holo</w>
+ <w>horiz</w>
+ <w>httpclient</w>
+ <w>hvga</w>
+ <w>iaload</w>
+ <w>iastore</w>
+ <w>iconst</w>
+ <w>inflater</w>
+ <w>infos</w>
+ <w>inlined</w>
+ <w>innerclass</w>
+ <w>inputfile</w>
+ <w>insn</w>
+ <w>instantiatable</w>
+ <w>instrumentations</w>
+ <w>intelli</w>
+ <w>interpolator</w>
+ <w>ints</w>
+ <w>invokestatic</w>
+ <w>invokevirtual</w>
+ <w>ipsum</w>
+ <w>ireturn</w>
+ <w>iterable</w>
+ <w>jarfile</w>
+ <w>jarlist</w>
+ <w>jarpath</w>
+ <w>javabuilder</w>
+ <w>javanature</w>
+ <w>jdwp</w>
+ <w>jpeg</w>
+ <w>junit</w>
+ <w>keepclasseswithmembernames</w>
+ <w>keepclasseswithmembers</w>
+ <w>keygen</w>
+ <w>keypass</w>
+ <w>keysexposed</w>
+ <w>keyshidden</w>
+ <w>keyssoft</w>
+ <w>keystore</w>
+ <w>keytool</w>
+ <w>kxml</w>
+ <w>landroid</w>
+ <w>layoublib</w>
+ <w>layoutlib</w>
+ <w>layoutlibs</w>
+ <w>layoutopt</w>
+ <w>layoutrules</w>
+ <w>ldltr</w>
+ <w>ldpi</w>
+ <w>ldrtl</w>
+ <w>levenshtein</w>
+ <w>lexing</w>
+ <w>libc</w>
+ <w>licensable</w>
+ <w>licensor</w>
+ <w>linenumber</w>
+ <w>ljava</w>
+ <w>lombok</w>
+ <w>lookups</w>
+ <w>lookupswitch</w>
+ <w>looper</w>
+ <w>lorem</w>
+ <w>lpackage</w>
+ <w>makefile</w>
+ <w>malloc</w>
+ <w>manifestmerger</w>
+ <w>manifmerger</w>
+ <w>mdpi</w>
+ <w>memalign</w>
+ <w>minsdk</w>
+ <w>mipmap</w>
+ <w>mkdirs</w>
+ <w>monospace</w>
+ <w>moreunit</w>
+ <w>multimap</w>
+ <w>multipart</w>
+ <w>multitouch</w>
+ <w>nano</w>
+ <w>nativelib</w>
+ <w>navexposed</w>
+ <w>navhidden</w>
+ <w>ninepatch</w>
+ <w>nodpi</w>
+ <w>nokeys</w>
+ <w>nonav</w>
+ <w>notlong</w>
+ <w>notnight</w>
+ <w>notouch</w>
+ <w>nullable</w>
+ <w>nulling</w>
+ <w>nullness</w>
+ <w>objectweb</w>
+ <w>opcode</w>
+ <w>opcodes</w>
+ <w>pathname</w>
+ <w>picasa</w>
+ <w>plugin's</w>
+ <w>png's</w>
+ <w>prebuilts</w>
+ <w>prefs</w>
+ <w>preload</w>
+ <w>prepending</w>
+ <w>printf</w>
+ <w>println</w>
+ <w>proc</w>
+ <w>prog</w>
+ <w>progdir</w>
+ <w>programmatically</w>
+ <w>proguard</w>
+ <w>prolog</w>
+ <w>qemu</w>
+ <w>quickfix</w>
+ <w>quickstart</w>
+ <w>qvga</w>
+ <w>rasterize</w>
+ <w>rasterizer</w>
+ <w>realloc</w>
+ <w>recurse</w>
+ <w>reflow</w>
+ <w>reformats</w>
+ <w>reimplement</w>
+ <w>renderscript</w>
+ <w>reparse</w>
+ <w>requestor</w>
+ <w>resampling</w>
+ <w>resizability</w>
+ <w>resized</w>
+ <w>revalidate</w>
+ <w>rrggbb</w>
+ <w>sccs</w>
+ <w>screenshot</w>
+ <w>scroller</w>
+ <w>scrollview</w>
+ <w>sdcard</w>
+ <w>sdk's</w>
+ <w>sdkbin</w>
+ <w>sdklib</w>
+ <w>sdkman</w>
+ <w>sdks</w>
+ <w>serialnumber</w>
+ <w>severities</w>
+ <w>sparsearray</w>
+ <w>sqrt</w>
+ <w>stacktrace</w>
+ <w>stderr</w>
+ <w>stdout</w>
+ <w>stopship</w>
+ <w>storepass</w>
+ <w>storetype</w>
+ <w>styleable</w>
+ <w>subclassed</w>
+ <w>subclassing</w>
+ <w>subfolder</w>
+ <w>submenu</w>
+ <w>superset</w>
+ <w>sysdir</w>
+ <w>sysimg</w>
+ <w>targetsdk</w>
+ <w>testcase</w>
+ <w>testroot</w>
+ <w>testsuite</w>
+ <w>tmpdir</w>
+ <w>traceview</w>
+ <w>tuple</w>
+ <w>tvdpi</w>
+ <w>uiautomator</w>
+ <w>uname</w>
+ <w>unarchive</w>
+ <w>unary</w>
+ <w>uncapitalized</w>
+ <w>uncompressing</w>
+ <w>unescape</w>
+ <w>unescaping</w>
+ <w>unformatted</w>
+ <w>unlocalized</w>
+ <w>unmanages</w>
+ <w>unregister</w>
+ <w>unregisters</w>
+ <w>userdata</w>
+ <w>versioncode</w>
+ <w>vert</w>
+ <w>viewport</w>
+ <w>vmsig</w>
+ <w>wakelock</w>
+ <w>wakelocks</w>
+ <w>wakeup</w>
+ <w>webkit</w>
+ <w>wikipedia</w>
+ <w>workdir</w>
+ <w>wqvga</w>
+ <w>writeable</w>
+ <w>wvga</w>
+ <w>xdpi</w>
+ <w>xerces</w>
+ <w>xfermode</w>
+ <w>xhdpi</w>
+ <w>xhigh</w>
+ <w>xlarge</w>
+ <w>xliff</w>
+ <w>xmlns</w>
+ <w>xxhdpi</w>
+ <w>xxhigh</w>
+ <w>xxxhdpi</w>
+ <w>xxxhigh</w>
+ <w>ydpi</w>
+ <w>yyyy</w>
+ <w>zipalign</w>
+ </words>
+ </dictionary>
+</component> \ No newline at end of file
diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml
index 63323b457a14..c9f9460658ff 100644
--- a/.idea/inspectionProfiles/idea_default.xml
+++ b/.idea/inspectionProfiles/idea_default.xml
@@ -50,7 +50,7 @@
<inspection_tool class="ConstantConditionalExpressionJS" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="ConstantConditions" enabled="true" level="WARNING" enabled_by_default="true">
<scope name="runtime.classes" level="WARNING" enabled="false">
- <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="false" />
+ <option name="SUGGEST_NULLABLE_ANNOTATIONS" value="true" />
<option name="DONT_REPORT_TRUE_ASSERT_STATEMENTS" value="false" />
</scope>
<option name="SUGGEST_NULLABLE_ANNOTATIONS" value="true" />
@@ -318,6 +318,10 @@
<inspection_tool class="MethodNamesDifferOnlyByCase" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MethodOverloadsParentMethod" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MethodOverridesStaticMethod" enabled="true" level="WARNING" enabled_by_default="true" />
+ <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="ERROR" enabled_by_default="true">
+ <option name="ignoreObjectMethods" value="true" />
+ <option name="ignoreAnonymousClassMethods" value="false" />
+ </inspection_tool>
<inspection_tool class="MisspelledCompareTo" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MisspelledEquals" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="MisspelledHashcode" enabled="true" level="WARNING" enabled_by_default="true" />
@@ -563,7 +567,7 @@
<inspection_tool class="UnnecessaryEnumModifier" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="UnnecessaryFullyQualifiedName" enabled="true" level="WARNING" enabled_by_default="true">
<scope name="Tests" level="WARNING" enabled="false">
- <option name="m_ignoreJavadoc" value="false" />
+ <option name="m_ignoreJavadoc" value="true" />
</scope>
<option name="m_ignoreJavadoc" value="true" />
</inspection_tool>
diff --git a/.idea/libraries/asm_tools.xml b/.idea/libraries/asm_tools.xml
new file mode 100644
index 000000000000..6009e9f32e01
--- /dev/null
+++ b/.idea/libraries/asm_tools.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+ <library name="asm-tools">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-4.0.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-analysis-4.0.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/asm-tree-4.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/asm-tools/src-4.0.zip!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/bouncy_castle.xml b/.idea/libraries/bouncy_castle.xml
new file mode 100644
index 000000000000..70ec93b828ec
--- /dev/null
+++ b/.idea/libraries/bouncy_castle.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+ <library name="bouncy-castle">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcpkix-jdk15on/1.48/bcpkix-jdk15on-1.48-sources.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/bouncycastle/bcprov-jdk15on/1.48/bcprov-jdk15on-1.48-sources.jar!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/builder_model.xml b/.idea/libraries/builder_model.xml
new file mode 100644
index 000000000000..c354fae6257d
--- /dev/null
+++ b/.idea/libraries/builder_model.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+ <library name="builder-model">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/builder-model/builder-model-0.12.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/builder-model/builder-model-0.12.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/commons_compress.xml b/.idea/libraries/commons_compress.xml
new file mode 100644
index 000000000000..be33df8d0a7d
--- /dev/null
+++ b/.idea/libraries/commons_compress.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+ <library name="commons-compress">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/commons-compress/commons-compress-1.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/easymock_tools.xml b/.idea/libraries/easymock_tools.xml
new file mode 100644
index 000000000000..d01b8848a450
--- /dev/null
+++ b/.idea/libraries/easymock_tools.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+ <library name="easymock-tools">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/easymock-tools/easymock-3.1-sources.jar!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/fest.xml b/.idea/libraries/fest.xml
new file mode 100644
index 000000000000..df47ca5b53d1
--- /dev/null
+++ b/.idea/libraries/fest.xml
@@ -0,0 +1,17 @@
+<component name="libraryTable">
+ <library name="fest">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-assert-1.2.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-reflect-1.2.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-swing-1.2.1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-util-1.1.3.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-assert-1.2-sources.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-reflect-1.2-sources.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-swing-1.2.1-sources.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/fest/fest-util-1.1.3-sources.jar!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/freemarker_2_3_20.xml b/.idea/libraries/freemarker_2_3_20.xml
new file mode 100644
index 000000000000..b7805a22b23b
--- /dev/null
+++ b/.idea/libraries/freemarker_2_3_20.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+ <library name="freemarker-2.3.20">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20-sources.jar!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/google_api_java_client.xml b/.idea/libraries/google_api_java_client.xml
new file mode 100644
index 000000000000..d76cd722f3eb
--- /dev/null
+++ b/.idea/libraries/google_api_java_client.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+ <library name="google-api-java-client">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/google-api-java-client/1.8.0-rc/google-api-java-client-min-repackaged.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/guava_tools.xml b/.idea/libraries/guava_tools.xml
new file mode 100644
index 000000000000..ac5f2f6b6ec6
--- /dev/null
+++ b/.idea/libraries/guava_tools.xml
@@ -0,0 +1,11 @@
+<component name="libraryTable">
+ <library name="guava-tools">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/google/guava/guava/15.0/guava-15.0-sources.jar!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/junit3_tools.xml b/.idea/libraries/junit3_tools.xml
new file mode 100644
index 000000000000..b3dd3f3b78cd
--- /dev/null
+++ b/.idea/libraries/junit3_tools.xml
@@ -0,0 +1,9 @@
+<component name="libraryTable">
+ <library name="junit3-tools">
+ <CLASSES>
+ <root url="jar://$APPLICATION_HOME_DIR$/lib/junit.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/kxml2.xml b/.idea/libraries/kxml2.xml
new file mode 100644
index 000000000000..688c2383b2be
--- /dev/null
+++ b/.idea/libraries/kxml2.xml
@@ -0,0 +1,13 @@
+<component name="libraryTable">
+ <library name="kxml2">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-2.3.0.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-src-2.3.0.zip!/www/kxml2/javadoc" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/kxml2-tools/kxml2-src-2.3.0.zip!/src" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/lombok_ast.xml b/.idea/libraries/lombok_ast.xml
new file mode 100644
index 000000000000..ef9fe6d90c76
--- /dev/null
+++ b/.idea/libraries/lombok_ast.xml
@@ -0,0 +1,18 @@
+<component name="libraryTable">
+ <library name="lombok-ast">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2.jar!/" />
+ </CLASSES>
+ <JAVADOC>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-javadoc.jar!/" />
+ </JAVADOC>
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/main" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/printer" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/template" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/ecjTransformer" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/src/javacTransformer" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2-sources.jar!/build/lombok.ast_generatedSource" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/libraries/mockito.xml b/.idea/libraries/mockito.xml
new file mode 100644
index 000000000000..7113f6f8f4ec
--- /dev/null
+++ b/.idea/libraries/mockito.xml
@@ -0,0 +1,12 @@
+<component name="libraryTable">
+ <library name="mockito">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5-sources.jar!/" />
+ <root url="jar://$PROJECT_DIR$/../../prebuilts/tools/common/m2/repository/org/mockito/mockito-all/1.9.5/mockito-all-1.9.5.jar!/" />
+ </SOURCES>
+ </library>
+</component> \ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 941f71844ed7..50ad2f06bf87 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -5,6 +5,7 @@
</component>
<component name="FrameworkDetectionExcludesConfiguration">
<file url="file://$PROJECT_DIR$" />
+ <type id="android" />
</component>
<component name="IdProvider" IDEtalkID="88DB5D232B345F18EEFB2825E88EC093" />
<component name="JavadocGenerationManager">
@@ -24,6 +25,30 @@
<option name="LOCALE" />
<option name="OPEN_IN_BROWSER" value="true" />
</component>
+ <component name="NullableNotNullManager">
+ <option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
+ <option name="myDefaultNotNull" value="org.jetbrains.annotations.NotNull" />
+ <option name="myNullables">
+ <value>
+ <list size="4">
+ <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+ <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+ <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+ <item index="3" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
+ </list>
+ </value>
+ </option>
+ <option name="myNotNulls">
+ <value>
+ <list size="4">
+ <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+ <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+ <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+ <item index="3" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
+ </list>
+ </value>
+ </option>
+ </component>
<component name="ProjectDetails">
<option name="projectName" value="idea-community" />
</component>
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 0322352e9df9..2d80274f2dc4 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -10,18 +10,26 @@
<module fileurl="file://$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" filepath="$PROJECT_DIR$/plugins/IntelliLang/IntelliLang-xml.iml" group="plugins/IntelliLang" />
<module fileurl="file://$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" filepath="$PROJECT_DIR$/RegExpSupport/RegExpSupport.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/ShortcutPromoter/ShortcutPromoter.iml" filepath="$PROJECT_DIR$/plugins/ShortcutPromoter/ShortcutPromoter.iml" group="plugins" />
+ <module fileurl="file://$PROJECT_DIR$/../adt/idea/adt-branding/adt-branding.iml" filepath="$PROJECT_DIR$/../adt/idea/adt-branding/adt-branding.iml" group="plugins/Android" />
<module fileurl="file://$PROJECT_DIR$/platform/analysis-api/analysis-api.iml" filepath="$PROJECT_DIR$/platform/analysis-api/analysis-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/analysis-impl/analysis-impl.iml" filepath="$PROJECT_DIR$/platform/analysis-impl/analysis-impl.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/android.iml" filepath="$PROJECT_DIR$/../adt/idea/android/android.iml" group="plugins/Android" />
+ <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/common/android-common.iml" filepath="$PROJECT_DIR$/../adt/idea/android/common/android-common.iml" group="plugins/Android" />
+ <module fileurl="file://$PROJECT_DIR$/../adt/idea/android-gradle-jps/android-gradle-jps.iml" filepath="$PROJECT_DIR$/../adt/idea/android-gradle-jps/android-gradle-jps.iml" group="plugins/Android" />
+ <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/jps-plugin/android-jps-plugin.iml" filepath="$PROJECT_DIR$/../adt/idea/android/jps-plugin/android-jps-plugin.iml" group="plugins/Android" />
+ <module fileurl="file://$PROJECT_DIR$/../adt/idea/android/rt/android-rt.iml" filepath="$PROJECT_DIR$/../adt/idea/android/rt/android-rt.iml" group="plugins/Android" />
<module fileurl="file://$PROJECT_DIR$/platform/annotations/annotations.iml" filepath="$PROJECT_DIR$/platform/annotations/annotations.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/ant/ant.iml" filepath="$PROJECT_DIR$/plugins/ant/ant.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/ant/jps-plugin/ant-jps-plugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/jps/antLayout/antlayout.iml" filepath="$PROJECT_DIR$/jps/antLayout/antlayout.iml" group="jps" />
<module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/runtime/appEngine-runtime.iml" group="plugins/GAE" />
+ <module fileurl="file://$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" filepath="$PROJECT_DIR$/../base/asset-studio/assetstudio.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/platform/boot/boot.iml" filepath="$PROJECT_DIR$/platform/boot/boot.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" filepath="$PROJECT_DIR$/platform/bootstrap/bootstrap.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/build/build.iml" filepath="$PROJECT_DIR$/build/build.iml" />
<module fileurl="file://$PROJECT_DIR$/colorSchemes/colorSchemes.iml" filepath="$PROJECT_DIR$/colorSchemes/colorSchemes.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/commander/commander.iml" filepath="$PROJECT_DIR$/plugins/commander/commander.iml" group="plugins" />
+ <module fileurl="file://$PROJECT_DIR$/../base/common/common.iml" filepath="$PROJECT_DIR$/../base/common/common.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/common-eclipse-util/common-eclipse-util.iml" filepath="$PROJECT_DIR$/plugins/eclipse/common-eclipse-util/common-eclipse-util.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml" filepath="$PROJECT_DIR$/plugins/javaFX/common-javaFX-plugin/common-javaFX-plugin.iml" group="plugins/JavaFX" />
<module fileurl="file://$PROJECT_DIR$/community-main.iml" filepath="$PROJECT_DIR$/community-main.iml" />
@@ -39,6 +47,7 @@
<module fileurl="file://$PROJECT_DIR$/build/cucumber-test-runner/cucumber-test-runner.iml" filepath="$PROJECT_DIR$/build/cucumber-test-runner/cucumber-test-runner.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/cvs/cvs-core/cvs-core.iml" filepath="$PROJECT_DIR$/plugins/cvs/cvs-core/cvs-core.iml" group="plugins/VCS/cvs" />
<module fileurl="file://$PROJECT_DIR$/plugins/cvs/cvs-plugin/cvs-plugin.iml" filepath="$PROJECT_DIR$/plugins/cvs/cvs-plugin/cvs-plugin.iml" group="plugins/VCS/cvs" />
+ <module fileurl="file://$PROJECT_DIR$/../base/ddmlib/ddmlib.iml" filepath="$PROJECT_DIR$/../base/ddmlib/ddmlib.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/java/debugger/impl/debugger-impl.iml" filepath="$PROJECT_DIR$/java/debugger/impl/debugger-impl.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" filepath="$PROJECT_DIR$/java/debugger/openapi/debugger-openapi.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/plugins/devkit/devkit.iml" filepath="$PROJECT_DIR$/plugins/devkit/devkit.iml" group="plugins" />
@@ -46,13 +55,16 @@
<module fileurl="file://$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" filepath="$PROJECT_DIR$/xml/dom-impl/dom-impl.iml" group="xml" />
<module fileurl="file://$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" filepath="$PROJECT_DIR$/xml/dom-openapi/dom-openapi.iml" group="xml" />
<module fileurl="file://$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" filepath="$PROJECT_DIR$/xml/dom-tests/dom-tests.iml" group="xml" />
+ <module fileurl="file://$PROJECT_DIR$/../base/draw9patch/draw9patch.iml" filepath="$PROJECT_DIR$/../base/draw9patch/draw9patch.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" filepath="$PROJECT_DIR$/platform/duplicates-analysis/duplicates-analysis.iml" />
+ <module fileurl="file://$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" filepath="$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" filepath="$PROJECT_DIR$/platform/dvcs-impl/dvcs-impl.iml" group="platform" />
- <module fileurl="file://$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" filepath="$PROJECT_DIR$/platform/dvcs-api/dvcs-api.iml" group="platform"/>
+ <module fileurl="file://$PROJECT_DIR$/../base/device_validator/dvlib/dvlib.iml" filepath="$PROJECT_DIR$/../base/device_validator/dvlib/dvlib.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/eclipse.iml" filepath="$PROJECT_DIR$/plugins/eclipse/eclipse.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" filepath="$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/editor-ui-ex/editor-ui-ex.iml" filepath="$PROJECT_DIR$/platform/editor-ui-ex/editor-ui-ex.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/editorconfig/editorconfig.iml" filepath="$PROJECT_DIR$/plugins/editorconfig/editorconfig.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/java/execution/impl/execution-impl.iml" filepath="$PROJECT_DIR$/java/execution/impl/execution-impl.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/execution/openapi/execution-openapi.iml" filepath="$PROJECT_DIR$/java/execution/openapi/execution-openapi.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/platform/extensions/extensions.iml" filepath="$PROJECT_DIR$/platform/extensions/extensions.iml" group="platform" />
@@ -65,7 +77,10 @@
<module fileurl="file://$PROJECT_DIR$/plugins/github/github.iml" filepath="$PROJECT_DIR$/plugins/github/github.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" group="plugins/GAE" />
<module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" group="plugins/GAE" />
+ <module fileurl="file://$PROJECT_DIR$/../studio/cloud/google-cloud-tools.iml" filepath="$PROJECT_DIR$/../studio/cloud/google-cloud-tools.iml" group="plugins/Google" />
+ <module fileurl="file://$PROJECT_DIR$/../studio/cloud/login/google-login.iml" filepath="$PROJECT_DIR$/../studio/cloud/login/google-login.iml" group="plugins/Google" />
<module fileurl="file://$PROJECT_DIR$/plugins/gradle/gradle.iml" filepath="$PROJECT_DIR$/plugins/gradle/gradle.iml" group="community/plugins/gradle" />
+ <module fileurl="file://$PROJECT_DIR$/../base/gradle-import/gradle-import.iml" filepath="$PROJECT_DIR$/../base/gradle-import/gradle-import.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/gradle/jps-plugin/gradle-jps-plugin.iml" group="community/plugins/gradle" />
<module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-api/gradle-tooling-extension-api.iml" group="community/plugins/gradle" />
<module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-impl/gradle-tooling-extension-impl.iml" group="community/plugins/gradle" />
@@ -116,12 +131,16 @@
<module fileurl="file://$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" filepath="$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/platform/lang-api/lang-api.iml" filepath="$PROJECT_DIR$/platform/lang-api/lang-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" filepath="$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/../base/layoutlib-api/layoutlib-api.iml" filepath="$PROJECT_DIR$/../base/layoutlib-api/layoutlib-api.iml" group="plugins/Android/android-sdk" />
+ <module fileurl="file://$PROJECT_DIR$/../base/lint/libs/lint-api/lint-api.iml" filepath="$PROJECT_DIR$/../base/lint/libs/lint-api/lint-api.iml" group="plugins/Android/android-sdk/lint" />
+ <module fileurl="file://$PROJECT_DIR$/../base/lint/libs/lint-checks/lint-checks.iml" filepath="$PROJECT_DIR$/../base/lint/libs/lint-checks/lint-checks.iml" group="plugins/Android/android-sdk/lint" />
<module fileurl="file://$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" filepath="$PROJECT_DIR$/platform/lvcs-api/lvcs-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" filepath="$PROJECT_DIR$/platform/lvcs-impl/lvcs-impl.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/python/main_idea_python_plugin.iml" filepath="$PROJECT_DIR$/python/main_idea_python_plugin.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/main_pycharm_ce.iml" filepath="$PROJECT_DIR$/python/main_pycharm_ce.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" filepath="$PROJECT_DIR$/python/edu/main_pycharm_edu.iml" group="python/educational" />
<module fileurl="file://$PROJECT_DIR$/java/manifest/manifest.iml" filepath="$PROJECT_DIR$/java/manifest/manifest.iml" group="java" />
+ <module fileurl="file://$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" filepath="$PROJECT_DIR$/../base/build-system/manifest-merger/manifest-merger.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven.iml" filepath="$PROJECT_DIR$/plugins/maven/maven.iml" group="plugins/maven" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" group="plugins/maven" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" group="plugins/maven" />
@@ -130,7 +149,9 @@
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" filepath="$PROJECT_DIR$/plugins/maven/maven-server-api/maven-server-api.iml" group="plugins/maven" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven2-server-impl/maven2-server-impl.iml" group="plugins/maven" />
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" filepath="$PROJECT_DIR$/plugins/maven/maven3-server-impl/maven3-server-impl.iml" group="plugins/maven" />
+ <module fileurl="file://$PROJECT_DIR$/../base/ninepatch/ninepatch.iml" filepath="$PROJECT_DIR$/../base/ninepatch/ninepatch.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/java/openapi/openapi.iml" filepath="$PROJECT_DIR$/java/openapi/openapi.iml" group="java" />
+ <module fileurl="file://$PROJECT_DIR$/../base/perflib/perflib.iml" filepath="$PROJECT_DIR$/../base/perflib/perflib.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-api/platform-api.iml" filepath="$PROJECT_DIR$/platform/platform-api/platform-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" filepath="$PROJECT_DIR$/platform/platform-impl/platform-impl.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/platform-main/platform-main.iml" filepath="$PROJECT_DIR$/platform/platform-main/platform-main.iml" group="platform" />
@@ -168,6 +189,8 @@
<module fileurl="file://$PROJECT_DIR$/python/rest/rest.iml" filepath="$PROJECT_DIR$/python/rest/rest.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/platform/script-debugger/backend/script-debugger-backend.iml" filepath="$PROJECT_DIR$/platform/script-debugger/backend/script-debugger-backend.iml" group="platform/script-debugger" />
<module fileurl="file://$PROJECT_DIR$/platform/script-debugger/debugger-ui/script-debugger-ui.iml" filepath="$PROJECT_DIR$/platform/script-debugger/debugger-ui/script-debugger-ui.iml" group="platform/script-debugger" />
+ <module fileurl="file://$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" filepath="$PROJECT_DIR$/../base/sdk-common/sdk-common.iml" group="plugins/Android/android-sdk" />
+ <module fileurl="file://$PROJECT_DIR$/../base/sdklib/sdklib.iml" filepath="$PROJECT_DIR$/../base/sdklib/sdklib.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/platform/smRunner/smRunner.iml" filepath="$PROJECT_DIR$/platform/smRunner/smRunner.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/cvs/smartcvs-src/smartcvs-src.iml" filepath="$PROJECT_DIR$/plugins/cvs/smartcvs-src/smartcvs-src.iml" group="plugins/VCS/cvs" />
<module fileurl="file://$PROJECT_DIR$/spellchecker/spellchecker.iml" filepath="$PROJECT_DIR$/spellchecker/spellchecker.iml" group="plugins" />
@@ -190,10 +213,12 @@
<module fileurl="file://$PROJECT_DIR$/plugins/testng/testng.iml" filepath="$PROJECT_DIR$/plugins/testng/testng.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/testng_rt/testng_rt.iml" filepath="$PROJECT_DIR$/plugins/testng_rt/testng_rt.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/platform/testFramework/bootstrap/tests_bootstrap.iml" filepath="$PROJECT_DIR$/platform/testFramework/bootstrap/tests_bootstrap.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/../base/testutils/testutils.iml" filepath="$PROJECT_DIR$/../base/testutils/testutils.iml" group="plugins/Android/android-sdk" />
<module fileurl="file://$PROJECT_DIR$/java/typeMigration/typeMigration.iml" filepath="$PROJECT_DIR$/java/typeMigration/typeMigration.iml" />
<module fileurl="file://$PROJECT_DIR$/plugins/ui-designer/ui-designer.iml" filepath="$PROJECT_DIR$/plugins/ui-designer/ui-designer.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/ui-designer-core/ui-designer-core.iml" filepath="$PROJECT_DIR$/plugins/ui-designer-core/ui-designer-core.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/ui-designer/jps-plugin/ui-designer-jps-plugin.iml" group="plugins" />
+ <module fileurl="file://$PROJECT_DIR$/updater/updater.iml" filepath="$PROJECT_DIR$/updater/updater.iml" />
<module fileurl="file://$PROJECT_DIR$/platform/usageView/usageView.iml" filepath="$PROJECT_DIR$/platform/usageView/usageView.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/util/util.iml" filepath="$PROJECT_DIR$/platform/util/util.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/util-rt/util-rt.iml" filepath="$PROJECT_DIR$/platform/util-rt/util-rt.iml" group="platform" />
@@ -220,8 +245,6 @@
<module fileurl="file://$PROJECT_DIR$/plugins/xslt-debugger/engine/xslt-debugger-engine.iml" filepath="$PROJECT_DIR$/plugins/xslt-debugger/engine/xslt-debugger-engine.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/xslt-debugger/engine/impl/xslt-debugger-engine-impl.iml" filepath="$PROJECT_DIR$/plugins/xslt-debugger/engine/impl/xslt-debugger-engine-impl.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/xpath/xslt-rt/xslt-rt.iml" filepath="$PROJECT_DIR$/plugins/xpath/xslt-rt/xslt-rt.iml" group="plugins" />
- <module fileurl="file://$PROJECT_DIR$/plugins/editorconfig/editorconfig.iml" filepath="$PROJECT_DIR$/plugins/editorconfig/editorconfig.iml" group="plugins"/>
-
</modules>
</component>
</project>
diff --git a/.idea/runConfigurations/AndroidStudio.xml b/.idea/runConfigurations/AndroidStudio.xml
new file mode 100644
index 000000000000..c62432ddf2f8
--- /dev/null
+++ b/.idea/runConfigurations/AndroidStudio.xml
@@ -0,0 +1,25 @@
+<component name="ProjectRunConfigurationManager">
+ <configuration default="false" name="AndroidStudio" type="Application" factoryName="Application" singleton="true">
+ <extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
+ <option name="MAIN_CLASS_NAME" value="com.intellij.idea.Main" />
+ <option name="VM_PARAMETERS" value="-ea -Xbootclasspath/p:../out/classes/production/boot -Xms384m -Xmx768m -Didea.is.internal=true -XX:MaxPermSize=384m -Dapple.awt.graphics.UseQuartz=true -Didea.platform.prefix=AndroidStudio -Dandroid.extra_templates.path=../../../sdk/templates -Dapple.laf.useScreenMenuBar=true -Dcom.apple.mrj.application.apple.menu.about.name=AndroidStudio -Dsun.awt.disablegrab=true" />
+ <option name="PROGRAM_PARAMETERS" value="" />
+ <option name="WORKING_DIRECTORY" value="file://$PROJECT_DIR$/bin" />
+ <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
+ <option name="ALTERNATIVE_JRE_PATH" value="" />
+ <option name="ENABLE_SWING_INSPECTOR" value="false" />
+ <option name="ENV_VARIABLES" />
+ <option name="PASS_PARENT_ENVS" value="true" />
+ <module name="community-main" />
+ <envs />
+ <RunnerSettings RunnerId="Debug">
+ <option name="DEBUG_PORT" value="" />
+ <option name="TRANSPORT" value="0" />
+ <option name="LOCAL" value="true" />
+ </RunnerSettings>
+ <RunnerSettings RunnerId="Run" />
+ <ConfigurationWrapper RunnerId="Debug" />
+ <ConfigurationWrapper RunnerId="Run" />
+ <method />
+ </configuration>
+</component> \ No newline at end of file
diff --git a/.idea/scopes/androidplugin.xml b/.idea/scopes/androidplugin.xml
new file mode 100644
index 000000000000..dcc1341cfd15
--- /dev/null
+++ b/.idea/scopes/androidplugin.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+ <scope name="androidplugin" pattern="file[group:Android]:*//*&amp;&amp;!file[group:android-sdk]:*//*" />
+</component> \ No newline at end of file
diff --git a/.idea/scopes/aosp_code.xml b/.idea/scopes/aosp_code.xml
new file mode 100644
index 000000000000..abf77af5586b
--- /dev/null
+++ b/.idea/scopes/aosp_code.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+ <scope name="aosp-code" pattern="test[group:android-sdk]:*..*||src[group:android-sdk]:*..*" />
+</component> \ No newline at end of file
diff --git a/.idea/scopes/obsoleteplugin.xml b/.idea/scopes/obsoleteplugin.xml
new file mode 100644
index 000000000000..0537436e7d19
--- /dev/null
+++ b/.idea/scopes/obsoleteplugin.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+ <scope name="obsoleteplugin" pattern="file[community-main]:plugins/android//*||file[community-main]:plugins/android-designer//*" />
+</component> \ No newline at end of file
diff --git a/.idea/scopes/platform.xml b/.idea/scopes/platform.xml
new file mode 100644
index 000000000000..a0bafd1f53f9
--- /dev/null
+++ b/.idea/scopes/platform.xml
@@ -0,0 +1,3 @@
+<component name="DependencyValidationManager">
+ <scope name="platform" pattern="src:*..*&amp;&amp;!src[group:Android]:*..*" />
+</component> \ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 275077f82558..d10a1db49785 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,6 +2,9 @@
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
+ <mapping directory="$PROJECT_DIR$/../adt/idea" vcs="Git" />
+ <mapping directory="$PROJECT_DIR$/../base" vcs="Git" />
+ <mapping directory="$PROJECT_DIR$/../studio/cloud" vcs="Git" />
</component>
</project>
diff --git a/build.xml b/build.xml
index 8e6bdbcfa226..3df0948be156 100644
--- a/build.xml
+++ b/build.xml
@@ -1,7 +1,23 @@
<project name="IntelliJ IDEA Community Edition" default="all">
<property name="project.home" value="${basedir}"/>
- <property name="out.dir" value="${project.home}/out"/>
- <property name="tmp.dir" value="${project.home}/out/tmp"/>
+
+ <!--
+ Sets the out folder. Defaults to ${basedir}/out.
+ To override, use command line arg "out": e.g. -Dout=/path/
+ -->
+ <condition property="out.dir" value="${out}" else="${project.home}/out">
+ <isset property="out" />
+ </condition>
+
+ <property name="tmp.dir" value="${out.dir}/tmp"/>
+
+ <!--
+ Sets the build number. Defaults to SNAPSHOT.
+ To override, use command line arg "buildNumber": e.g. -DbuildNumber=777
+ -->
+ <condition property="buildId" value="${buildNumber}" else="SNAPSHOT">
+ <isset property="buildNumber" />
+ </condition>
<target name="cleanup">
<delete dir="${out.dir}" failonerror="false"/>
@@ -14,12 +30,17 @@
<macrodef name="call_gant">
<attribute name="script" />
+ <attribute name="test.patterns" default="" />
<sequential>
<java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
+ <jvmarg line="-Xmx1424m -XX:MaxPermSize=352m"/>
+ <jvmarg value="-Dout=${out.dir}" />
+ <jvmarg value="-DbuildNumber=${buildId}" />
<jvmarg line="-Xmx612m -XX:MaxPermSize=152m"/>
<sysproperty key="java.awt.headless" value="true"/>
<arg line="&quot;-Dgant.script=@{script}&quot;"/>
<arg line="&quot;-Dteamcity.build.tempDir=${tmp.dir}&quot;"/>
+ <arg line="&quot;-Didea.test.patterns=@{test.patterns}&quot;"/>
<arg line="&quot;-Didea.test.group=ALL_EXCLUDE_DEFINED&quot;"/>
<arg value="-f"/>
<arg value="${project.home}/build/gant.xml"/>
@@ -32,8 +53,17 @@
</target>
<target name="test" depends="init">
- <call_gant script="${project.home}/build/scripts/tests.gant"/>
+ <call_gant script="${project.home}/build/scripts/tests.gant" test.patterns="org.jetbrains.android.*;com.android.tools.idea.*;com.google.gct.*"/>
+ </target>
+
+ <!-- The build task creates an updater.jar in ${out.dir}. This task bundles log4j & the updater into a single jar -->
+ <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="${project.home}/build/lib/jarjar-1.0.jar"/>
+ <target name="fullupdater" depends="build">
+ <jarjar jarfile="${out.dir}/updater-full.jar">
+ <zipfileset src="${out.dir}/updater.jar" />
+ <zipfileset src="lib/log4j.jar" />
+ </jarjar>
</target>
- <target name="all" depends="cleanup,build"/>
+ <target name="all" depends="cleanup,build,fullupdater"/>
</project>
diff --git a/build/Install-Linux-tar.txt b/build/Install-Linux-tar.txt
index 8c9f0481fd44..2faac26708a9 100644
--- a/build/Install-Linux-tar.txt
+++ b/build/Install-Linux-tar.txt
@@ -11,7 +11,7 @@ INSTALLATION INSTRUCTIONS
2. Open a console and cd into "{installation home}/bin" and type:
- ./@@product@@.sh
+ ./@@script_name@@
to start the application.
diff --git a/build/conf/mac/Contents/Info.plist b/build/conf/mac/Contents/Info.plist
index d13854c5f77a..4a9c7d117dce 100644
--- a/build/conf/mac/Contents/Info.plist
+++ b/build/conf/mac/Contents/Info.plist
@@ -39,11 +39,11 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleGetInfoString</key>
- <string>@@bundle_name@@ @@version@@, build @@build@@. Copyright JetBrains s.r.o., (c) 2000-@@year@@</string>
+ <string>@@bundle_name@@ EAP, build EAP. Copyright @@company_name@@, (c) @@min_year@@-@@max_year@@</string>
<key>CFBundleShortVersionString</key>
- <string>@@version@@</string>
+ <string>EAP</string>
<key>CFBundleVersion</key>
- <string>@@build@@</string>
+ <string>EAP</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>CFBundleHelpBookName</key>
diff --git a/build/gant.xml b/build/gant.xml
index 4b56378f1652..7991950aae81 100644
--- a/build/gant.xml
+++ b/build/gant.xml
@@ -47,6 +47,9 @@
</taskdef>
<target name="doGant">
- <gant file="${gant.script}" target="${gant.target}"/>
+ <gant file="${gant.script}" target="${gant.target}">
+ <definition name="teamcity.build.tempDir" value="${teamcity.build.tempDir}"/>
+ <definition name="idea.test.patterns" value="${idea.test.patterns}"/>
+ </gant>
</target>
</project>
diff --git a/build/scripts/common_tests.gant b/build/scripts/common_tests.gant
index d9e41382c75d..eb21bac9d8a4 100644
--- a/build/scripts/common_tests.gant
+++ b/build/scripts/common_tests.gant
@@ -20,6 +20,10 @@ includeTargets << new File("${guessHome(this)}/build/scripts/cucumber-tests.gant
requireProperty("out", "$home/out")
+target(check: "Ensure the environment is configured") {
+ tempDir = p("teamcity.build.tempDir")
+}
+
target(compile: "Compile project") {
ant.delete(failonerror: false) {
fileset(dir: "$home/reports")
@@ -39,7 +43,7 @@ private pass(String prop) {
}
target('run_tests': 'Run java tests') {
- depends([compile])
+ depends([check, compile])
def classpathFile = "$home/junit.classpath"
List<String> testRuntimeClasspath = projectBuilder.moduleRuntimeClasspath(findModule("community-main"), true)
@@ -84,5 +88,5 @@ target('run_tests': 'Run java tests') {
}
target('default' : "Run all tests") {
- depends([compile, run_tests, run_cucumber_tests])
-} \ No newline at end of file
+ depends([compile, run_tests])
+}
diff --git a/build/scripts/dist.gant b/build/scripts/dist.gant
index a79fb54395d0..a31b66f5a654 100644
--- a/build/scripts/dist.gant
+++ b/build/scripts/dist.gant
@@ -19,6 +19,12 @@ import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
requireProperty("out", "$home/out")
+requireProperty("buildNumber", "SNAPSHOT")
+
+// "out" has to be canonical, otherwise the ant build fails
+// with mysterious errors
+out = new File(out).getCanonicalPath()
+setProperty("out", out)
class Paths {
final sandbox
@@ -62,7 +68,7 @@ target(compile: "Compile project") {
}
private String appInfoFile() {
- return "${projectBuilder.moduleOutput(findModule("community-resources"))}/idea/IdeaApplicationInfo.xml"
+ return "${projectBuilder.moduleOutput(findModule("adt-branding"))}/idea/AndroidStudioApplicationInfo.xml"
}
target('default': 'The default target') {
@@ -73,10 +79,17 @@ target('default': 'The default target') {
zipSources(home, paths.artifacts)
- layoutAll([buildNumber: "IC-$snapshot",
- system_selector: "IdeaIC${p("component.version.major")}",
+ layoutAll([buildNumber: "AI-$snapshot".replaceAll("SNAPSHOT", p("buildNumber")),
+ system_selector: "AndroidStudioPreview",
+ platform_prefix: "AndroidStudio",
+ icns: "${projectBuilder.moduleOutput(findModule("adt-branding"))}/artwork/AndroidStudio.icns",
+ ide_jvm_args: "-Didea.platform.prefix=AndroidStudio",
tools_jar: true],
home, null, paths, true)
+
+ // Generate updater.jar from the updater module (patch updater)
+ projectBuilder.stage("Generating updater in $out")
+ layoutUpdater(out)
}
target('build-dist-jars' : 'Target to build jars from locally compiled classes') {
@@ -84,7 +97,7 @@ target('build-dist-jars' : 'Target to build jars from locally compiled classes')
// load ApplicationInfo.xml properties
ant.xmlproperty(file: appInfoFile(), collapseAttributes: "true")
- layoutAll([buildNumber: "IC-$snapshot",
+ layoutAll([buildNumber: "AI-$snapshot".replaceAll("SNAPSHOT", p("buildNumber")),
system_selector: "IdeaIC${p("component.version.major")}",
tools_jar: true],
home, null, paths)
@@ -93,6 +106,8 @@ target('build-dist-jars' : 'Target to build jars from locally compiled classes')
def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps = false) {
Paths paths = _paths != null ? _paths : new Paths(out)
+ args.companyName = p("component.company.name")
+
wireBuildDate(args.buildNumber, appInfoFile())
ant.echo(message: args.buildNumber, file: "$paths.distAll/build.txt")
@@ -123,44 +138,63 @@ def layoutAll(Map args, String home, String out, Paths _paths = null, buildJps =
layoutMac(args, home, paths)
layoutUnix(args, home, paths)
- buildWinZip("$paths.artifacts/idea${args.buildNumber}.win.zip", [paths.distAll, paths.distWin])
+ def winAppRoot = "android-studio"
+ def macAppRoot = "Android Studio.app"
+ def linTarRoot = "android-studio"
- def macAppRoot = isEap() ?
- "IntelliJ IDEA ${p("component.version.major")} CE EAP.app/Contents" :
- "IntelliJ IDEA ${p("component.version.major")} CE.app/Contents"
+ androidBuildNumber = p("buildNumber")
+ //def macAppRoot = isEap() ?
+ // "IntelliJ IDEA ${p("component.version.major")} CE EAP.app/Contents" :
+ // "IntelliJ IDEA ${p("component.version.major")} CE.app/Contents"
- String macZip = "$paths.artifacts/idea${args.buildNumber}.mac.zip"
- buildMacZip(macAppRoot, macZip, [paths.distAll], paths.distMac)
- notifyArtifactBuilt(macZip)
+ def winZip = "$paths.artifacts/android-studio-${androidBuildNumber}.win.zip"
+ def macZip = "$paths.artifacts/android-studio-${androidBuildNumber}.mac.zip"
+ def linTar = "$paths.artifacts/android-studio-${androidBuildNumber}.tar"
- buildTarGz("idea-${args.buildNumber}", "$paths.artifacts/idea${args.buildNumber}.tar", [paths.distAll, paths.distUnix])
+ buildWinZip(winAppRoot, winZip, [paths.distAll, paths.distWin])
+ buildTarGz(linTarRoot, linTar, [paths.distAll, paths.distUnix])
+ buildMacZip(macAppRoot, macZip, [paths.distAll], paths.distMac)
}
-private layoutWin(Map args, String home, Paths paths) {
+private layoutWin(Map _args, String home, Paths paths) {
String target = paths.distWin
+ Map args = new HashMap(_args)
+ args.product_uc = "ANDROID_STUDIO"
+ args.vm_options = "studio.exe"
+
layout(target) {
dir("bin") {
fileset(dir: "$home/bin/win")
}
}
- ant.copy(file: "$home/platform/icons/src/idea_CE.ico", tofile: "$target/bin/idea.ico")
-
- winScripts(target, home, "idea.bat", args)
- winVMOptions(target, null, "idea.exe", "idea64.exe")
- List resourcePaths = ["$home/community-resources/src", "$home/platform/icons/src"]
- buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher.exe", "$target/bin/idea.exe", appInfoFile(),
- "$home/build/conf/ideaCE-launcher.properties", args.ce_exe_selector, resourcePaths)
- buildWinLauncher(home, "$home/bin/WinLauncher/WinLauncher64.exe", "$target/bin/idea64.exe", appInfoFile(),
- "$home/build/conf/ideaCE64-launcher.properties", args.ce_exe_selector, resourcePaths)
+ ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/androidstudio.ico", tofile: "$target/bin/idea.ico")
+
+ // The 0.1.1 win launcher.
+ ant.copy( file: "$home/../adt/idea/native/WinLauncher/out/Release-Win32/studio.exe",
+ tofile: "$target/bin/studio.exe")
+ ant.copy( file: "$home/../adt/idea/native/WinLauncher/out/Release-Win32/studio.exe.manifest",
+ tofile: "$target/bin/studio.exe.manifest")
+ ant.copy( file: "$home/../adt/idea/native/WinLauncher/out/Release-x64/studio64.exe",
+ tofile: "$target/bin/studio64.exe")
+ ant.copy( file: "$home/../adt/idea/native/WinLauncher/out/Release-x64/studio64.exe.manifest",
+ tofile: "$target/bin/studio64.exe.manifest")
+ // Manual updater script
+ ant.copy( file: "$home/../adt/idea/native/update_studio.bat",
+ tofile: "$target/bin/update_studio.bat")
+
+ winScripts(target, home, "studio.bat", args)
+ winVMOptions(target, args, "studio.exe", "studio64.exe")
}
private layoutMac(Map _args, String home, Paths paths) {
String target = paths.distMac
Map args = new HashMap(_args)
- args.bundleIdentifier = "com.jetbrains.intellij.ce"
+ args.bundleIdentifier = "com.google.android.studio"
+ args.executable = "studio"
+ args.help_id = "AI"
args.doc_types = """
<dict>
<key>CFBundleTypeExtensions</key>
@@ -178,21 +212,34 @@ private layoutMac(Map _args, String home, Paths paths) {
args."idea.properties.path" = "${paths.distAll}/bin/idea.properties"
args.urlSchemes = ["idea"]
args.mac_no_yjp = true
+
+ // Manual updater script
+ ant.copy(file: "$home/../adt/idea/native/update_studio.sh", tofile: "$target/bin/update_studio.sh")
+
layoutMacApp(target, home, args)
}
-private layoutUnix(Map args, String home, Paths paths) {
+private layoutUnix(Map _args, String home, Paths paths) {
String target = paths.distUnix
+ Map args = new HashMap(_args)
+ args.product_uc = "STUDIO"
+ args.vm_options = "studio"
+ args.script_name = "studio.sh"
+
layout(target) {
dir("bin") {
fileset(dir: "$home/bin/linux")
}
}
- ant.copy(file: "$home/platform/icons/src/icon_CE_128.png", tofile: "$target/bin/idea.png")
+ ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/icon_AS_128.png", tofile: "$target/bin/idea.png")
+ ant.copy(file: "$home/../adt/idea/adt-branding/src/artwork/androidstudio.ico", tofile: "$target/bin/androidstudio.ico")
+
+ // Manual updater script
+ ant.copy(file: "$home/../adt/idea/native/update_studio.sh", tofile: "$target/bin/update_studio.sh")
- unixScripts(target, home, "idea.sh", args)
- unixVMOptions(target, "idea")
+ unixScripts(target, home, args.script_name, args)
+ unixVMOptions(target, "studio")
unixReadme(target, home, args)
}
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index e33f920fe146..ba7a556eefe5 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -13,6 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+import org.jetbrains.jps.model.java.JpsJavaClasspathKind
+import org.jetbrains.jps.model.module.JpsLibraryDependency
+import org.jetbrains.jps.model.library.JpsOrderRootType
+import org.jetbrains.jps.util.JpsPathUtil
+
import static org.jetbrains.jps.idea.IdeaProjectLoader.guessHome
includeTargets << new File("${guessHome(this)}/build/scripts/utils.gant")
@@ -24,7 +30,7 @@ target('default': "Developers update") {
}
String appInfoFileName() {
- return "idea/IdeaApplicationInfo.xml"
+ return "idea/AndroidStudioApplicationInfo.xml"
}
String patchAppDescriptor(String targetDirectory) {
@@ -33,12 +39,12 @@ String patchAppDescriptor(String targetDirectory) {
ant.delete(dir: patchedDirectory)
layout(patchedDirectory) {
- module("community-resources") {
+ module("adt-branding") {
include(name: appInfoFileName())
}
}
- ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_NUMBER__", value: "IC-$snapshot")
+ ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_NUMBER__", value: "AI-$snapshot")
ant.replace(file: "$patchedDirectory/${appInfoFileName()}", token: "__BUILD_DATE__", value: new Date().format("yyyyMMddHHmm"))
return patchedDirectory
@@ -152,7 +158,8 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir
module("colorSchemes")
module("resources")
module("platform-resources")
- module("community-resources") {
+ module("community-resources")
+ module("adt-branding") {
if (patchedDescriptorDir != null) {
exclude(name: appInfoFileName())
}
@@ -254,9 +261,8 @@ def layoutFull(String home, String targetDirectory, String patchedDescriptorDir
}
public def layoutCommunityPlugins(String home) {
- if (isDefined("androidPluginHome")) {
- layoutAndroid(p("androidPluginHome"))
- }
+ layoutAndroid()
+ layoutGoogle()
dir("plugins") {
def simplePlugins = ["commander", "copyright", "java-i18n", "hg4idea", "github"] //, "tasks-time-tracking"]
@@ -265,18 +271,21 @@ public def layoutCommunityPlugins(String home) {
layoutPlugin it
}
- layoutPlugin("ant", "ant", "antIntegration") {
- jar("ant-jps-plugin.jar") {
- module("ant-jps-plugin")
- }
- }
- layoutPlugin("uiDesigner", "ui-designer", "uiDesigner") {
- dir("jps") {
- jar("ui-designer-jps-plugin.jar") {
- module("ui-designer-jps-plugin")
- }
- }
- }
+ // ant not needed in AS
+ // layoutPlugin("ant", "ant", "antIntegration") {
+ // jar("ant-jps-plugin.jar") {
+ // module("ant-jps-plugin")
+ // }
+ // }
+
+ // uiDesigner not needed in AS
+ // layoutPlugin("uiDesigner", "ui-designer", "uiDesigner") {
+ // dir("jps") {
+ // jar("ui-designer-jps-plugin.jar") {
+ // module("ui-designer-jps-plugin")
+ // }
+ // }
+ // }
pluginDir("properties") {
dir("lib") {
@@ -383,13 +392,14 @@ public def layoutCommunityPlugins(String home) {
}
}
- pluginDir("ByteCodeViewer") {
- dir("lib") {
- jar("byteCodeViewer.jar") {
- noResources("ByteCodeViewer")
- }
- }
- }
+ // ByteCodeViewer not needed in AS
+ // pluginDir("ByteCodeViewer") {
+ // dir("lib") {
+ // jar("byteCodeViewer.jar") {
+ // noResources("ByteCodeViewer")
+ // }
+ // }
+ // }
pluginDir("cvsIntegration") {
dir("lib") {
@@ -419,36 +429,38 @@ public def layoutCommunityPlugins(String home) {
}
}
- layoutPlugin("xpath") {
- dir("rt") {
- jar("xslt-rt.jar") {module("xslt-rt")}
- }
- }
-
- layoutPlugin("xslt-debugger") {
- jar("xslt-debugger-engine.jar") {
- module("xslt-debugger-engine") {
- excludes: "lib"
- }
- }
- fileset(dir: "$home/plugins/xslt-debugger/engine/lib") {
- include(name: "**/rmi-stubs.jar")
- }
- dir("rt") {
- jar("xslt-debugger-engine-impl.jar") {
- module("xslt-debugger-engine-impl") {
- exclude(name: "lib")
- exclude(name: "**/*.jar")
- exclude(name: "**/*.html")
- }
- }
- fileset(dir: "$home/plugins/xslt-debugger/engine/impl/lib") {
- include(name: "**/*.jar")
- exclude(name: "**/rmi-stubs.jar")
- include(name: "**/*.html")
- }
- }
- }
+ // xpath not needed in AS
+ // layoutPlugin("xpath") {
+ // dir("rt") {
+ // jar("xslt-rt.jar") {module("xslt-rt")}
+ // }
+ // }
+
+ // xslt-debugger not needed in AS
+ // layoutPlugin("xslt-debugger") {
+ // jar("xslt-debugger-engine.jar") {
+ // module("xslt-debugger-engine") {
+ // excludes: "lib"
+ // }
+ // }
+ // fileset(dir: "$home/plugins/xslt-debugger/engine/lib") {
+ // include(name: "**/rmi-stubs.jar")
+ // }
+ // dir("rt") {
+ // jar("xslt-debugger-engine-impl.jar") {
+ // module("xslt-debugger-engine-impl") {
+ // exclude(name: "lib")
+ // exclude(name: "**/*.jar")
+ // exclude(name: "**/*.html")
+ // }
+ // }
+ // fileset(dir: "$home/plugins/xslt-debugger/engine/impl/lib") {
+ // include(name: "**/*.jar")
+ // exclude(name: "**/rmi-stubs.jar")
+ // include(name: "**/*.html")
+ // }
+ // }
+ // }
pluginDir("Groovy") {
dir("lib") {
@@ -495,22 +507,25 @@ public def layoutCommunityPlugins(String home) {
}
}
- layoutPlugin("devkit") {
- jar("devkit-jps-plugin.jar") {
- module("devkit-jps-plugin")
- }
- fileset(dir: "${home}/plugins/devkit/lib") {
- include(name: "**/*.jar")
- }
- }
- layoutPlugin("eclipse") {
- jar("eclipse-jps-plugin.jar") {
- module("eclipse-jps-plugin")
- }
- jar("common-eclipse-util.jar") {
- module("common-eclipse-util")
- }
- }
+ // devkit not needed in AS
+ // layoutPlugin("devkit") {
+ // jar("devkit-jps-plugin.jar") {
+ // module("devkit-jps-plugin")
+ // }
+ // fileset(dir: "${home}/plugins/devkit/lib") {
+ // include(name: "**/*.jar")
+ // }
+ // }
+
+ // eclipse not needed in AS
+ // layoutPlugin("eclipse") {
+ // jar("eclipse-jps-plugin.jar") {
+ // module("eclipse-jps-plugin")
+ // }
+ // jar("common-eclipse-util.jar") {
+ // module("common-eclipse-util")
+ // }
+ // }
layoutPlugin("terminal") {
fileset(dir: "$home/plugins/terminal/lib") {
@@ -565,6 +580,85 @@ public def layoutCommunityPlugins(String home) {
}
}
+def layoutGoogle() {
+ dir("plugins") {
+ layoutPlugin("google-cloud-tools") {
+ jar("google-cloud-tools.jar") {
+ module("google-cloud-tools")
+ }
+ dir("templates") {
+ fileset(dir: "${home}/../studio/cloud/resources/templates")
+ }
+ dir("clientTemplates") {
+ fileset(dir: "${home}/../studio/cloud/resources/clientTemplates")
+ }
+ fileset(dir: "${home}/../studio/cloud/lib") {
+ include(name: "**/*.jar")
+ }
+ }
+ layoutPlugin("google-login") {
+ jar("google-login.jar") {
+ module("google-login")
+ }
+ fileset(dir: "${home}/../studio/cloud/login/lib") {
+ include(name: "**/*.jar")
+ }
+ // Additional libraries that need to be manually copied, see how freemarker
+ // is copied by the Android plugin
+ fileset(file: "${home}/../../prebuilts/tools/common/google-api-java-client/1.8.0-rc/google-api-java-client-min-repackaged.jar")
+ }
+ }
+}
+
+private Set<String> findModuleDependencies(List<String> modules) {
+ Set<String> paths = new HashSet<String>();
+ modules.each {
+ m = findModule(it)
+ m.getDependenciesList().getDependencies().each {
+ projectBuilder.stage("looking at dependency " + it);
+
+ if (it instanceof JpsLibraryDependency) { // only want library dependencies (and not other modules)
+ lib = it.getLibrary()
+ if (lib != null) {
+ libroots = lib.getRoots(JpsOrderRootType.COMPILED) // only want compile (and not test)
+ libroots.each {
+ paths.addAll(JpsPathUtil.urlToFile(it.getUrl()).getAbsolutePath());
+ projectBuilder.stage("Module: " + m.getName() + ", Dependency: " + it.getUrl());
+ }
+ }
+ }
+ }
+ }
+ return paths;
+}
+
+// Obtain the absolute path to the NOTICE file corresponding to the given jar file.
+// The NOTICE file is assumed to be present in the same folder as the jar file. It is an error if it is missing
+private File getNoticeFileForJar(String jarPath) {
+ File parentFile = new File(jarPath).getParentFile()
+ File notice = new File(parentFile, "NOTICE")
+ if (!notice.exists()) {
+ notice = new File(parentFile, "NOTICE.txt")
+ }
+ if (!notice.exists()) {
+ notice = new File(parentFile, "LICENSE.txt")
+ }
+ if (!notice.exists()) {
+ notice = new File(parentFile, "LICENSE")
+ }
+
+ return notice
+}
+
+private void appendToFile(File to, File from) {
+ if (from.exists()) {
+ to.append(from.getName() + ":\n")
+ to.append(from.getText("UTF-8"), "UTF-8")
+ projectBuilder.stage("Appending NOTICE file: " + from.getAbsolutePath())
+ } else {
+ projectBuilder.stage("Skipping non-existent NOTICE file: " + from.getAbsolutePath())
+ }
+}
def layoutPlugin(String moduleName) {
layoutPlugin(moduleName, moduleName, {})
@@ -670,61 +764,106 @@ def reorder(String home, String targetDirectory) {
}
}
-def layoutAndroid(String androidHome) {
+def layoutAndroid() {
dir("plugins") {
- layoutPlugin("android") {
- fileset(dir: "${androidHome}/android/lib") {
- include(name: "**/*.jar")
- exclude(name: "**/ddmlib_1.jar")
- exclude(name: "src/*.jar")
- }
+ def androidModule = "android"
+ dir(androidModule) {
+ dir("lib") {
+ jar("android.jar") {
+ module("ui-designer-core") {
+ patternset(refid: "resources.excluded")
+ }
+ noResources(androidModule)
+ }
- jar("android-common.jar") {
- module("android-common")
- }
+ jar("resources_en.jar") {
+ module(androidModule) {
+ patternset(refid: "resources.included")
+ }
+ module("ui-designer-core") {
+ patternset(refid: "resources.included")
+ }
+ }
- jar("android-rt.jar") {
- module("android-rt")
- }
+ fileset(dir: "${home}/../adt/idea/android/lib") {
+ include(name: "**/*.jar")
+ }
- jar("common.jar") {
- module("common")
- }
- jar("sdklib.jar") {
- module("sdklib")
- }
- jar("layoutlib-api.jar") {
- module("layoutlib-api")
- }
- jar("manifest-merger.jar") {
- module("manifest-merger")
- }
- jar("sdk-tools.jar") {
- module("assetstudio")
- module("ddmlib")
- module("dvlib")
- module("draw9patch")
- module("lint-api")
- module("lint-checks")
- module("ninepatch")
- module("sdk-common")
- module("perflib")
- }
- jar("androidAnnotations.jar") {
- fileset(dir: "$androidHome/android/annotations")
- }
- dir("jps") {
- jar("android-gradle-jps.jar") { module("android-gradle-jps") }
- }
- dir("device-art-resources") {
- fileset(dir: "$androidHome/android/device-art-resources")
- }
+ jar("androidAnnotations.jar") {
+ fileset(dir: "${home}/../adt/idea/android/annotations")
+ }
- dir("jps") {
- jar("android-jps-plugin.jar") { module("android-jps-plugin") }
- }
- dir("templates") {
- fileset(dir: "$androidHome/tools-base/templates")
+ // Add Additional libraries that the Android plugin depends on that come from TOOLS_PREBUILTS.
+ // Note: This is a HACK: rather than encoding the full path, we should really query
+ // the project model for the classpath just like we do for the androidModules' dependencies
+ // below
+ // Also see similar issue in Google Cloud Login plugin
+ fileset(file: "${home}/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/freemarker-2.3.20.jar")
+
+ androidModules = [
+ "assetstudio",
+ "common",
+ "ddmlib",
+ "draw9patch",
+ "dvlib",
+ "layoutlib-api",
+ "lint-api",
+ "lint-checks",
+ "manifest-merger",
+ "ninepatch",
+ "perflib",
+ "sdk-common",
+ "sdklib"
+ ]
+
+ androidModules.each { moduleName ->
+ jar("${moduleName}.jar") {
+ module(moduleName)
+ }
+ }
+
+ // copy over dependencies of all android modules
+ androidModuleDeps = findModuleDependencies(androidModules)
+ androidModuleDeps.each {
+ fileset(file: it)
+ }
+
+ // Create a single NOTICE file with the contents of all the NOTICES of the dependencies.
+ // I couldn't figure out the right ant commands to be able to change the name of the file
+ // when copying, so we'll just call it by its final name (NOTICE)
+ File noticeFile = new File(System.getProperty("java.io.tmpdir") + File.separator + "NOTICE")
+ noticeFile.deleteOnExit()
+ androidModuleDeps.each {
+ appendToFile(noticeFile, getNoticeFileForJar(it))
+ }
+ appendToFile(noticeFile, new File("${home}/../../prebuilts/tools/common/m2/repository/org/freemarker/freemarker/2.3.20/NOTICE"))
+ fileset(file: noticeFile.getPath())
+
+ jar("android-common.jar") {
+ module("android-common")
+ }
+
+ jar("android-rt.jar") {
+ module("android-rt")
+ }
+
+ dir("jps") {
+ jar("android-jps-plugin.jar") { module("android-jps-plugin") }
+ jar("android-gradle-jps.jar") { module("android-gradle-jps") }
+ }
+
+ dir("device-art-resources") {
+ fileset(dir: "${home}/../adt/idea/android/device-art-resources")
+ }
+
+ dir("templates") {
+ fileset(dir: "${home}/../base/templates") {
+ include(name: "activities/**")
+ include(name: "gradle/**")
+ include(name: "other/**")
+ include(name: "gradle-projects/**")
+ }
+ }
}
}
}
diff --git a/build/scripts/tests.gant b/build/scripts/tests.gant
index b512a18dad8d..03b740ccf434 100644
--- a/build/scripts/tests.gant
+++ b/build/scripts/tests.gant
@@ -7,8 +7,8 @@ setProperty("cucumber_test_dirs", [["git4idea", "Idea", "$home/plugins/git4idea/
def isMac = System.getProperty("os.name").toLowerCase().startsWith("mac")
def args = [
- "-Xmx450m",
- "-XX:MaxPermSize=430m",
+ "-Xmx1024m",
+ "-XX:MaxPermSize=630m",
"-XX:ReservedCodeCacheSize=96m"
]
if (isMac) args << "-d32";
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index b090f7a84dd5..7845d32938da 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -56,6 +56,7 @@ binding.setVariable("isEap", {
binding.setVariable("mem32", "-server -Xms128m -Xmx512m -XX:MaxPermSize=250m -XX:ReservedCodeCacheSize=150m")
binding.setVariable("mem64", "-Xms128m -Xmx750m -XX:MaxPermSize=350m -XX:ReservedCodeCacheSize=225m")
binding.setVariable("common_vmoptions", "-ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true " +
+ "-Didea.project.structure.max.errors.to.show=0 " +
"-Djsse.enableSNIExtension=false " +
"-XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50")
@@ -167,7 +168,10 @@ projectBuilder.compressJars = false
binding.setVariable("notifyArtifactBuilt", { String artifactPath ->
if (!artifactPath.startsWith(home)) {
- projectBuilder.error("Artifact path $artifactPath should start with $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("/")) {
@@ -221,7 +225,8 @@ binding.setVariable("copyAndPatchFiles", { Closure files, String target, Map arg
binding.setVariable("wireBuildDate", { String buildNumber, String appInfoFile ->
ant.tstamp()
- patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP])
+ patchFiles([appInfoFile], ["BUILD_NUMBER": buildNumber, "BUILD_DATE": DSTAMP,
+ "PACKAGE_CODE": buildNumber.substring(0, buildNumber.indexOf('-'))])
})
binding.setVariable("commonJvmArgs", {
@@ -232,9 +237,10 @@ binding.setVariable("commonJvmArgs", {
"-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"]
+ "-Didea.config.path=${p("teamcity.build.tempDir")}/config"]
+ // We don't want this on the Jenkins build server
+ // "-Xdebug",
+ // "-Xrunjdwp:transport=dt_socket,server=y,suspend=$suspendUntilDebuggerConnect,address=$debugPort"]
})
binding.setVariable("classPathLibs", [
@@ -402,6 +408,9 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args ->
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)
@@ -429,8 +438,8 @@ binding.setVariable("layoutMacApp", { String path, String ch, Map args ->
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()
- String vm_options = args.vm_options != null ? args.vm_options : "${p("component.names.product").toLowerCase()}.exe"
+ 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")
}
@@ -503,14 +512,19 @@ binding.setVariable("unixScripts", { String target, String home, String name, Ma
ant.fixcrlf(srcdir: "$target/bin", includes: "*.sh", eol: "unix")
})
-binding.setVariable("winVMOptions", { String target, String system_selector, String name, String name64 = null ->
+binding.setVariable("winVMOptions", { String target, Map args, String name, String name64 = null ->
if (name != null) {
- def options = isEap() && system_selector != null ? vmOptions32yjp(system_selector) : vmOptions32()
+ 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 = isEap() && system_selector != null ? vmOptions64yjp(system_selector) : vmOptions64()
+ 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'))
}
@@ -534,6 +548,7 @@ binding.setVariable("unixReadme", { String target, String home, Map args ->
["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")
})
@@ -690,14 +705,14 @@ private String submapToXml(Map properties, List keys) {
return buff.toString()
}
-binding.setVariable("buildWinZip", { String zipPath, List paths ->
+binding.setVariable("buildWinZip", { String zipRoot, String zipPath, List paths ->
projectBuilder.stage(".win.zip")
fixIdeaPropertiesEol(paths, "dos")
ant.zip(zipfile: zipPath) {
paths.each {
- fileset(dir: it)
+ zipfileset(dir: it, prefix: zipRoot)
}
}
@@ -816,6 +831,14 @@ binding.setVariable("buildWinLauncher", { String ch, String inputPath, String ou
}
})
+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();
diff --git a/build_ide_ext.sh b/build_ide_ext.sh
new file mode 100755
index 000000000000..bc8109a55014
--- /dev/null
+++ b/build_ide_ext.sh
@@ -0,0 +1,66 @@
+#!/bin/bash
+# Expected arguments:
+# $1 = out_dir
+# $2 = qualifier (ignored, optional)
+# $3 = build_number or preview-<build_number>
+# $4 = --target ...
+
+PROG_DIR=$(dirname "$0")
+
+DEST=""
+QUAL=""
+BNUM=""
+TARGET=""
+
+function die() {
+ echo "$*" > /dev/stderr
+ echo "Usage: $0 [--keep] dest_dir [date] build_number [--target build]" > /dev/stderr
+ exit 1
+}
+
+while [[ -n "$1" ]]; do
+ if [[ "$1" == "--target" ]]; then
+ shift
+ TARGET="$1"
+ elif [[ "${1:0:2}" == "--" ]]; then
+ die "[$0] Unknown parameter: $1"
+ elif [[ -z "$DEST" ]]; then
+ DEST="$1"
+ elif [[ -z "$QUAL" ]]; then
+ QUAL="$1"
+ elif [[ -z "$BNUM" ]]; then
+ BNUM="$1"
+ else
+ die "[$0] Unknown parameter: $1"
+ fi
+ shift
+done
+
+if [[ -z $BNUM && -n $QUAL ]]; then
+ BNUM="$QUAL"
+ QUAL=""
+fi
+BNUM="${BNUM/preview-/}"
+
+if [[ -z "$DEST" ]]; then die "## Error: Missing dest_dir"; fi
+if [[ -z "$BNUM" ]]; then die "## Error: Missing build_number"; fi
+
+cd $PROG_DIR
+
+OUT="../../out/host/android-studio"
+mkdir -p "$OUT"
+
+ANT="java -jar lib/ant/lib/ant-launcher.jar -f build.xml"
+
+echo "## Building android-studio ##"
+echo "## Dest dir : $DEST"
+echo "## Qualifier: $QUAL"
+echo "## Build Num: $BNUM"
+echo "## Target : $TARGET"
+echo
+
+$ANT "-Dout=$OUT" "-DbuildNumber=$BNUM" $TARGET
+
+echo "## Copying android-studio destination files"
+cp -rfv $OUT/artifacts/android-studio* $DEST/
+cp -rfv $OUT/updater-full.jar $DEST/android-studio-updater.jar
diff --git a/build_studio.sh b/build_studio.sh
new file mode 100755
index 000000000000..d7bed52e9e8a
--- /dev/null
+++ b/build_studio.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Expected arguments:
+# $1 = out_dir
+# $2 = dist_dir
+# $3 = build_number
+
+PROG_DIR=$(dirname "$0")
+
+function die() {
+ echo "$*" > /dev/stderr
+ echo "Usage: $0 <out_dir> <dest_dir> <build_number>" > /dev/stderr
+ exit 1
+}
+
+while [[ -n "$1" ]]; do
+ if [[ -z "$OUT" ]]; then
+ OUT="$1"
+ elif [[ -z "$DIST" ]]; then
+ DIST="$1"
+ elif [[ -z "$BNUM" ]]; then
+ BNUM="$1"
+ else
+ die "[$0] Unknown parameter: $1"
+ fi
+ shift
+done
+
+if [[ -z "$OUT" ]]; then die "## Error: Missing out folder"; fi
+if [[ -z "$DIST" ]]; then die "## Error: Missing destination folder"; fi
+if [[ -z "$BNUM" ]]; then die "## Error: Missing build number"; fi
+
+cd "$PROG_DIR"
+
+mkdir -p "$OUT"
+
+ANT="java -jar lib/ant/lib/ant-launcher.jar -f build.xml"
+
+echo "## Building android-studio ##"
+echo "## Dest dir : $DIST"
+echo "## Qualifier: $QUAL"
+echo "## Build Num: $BNUM"
+echo
+
+$ANT "-Dout=$OUT" "-DbuildNumber=$BNUM"
+
+echo "## Copying android-studio destination files"
+cp -rfv "$OUT"/artifacts/android-studio* "$DIST"/
+cp -rfv "$OUT"/updater-full.jar "$DIST"/android-studio-updater.jar
diff --git a/community-main.iml b/community-main.iml
index 51f709d431a1..124943e8a84a 100644
--- a/community-main.iml
+++ b/community-main.iml
@@ -82,6 +82,8 @@
<orderEntry type="module" module-name="tasks-tests" />
<orderEntry type="module" module-name="github" />
<orderEntry type="module" module-name="hg4idea" />
+ <orderEntry type="module" module-name="android" />
+ <orderEntry type="module" module-name="adt-branding" />
<orderEntry type="module" module-name="relaxng" />
<orderEntry type="module" module-name="gradle" />
<orderEntry type="module" module-name="remote-servers-impl" />
@@ -99,6 +101,8 @@
<orderEntry type="module" module-name="ui-designer-jps-plugin" scope="TEST" />
<orderEntry type="module" module-name="java-tests" scope="TEST" />
<orderEntry type="module" module-name="community-tests" scope="TEST" />
+ <orderEntry type="module" module-name="google-cloud-tools" />
+ <orderEntry type="module" module-name="google-login" />
<orderEntry type="module" module-name="jira" />
<orderEntry type="module" module-name="java-decompiler" />
<orderEntry type="module" module-name="structuralsearch" />
diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java
index ce8a2d0f14e9..fd72b556b709 100644..100755
--- a/platform/bootstrap/src/com/intellij/idea/Main.java
+++ b/platform/bootstrap/src/com/intellij/idea/Main.java
@@ -17,6 +17,7 @@ package com.intellij.idea;
import com.intellij.ide.Bootstrap;
import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.openapi.util.io.FileUtilRt;
@@ -26,11 +27,13 @@ import com.intellij.util.Restarter;
import javax.swing.*;
import java.awt.*;
import java.io.*;
-import java.util.ArrayList;
-import java.util.Collections;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
import java.util.List;
import java.util.Locale;
+
@SuppressWarnings({"UseOfSystemOutOrSystemErr", "MethodNamesDifferingOnlyByCase"})
public class Main {
public static final int UPDATE_FAILED = 1;
@@ -43,6 +46,8 @@ public class Main {
private static final String PLATFORM_PREFIX_PROPERTY = "idea.platform.prefix";
private static final String[] NO_ARGS = {};
+ private static final String MAIN_LOG_PROPERTY = "com.intellij.idea.Main.DelayedLog";
+
private static boolean isHeadless;
private static boolean isCommandLine;
@@ -68,8 +73,9 @@ public class Main {
installPatch();
}
catch (Throwable t) {
+ appendLog("Exception: " + t.toString() + '\n');
showMessage("Update Failed", t);
- System.exit(UPDATE_FAILED);
+ exit(UPDATE_FAILED);
}
}
}
@@ -79,10 +85,15 @@ public class Main {
}
catch (Throwable t) {
showMessage("Start Failed", t);
- System.exit(STARTUP_EXCEPTION);
+ exit(STARTUP_EXCEPTION);
}
}
+ private static void exit(int code) {
+ dumpDelayedLogging();
+ System.exit(code);
+ }
+
public static boolean isHeadless() {
return isHeadless;
}
@@ -130,13 +141,19 @@ public class Main {
File patchCopy = new File(tempDir, patchFileName + "_copy");
File log4jCopy = new File(tempDir, "log4j.jar." + platform + "_copy");
if (!FileUtilRt.delete(patchCopy) || !FileUtilRt.delete(log4jCopy)) {
+ appendLog("Cannot delete temporary files in " + tempDir);
throw new IOException("Cannot delete temporary files in " + tempDir);
}
File patch = new File(tempDir, patchFileName);
+ appendLog("[Patch] Original patch %s: %s\n", patch.exists() ? "exists" : "does not exist",
+ patch.getAbsolutePath());
if (!patch.exists()) return;
File log4j = new File(PathManager.getLibPath(), "log4j.jar");
- if (!log4j.exists()) throw new IOException("Log4J missing: " + log4j);
+ if (!log4j.exists()) {
+ appendLog("Log4J missing: " + log4j);
+ throw new IOException("Log4J missing: " + log4j);
+ }
copyFile(patch, patchCopy, true);
copyFile(log4j, log4jCopy, false);
@@ -151,7 +168,7 @@ public class Main {
//noinspection SpellCheckingInspection
Collections.addAll(args,
- System.getProperty("java.home") + "/bin/java",
+ System.getProperty("java.home") + "/bin/java".replace('/', File.separatorChar),
"-Xmx500m",
"-classpath",
patchCopy.getPath() + File.pathSeparator + log4jCopy.getPath(),
@@ -162,14 +179,19 @@ public class Main {
"install",
PathManager.getHomePath());
+ appendLog("[Patch] Restarted cmd: %s\n", args.toString());
+
status = Restarter.scheduleRestart(ArrayUtilRt.toStringArray(args));
+
+ appendLog("[Patch] Restarted status: %d\n", status);
}
else {
+ appendLog("[Patch] Restart is not supported\n");
String message = "Patch update is not supported - please do it manually";
showMessage("Update Error", message, true);
}
- System.exit(status);
+ exit(status);
}
private static void copyFile(File original, File copy, boolean move) throws IOException {
@@ -193,6 +215,12 @@ public class Main {
message.append(studio ? "code.google.com/p/android/issues" : "youtrack.jetbrains.com");
message.append("\n\n");
t.printStackTrace(new PrintWriter(message));
+
+ String p = System.getProperty(MAIN_LOG_PROPERTY);
+ if (p != null) {
+ message.append('\n').append(p);
+ }
+
showMessage(title, message.toString(), true);
}
@@ -226,4 +254,60 @@ public class Main {
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), scrollPane, title, type);
}
}
+
+
+ /**
+ * Appends the non-null string to an internal log property because at
+ * this point when the updater runs the main logger hasn't been setup yet.
+ *
+ * We use a system property rather than a global static variable because
+ * both codes do not run in the same ClassLoader and don't have the same
+ * globals.
+ */
+ private static void appendLog(String message, Object...params) {
+ String p = System.getProperty(MAIN_LOG_PROPERTY);
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ");
+ String s = dateFormat.format(new Date()) + String.format(message, params);
+ if (p == null) {
+ p = s;
+ } else {
+ p += s;
+ }
+ System.setProperty(MAIN_LOG_PROPERTY, p);
+ }
+
+ /** Invoked by Main to dump the log when the Main is exiting right away.
+ * The normal IDE log will not be used. */
+ public static void dumpDelayedLogging() {
+ String p = System.getProperty(MAIN_LOG_PROPERTY);
+ if (p != null) {
+ System.clearProperty(MAIN_LOG_PROPERTY);
+ File log = new File(PathManager.getLogPath());
+ //noinspection ResultOfMethodCallIgnored
+ log.mkdirs();
+ log = new File(log, "idea_patch.log");
+ FileOutputStream fos = null;
+ try {
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ fos = new FileOutputStream(log, true /*append*/);
+ fos.write(p.getBytes("UTF-8"));
+ } catch (IOException ignore) {
+ } finally {
+ if (fos != null) {
+ try { fos.close(); } catch (IOException ignored) {}
+ }
+ }
+ }
+ }
+
+ /** Invoked by StartupUtil once the main logger is setup. */
+ public static void dumpDelayedLogging(Logger log) {
+ if (log != null) {
+ String p = System.getProperty(MAIN_LOG_PROPERTY);
+ if (p != null) {
+ log.info(p);
+ System.clearProperty(MAIN_LOG_PROPERTY);
+ }
+ }
+ }
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
index 6e1740c4fbcb..f240681b82e6 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/AbstractExternalSystemSettings.java
@@ -18,6 +18,7 @@ package com.intellij.openapi.externalSystem.settings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NotNull;
@@ -107,6 +108,9 @@ public abstract class AbstractExternalSystemSettings<
}
}
}
+ if (ps == null) {
+ ps = myLinkedProjectsSettings.get(FileUtil.toSystemIndependentName(linkedProjectPath));
+ }
return ps;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
index dc47793401e0..0f47fbefd536 100644
--- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
@@ -224,7 +224,7 @@ public class ScopeViewPane extends AbstractProjectViewPane {
@Override
public int getWeight() {
- return 3;
+ return 200; // was 3, changed to 200 in Android Studio so that has a lower weight than the Android view.
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
index dfe5e6375df4..ac296d677232 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
@@ -1009,6 +1009,11 @@ public class IdeErrorsDialog extends DialogWrapper implements MessagePoolListene
return getCorePluginSubmitter(reporters);
}
for (ErrorReportSubmitter reporter : reporters) {
+ /** Android Studio: Always use the android error reporter */
+ String canonicalName = reporter.getClass().getCanonicalName();
+ if (canonicalName != null && canonicalName.contains("android")) {
+ return reporter;
+ }
final PluginDescriptor descriptor = reporter.getPluginDescriptor();
if (descriptor != null && Comparing.equal(pluginId, descriptor.getPluginId())) {
return reporter;
diff --git a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
index e49cef42cc81..8c41a8e30ab6 100644
--- a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
+++ b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
@@ -65,7 +65,7 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter {
}
private void checkJvm() {
- if (StringUtil.containsIgnoreCase(System.getProperty("java.vm.name", ""), "OpenJDK") && !SystemInfo.isJavaVersionAtLeast("1.7")) {
+ if (StringUtil.containsIgnoreCase(System.getProperty("java.vm.name", ""), "OpenJDK")) {
notifyUnsupportedJvm("unsupported.jvm.openjdk.message");
}
else if (StringUtil.endsWithIgnoreCase(System.getProperty("java.version", ""), "-ea")) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
index fce491bfeb08..4a72eda21a3e 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
@@ -47,6 +47,7 @@ public class SendFeedbackAction extends AnAction implements DumbAware {
urlTemplate = urlTemplate
.replace("$BUILD", eap ? appInfo.getBuild().asStringWithoutProductCode() : appInfo.getBuild().asString())
.replace("$TIMEZONE", System.getProperty("user.timezone"))
+ .replace("$VERSION", appInfo.getFullVersion())
.replace("$EVAL", isEvaluationLicense() ? "true" : "false")
.replace("$DESCR", getDescription());
BrowserUtil.browse(urlTemplate, project);
diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
index 10f9c7365cfe..43c0a2d298f1 100644..100755
--- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
+++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
@@ -130,6 +130,7 @@ public class StartupUtil {
Logger log = Logger.getInstance(Main.class);
startLogging(log);
loadSystemLibraries(log);
+ Main.dumpDelayedLogging(log);
fixProcessEnvironment(log);
if (!Main.isHeadless()) {
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
index 0e5ac83289a0..28a17e261f97 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/updater/SendStatisticsProjectComponent.java
@@ -71,18 +71,7 @@ public class SendStatisticsProjectComponent implements ProjectComponent {
StatisticsNotificationManager.showNotification(statisticsService, myProject);
}
else if (StatisticsUploadAssistant.isSendAllowed() && StatisticsUploadAssistant.isTimeToSend()) {
- StatisticsService serviceToUse = null;
- StatisticsServiceEP[] extensions = StatisticsService.EP_NAME.getExtensions();
- if (extensions.length > 1) {
- LOG.warn(String.format("More than one stats service detected (%s). Falling back to the built-in one", Arrays.toString(extensions)));
- }
- else if (extensions.length == 1) {
- serviceToUse = extensions[0].getInstance();
- }
- if (serviceToUse == null) {
- serviceToUse = statisticsService;
- }
- runWithDelay(serviceToUse);
+ runWithDelay(statisticsService);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
index 51809addc44c..8120b0644675 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
@@ -132,6 +132,27 @@ public class ConfigImportHelper {
maxFile = file;
}
}
+
+ // Android Studio: Attempt to find user settings from earlier versions where the settings names
+ // are different from the current setting name
+ if (maxFile == null) {
+ File preview = new File(PathManager.getDefaultConfigPathFor("AndroidStudioPreview"));
+ File beta = new File(PathManager.getDefaultConfigPathFor("AndroidStudioBeta")); // relevant when we switch from beta to stable
+ for (File file : new File[] { preview, beta }) {
+ if (!file.isDirectory()) {
+ continue;
+ }
+ File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
+ if (options.exists()) {
+ final long modified = options.lastModified();
+ if (modified > lastModified) {
+ lastModified = modified;
+ maxFile = file;
+ }
+ }
+ }
+ }
+
return maxFile != null ? new File(maxFile, CONFIG_RELATED_PATH) : null;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
index b7c133fb0740..b4adf378942e 100644..100755
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/ChannelStatus.java
@@ -28,10 +28,25 @@ public class ChannelStatus implements Comparable<ChannelStatus> {
@NonNls public static final String EAP_CODE = "eap";
@NonNls public static final String RELEASE_CODE = "release";
- public static final ChannelStatus EAP = new ChannelStatus(0, EAP_CODE, "Early Access Program");
- public static final ChannelStatus MILESTONE = new ChannelStatus(1, "milestone", "Milestone Releases");
- public static final ChannelStatus BETA = new ChannelStatus(2, "beta", "Beta Releases or Public Previews");
- public static final ChannelStatus RELEASE = new ChannelStatus(3, RELEASE_CODE, "New Major Version Releases");
+ /**
+ * EAP is our Canary Channel.
+ * <p/>
+ * From the updates.xml description: <br/>
+ * Canary builds are the bleeding edge, released about weekly. While these builds do get tested,
+ * they are still subject to bugs, as we want people to see what's new as soon as possible.
+ * This is not recommended for production.
+ */
+ public static final ChannelStatus EAP = new ChannelStatus(0, EAP_CODE, "Canary Channel");
+ /**
+ * Milestone is our Dev Channel.
+ * <p/>
+ * From the updates.xml description: <br/>
+ * Dev channel builds are hand-picked older canary builds that survived the test of time.
+ * It's updated roughly every month.
+ */
+ public static final ChannelStatus MILESTONE = new ChannelStatus(1, "milestone", "Dev Channel");
+ public static final ChannelStatus BETA = new ChannelStatus(2, "beta", "Beta Channel");
+ public static final ChannelStatus RELEASE = new ChannelStatus(3, RELEASE_CODE, "Stable Channel");
private static final List<ChannelStatus> ALL_TYPES = ContainerUtil.immutableList(RELEASE, BETA, MILESTONE, EAP);
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
index 83858cc4fb40..f1206ef190f1 100644..100755
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.updateSettings.impl;
+import com.google.common.net.HttpHeaders;
import com.intellij.diagnostic.IdeErrorsDialog;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.*;
@@ -774,10 +775,31 @@ public final class UpdateChecker {
String platform = PlatformUtils.getPlatformPrefix();
File tempFile = FileUtil.createTempFile(platform, "patch", true);
+ LOG.info(String.format("[Patch] Download %s to %s", fileName, tempFile.getAbsolutePath()));
OutputStream out = new BufferedOutputStream(new FileOutputStream(tempFile));
try {
- URLConnection connection = HttpConfigurable.getInstance().openConnection(new URL(new URL(getPatchesUrl()), fileName).toString());
+ String requestUrl = new URL(new URL(getPatchesUrl()), fileName).toString();
+ URLConnection connection;
+
+ int followCount = 2;
+ while(true) {
+ connection = HttpConfigurable.getInstance().openConnection(requestUrl);
+
+ if (connection instanceof HttpURLConnection) {
+ HttpURLConnection hcnx = (HttpURLConnection)connection;
+ int code = hcnx.getResponseCode();
+ if (code >= 301 && code <= 307 && --followCount >= 0) {
+ String loc = hcnx.getHeaderField(HttpHeaders.LOCATION);
+ if (loc != null) {
+ requestUrl = loc;
+ continue;
+ }
+ }
+ }
+ break;
+ }
+
try {
InputStream in = UrlConnectionUtil.getConnectionInputStreamWithException(connection, i);
try {
@@ -819,6 +841,7 @@ public final class UpdateChecker {
File patchFile = new File(FileUtil.getTempDirectory(), patchFileName);
FileUtil.copy(tempFile, patchFile);
FileUtil.delete(tempFile);
+ LOG.info(String.format("[Patch] moved to %s", patchFile.getAbsolutePath()));
}
public static Set<String> getDisabledToUpdatePlugins() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
index 9c6c6a2020e5..97082c394aaf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdatesXmlLoader.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.updateSettings.impl;
+import com.google.common.net.HttpHeaders;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.reporter.ConnectionException;
import com.intellij.openapi.application.ApplicationManager;
@@ -31,6 +32,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Callable;
@@ -68,10 +70,29 @@ public class UpdatesXmlLoader {
URL requestUrl = prepareRequestUrl(updateUrl);
- URLConnection connection = requestUrl.openConnection();
- connection.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
- connection.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
- final InputStream inputStream = connection.getInputStream();
+ URLConnection cnx;
+ int followCount = 2;
+ while(true) {
+ cnx = requestUrl.openConnection();
+ cnx.setConnectTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+ cnx.setReadTimeout(HttpConfigurable.CONNECTION_TIMEOUT);
+
+ if (cnx instanceof HttpURLConnection) {
+ HttpURLConnection hcnx = (HttpURLConnection)cnx;
+ int code = hcnx.getResponseCode();
+ if (code >= 301 && code <= 307 && --followCount >= 0) {
+ String loc = hcnx.getHeaderField(HttpHeaders.LOCATION);
+ if (loc != null) {
+ prepareUrl(loc);
+ requestUrl = prepareRequestUrl(loc);
+ continue;
+ }
+ }
+ }
+ break;
+ }
+
+ final InputStream inputStream = cnx.getInputStream();
Reader reader = new InputStreamReader(inputStream);
try {
return new UpdatesInfo(JDOMUtil.loadDocument(inputStream).getRootElement());
diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties
index 016c62b9f601..05e73117e044 100644
--- a/platform/platform-resources-en/src/messages/IdeBundle.properties
+++ b/platform/platform-resources-en/src/messages/IdeBundle.properties
@@ -1099,7 +1099,7 @@ FileChooser.refreshActionLabelText=Refresh
browsers.settings=Web Browsers
updates.check.period.on.exit=On every exit
-unsupported.jvm.openjdk.message=OpenJDK 6 is not supported. Please use Oracle Java or newer OpenJDK.
+unsupported.jvm.openjdk.message=OpenJDK shows intermittent performance and UI issues. We recommend using the Oracle JRE/JDK.
unsupported.jvm.ea.message=Early Access Java versions may cause compatibility issues. Please use stable release.
unsupported.jvm.link=<br/><a href="#">Do not show again</a>.
diff --git a/plugins/android/lib/guava-15.0.jar b/plugins/android/lib/guava-15.0.jar
new file mode 100644
index 000000000000..eb9ef8ad5fff
--- /dev/null
+++ b/plugins/android/lib/guava-15.0.jar
Binary files differ
diff --git a/plugins/android/lib/jarutils.jar b/plugins/android/lib/jarutils.jar
new file mode 100644
index 000000000000..1259ccfd6e44
--- /dev/null
+++ b/plugins/android/lib/jarutils.jar
Binary files differ
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
index 30fb81af6075..d17b9fdea764 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
@@ -331,6 +331,10 @@ public class GradleScriptType extends GroovyRunnableScriptType {
}
}
+ if (result == GlobalSearchScope.EMPTY_SCOPE) {
+ result = baseScope;
+ }
+
String modulePath = module.getOptionValue(ExternalSystemConstants.LINKED_PROJECT_PATH_KEY);
if(modulePath == null) return result;
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
index 199db3a52538..bfe3d1466ae3 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/Maven3ServerIndexerImpl.java
@@ -207,7 +207,8 @@ public class Maven3ServerIndexerImpl extends MavenRemoteObject implements MavenS
throw new MavenServerProcessCanceledException();
}
catch (Exception e) {
- throw new MavenServerIndexerException(wrapException(e));
+ // Disabled in Android Studio, no need to know about this exception
+ // throw new MavenServerIndexerException(wrapException(e));
}
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
index 83ed5047b023..5f301ac7a15e 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/CreationTool.java
@@ -16,8 +16,10 @@
package com.intellij.designer.designSurface.tools;
import com.intellij.designer.designSurface.OperationContext;
+import com.intellij.designer.model.RadComponent;
import java.util.Collections;
+import java.util.List;
/**
* @author Alexander Lobas
@@ -49,6 +51,11 @@ public class CreationTool extends AbstractCreationTool {
@Override
protected void updateTarget() {
- myTargetOperation.setComponent(myContext.getComponents().get(0));
+ if (myTargetOperation != null && myContext != null) {
+ List<RadComponent> components = myContext.getComponents();
+ if (components != null && !components.isEmpty()) {
+ myTargetOperation.setComponent(components.get(0));
+ }
+ }
}
} \ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
index a44a34398d3c..5ad9e4465ec5 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/PropertyTablePanel.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.PopupHandler;
@@ -85,7 +86,11 @@ public final class PropertyTablePanel extends JPanel implements ListSelectionLis
actionGroup.addSeparator();
RestoreDefault restoreDefault = new RestoreDefault(myPropertyTable);
- restoreDefault.registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_DELETE).getShortcutSet(), myPropertyTable);
+ // Don't register ACTION_DELETE on Mac; on Mac, the default delete key is VK_DELETE rather than VK_BACK_SPACE
+ // which means users end up accidentally restoring to default when trying to edit inside property editors.
+ if (!SystemInfo.isMac) {
+ restoreDefault.registerCustomShortcutSet(actionManager.getAction(IdeActions.ACTION_DELETE).getShortcutSet(), myPropertyTable);
+ }
actionGroup.add(restoreDefault);
actionGroup.add(new ShowExpert(myPropertyTable));
diff --git a/resources-en/src/tips/Welcome.html b/resources-en/src/tips/Welcome.html
index 7301e9483c11..6d8381a5728f 100644
--- a/resources-en/src/tips/Welcome.html
+++ b/resources-en/src/tips/Welcome.html
@@ -4,7 +4,7 @@
</head>
<body>
<h1>
- Welcome to <span class="product">&productName;</span> <span class="version">&majorVersion;</span></h1>
+ Welcome to <span class="product">&productName;</span> <span class="version">&majorVersion;.&minorVersion;<</span></h1>
<p>
You can quickly get familiar with the main features of the IDE by reading these tips. You may try out
the features described in the tips while this dialog stays open on the screen. If you close the dialog,
diff --git a/updater/src/com/intellij/updater/BaseUpdateAction.java b/updater/src/com/intellij/updater/BaseUpdateAction.java
index 1d5e5a1cc78f..67a16f8eb4ca 100644..100755
--- a/updater/src/com/intellij/updater/BaseUpdateAction.java
+++ b/updater/src/com/intellij/updater/BaseUpdateAction.java
@@ -35,7 +35,13 @@ public abstract class BaseUpdateAction extends PatchAction {
protected void replaceUpdated(File from, File dest) throws IOException {
// on OS X code signing caches seem to be associated with specific file ids, so we need to remove the original file.
- if (!dest.delete()) throw new IOException("Cannot delete file " + dest);
+ if (!dest.delete()) {
+ if (Utils.isWindows()) {
+ throw new RetryException("Cannot delete file " + dest);
+ } else {
+ throw new IOException("Cannot delete file " + dest);
+ }
+ }
Utils.copy(from, dest);
}
diff --git a/updater/src/com/intellij/updater/CreateAction.java b/updater/src/com/intellij/updater/CreateAction.java
index e1a3fa1dabdc..5b0f8df595a5 100644..100755
--- a/updater/src/com/intellij/updater/CreateAction.java
+++ b/updater/src/com/intellij/updater/CreateAction.java
@@ -59,7 +59,15 @@ public class CreateAction extends PatchAction {
private static void prepareToWriteFile(File file) throws IOException {
if (file.exists()) {
- Utils.delete(file);
+ try {
+ Utils.delete(file);
+ } catch (IOException e) {
+ if (Utils.isWindows() && file.exists()) {
+ throw new RetryException(e);
+ } else {
+ throw e;
+ }
+ }
return;
}
diff --git a/updater/src/com/intellij/updater/DeleteAction.java b/updater/src/com/intellij/updater/DeleteAction.java
index 3dd1b850e415..286e4710f9e1 100644..100755
--- a/updater/src/com/intellij/updater/DeleteAction.java
+++ b/updater/src/com/intellij/updater/DeleteAction.java
@@ -43,13 +43,23 @@ public class DeleteAction extends PatchAction {
@Override
protected void doApply(ZipFile patchFile, File toFile) throws IOException {
- Utils.delete(toFile);
+ try {
+ Utils.delete(toFile);
+ } catch (IOException e) {
+ if (Utils.isWindows() && toFile.exists()) {
+ throw new RetryException(e);
+ } else {
+ throw e;
+ }
+ }
}
+ @Override
protected void doBackup(File toFile, File backupFile) throws IOException {
Utils.copy(toFile, backupFile);
}
+ @Override
protected void doRevert(File toFile, File backupFile) throws IOException {
Utils.delete(toFile); // make sure there is no directory remained on this path (may remain from previous 'create' actions
Utils.copy(backupFile, toFile);
diff --git a/updater/src/com/intellij/updater/Digester.java b/updater/src/com/intellij/updater/Digester.java
index 00792ce00321..ba6a4703e241 100644..100755
--- a/updater/src/com/intellij/updater/Digester.java
+++ b/updater/src/com/intellij/updater/Digester.java
@@ -28,7 +28,8 @@ public class Digester {
zipFile = new ZipFile(file);
}
catch (IOException e) {
- Runner.printStackTrace(e);
+ // If this isn't a zip file, this isn't really an error, merely an info.
+ Runner.infoStackTrace("Can't open file as zip file: " + file.getPath() + "\n", e);
return doDigestRegularFile(file);
}
diff --git a/updater/src/com/intellij/updater/RetryException.java b/updater/src/com/intellij/updater/RetryException.java
new file mode 100755
index 000000000000..e13c4eb0f2c8
--- /dev/null
+++ b/updater/src/com/intellij/updater/RetryException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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 com.intellij.updater;
+
+import java.io.IOException;
+
+/**
+ * Exception thrown when an IOException arises when performing a patch
+ * action and it's likely that retrying will be successful.
+ */
+public class RetryException extends IOException {
+ public RetryException() {
+ }
+
+ public RetryException(String message) {
+ super(message);
+ }
+
+ public RetryException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public RetryException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/updater/src/com/intellij/updater/Runner.java b/updater/src/com/intellij/updater/Runner.java
index 1e57010543e9..d0143a946b0c 100644..100755
--- a/updater/src/com/intellij/updater/Runner.java
+++ b/updater/src/com/intellij/updater/Runner.java
@@ -38,11 +38,22 @@ public class Runner {
create(oldVersionDesc, newVersionDesc, oldFolder, newFolder, patchFile, ignoredFiles, criticalFiles, optionalFiles);
}
else if (args.length >= 2 && "install".equals(args[0])) {
- String destFolder = args[1];
+ // install [--exit0] <destination_folder>
+ int nextArg = 1;
+
+ // Default install exit code is SwingUpdaterUI.RESULT_REQUIRES_RESTART (42) unless overridden to be 0.
+ // This is used by testUI/build.gradle as gradle expects a javaexec to exit with code 0.
+ boolean useExitCode0 = false;
+ if (args[nextArg].equals("--exit0")) {
+ useExitCode0 = true;
+ nextArg++;
+ }
+
+ String destFolder = args[nextArg++];
initLogger();
logger.info("destFolder: " + destFolder);
- install(destFolder);
+ install(useExitCode0, destFolder);
}
else {
printUsage();
@@ -93,6 +104,10 @@ public class Runner {
}
}
+ public static void infoStackTrace(String msg, Throwable e){
+ logger.info(msg, e);
+ }
+
public static void printStackTrace(Throwable e){
logger.error(e.getMessage(), e);
}
@@ -115,8 +130,8 @@ public class Runner {
private static void printUsage() {
System.err.println("Usage:\n" +
"create <old_version_description> <new_version_description> <old_version_folder> <new_version_folder>" +
- " <patch_file_name> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
- "install <destination_folder> [log_directory]\n");
+ " <patch_file_name> <log_directory> [ignored=file1;file2;...] [critical=file1;file2;...] [optional=file1;file2;...]\n" +
+ "install [--exit0] <destination_folder> [log_directory]\n");
}
private static void create(String oldBuildDesc,
@@ -127,9 +142,31 @@ public class Runner {
List<String> ignoredFiles,
List<String> criticalFiles,
List<String> optionalFiles) throws IOException, OperationCancelledException {
- UpdaterUI ui = new ConsoleUpdaterUI();
+ File tempPatchFile = Utils.createTempFile();
+ createImpl(oldBuildDesc,
+ newBuildDesc,
+ oldFolder,
+ newFolder,
+ patchFile,
+ tempPatchFile,
+ ignoredFiles,
+ criticalFiles,
+ optionalFiles,
+ new ConsoleUpdaterUI(), resolveJarFile());
+ }
+
+ static void createImpl(String oldBuildDesc,
+ String newBuildDesc,
+ String oldFolder,
+ String newFolder,
+ String outPatchJar,
+ File tempPatchFile,
+ List<String> ignoredFiles,
+ List<String> criticalFiles,
+ List<String> optionalFiles,
+ UpdaterUI ui,
+ File resolvedJar) throws IOException, OperationCancelledException {
try {
- File tempPatchFile = Utils.createTempFile();
PatchFileCreator.create(new File(oldFolder),
new File(newFolder),
tempPatchFile,
@@ -138,13 +175,13 @@ public class Runner {
optionalFiles,
ui);
- logger.info("Packing jar file: " + patchFile );
- ui.startProcess("Packing jar file '" + patchFile + "'...");
+ logger.info("Packing jar file: " + outPatchJar );
+ ui.startProcess("Packing jar file '" + outPatchJar + "'...");
- FileOutputStream fileOut = new FileOutputStream(patchFile);
+ FileOutputStream fileOut = new FileOutputStream(outPatchJar);
try {
ZipOutputWrapper out = new ZipOutputWrapper(fileOut);
- ZipInputStream in = new ZipInputStream(new FileInputStream(resolveJarFile()));
+ ZipInputStream in = new ZipInputStream(new FileInputStream(resolvedJar));
try {
ZipEntry e;
while ((e = in.getNextEntry()) != null) {
@@ -186,7 +223,7 @@ public class Runner {
Utils.cleanup();
}
- private static void install(final String destFolder) throws Exception {
+ private static void install(final boolean useExitCode0, final String destFolder) throws Exception {
InputStream in = Runner.class.getResourceAsStream("/" + PATCH_PROPERTIES_ENTRY);
Properties props = new Properties();
try {
@@ -213,7 +250,9 @@ public class Runner {
new SwingUpdaterUI(props.getProperty(OLD_BUILD_DESCRIPTION),
props.getProperty(NEW_BUILD_DESCRIPTION),
+ useExitCode0 ? 0 : SwingUpdaterUI.RESULT_REQUIRES_RESTART,
new SwingUpdaterUI.InstallOperation() {
+ @Override
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
logger.info("installing patch to the " + destFolder);
return doInstall(ui, destFolder);
@@ -221,11 +260,26 @@ public class Runner {
});
}
+ interface IJarResolver {
+ File resolveJar() throws IOException;
+ }
+
private static boolean doInstall(UpdaterUI ui, String destFolder) throws OperationCancelledException {
+ return doInstallImpl(ui, destFolder, new IJarResolver() {
+ @Override
+ public File resolveJar() throws IOException {
+ return resolveJarFile();
+ }
+ });
+ }
+
+ static boolean doInstallImpl(UpdaterUI ui,
+ String destFolder,
+ IJarResolver jarResolver) throws OperationCancelledException {
try {
try {
File patchFile = Utils.createTempFile();
- ZipFile jarFile = new ZipFile(resolveJarFile());
+ ZipFile jarFile = new ZipFile(jarResolver.resolveJar());
logger.info("Extracting patch file...");
ui.startProcess("Extracting patch file...");
diff --git a/updater/src/com/intellij/updater/SwingUpdaterUI.java b/updater/src/com/intellij/updater/SwingUpdaterUI.java
index d44fc2e094f1..749dcc2fc350 100644..100755
--- a/updater/src/com/intellij/updater/SwingUpdaterUI.java
+++ b/updater/src/com/intellij/updater/SwingUpdaterUI.java
@@ -10,6 +10,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
+import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
@@ -19,7 +20,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicBoolean;
public class SwingUpdaterUI implements UpdaterUI {
- private static final int RESULT_REQUIRES_RESTART = 42;
+ static final int RESULT_REQUIRES_RESTART = 42;
private static final EmptyBorder FRAME_BORDER = new EmptyBorder(8, 8, 8, 8);
private static final EmptyBorder LABEL_BORDER = new EmptyBorder(0, 0, 5, 0);
@@ -32,6 +33,7 @@ public class SwingUpdaterUI implements UpdaterUI {
private static final String PROCEED_BUTTON_TITLE = "Proceed";
+ private final int mySuccessExitCode;
private final InstallOperation myOperation;
private final JLabel myProcessTitle;
@@ -40,16 +42,30 @@ public class SwingUpdaterUI implements UpdaterUI {
private final JTextArea myConsole;
private final JPanel myConsolePane;
+ private final JButton myRetryButton;
private final JButton myCancelButton;
private final ConcurrentLinkedQueue<UpdateRequest> myQueue = new ConcurrentLinkedQueue<UpdateRequest>();
private final AtomicBoolean isCancelled = new AtomicBoolean(false);
private final AtomicBoolean isRunning = new AtomicBoolean(false);
private final AtomicBoolean hasError = new AtomicBoolean(false);
+ private final AtomicBoolean hasRetry = new AtomicBoolean(false);
private final JFrame myFrame;
private boolean myApplied;
- public SwingUpdaterUI(String oldBuildDesc, String newBuildDesc, InstallOperation operation) {
+ /**
+ * Displays the updater UI and asynchronously runs the operation list.
+ *
+ * @param oldBuildDesc The old build description, for display purposes.
+ * @param newBuildDesc The new build description, for display purposes.
+ * @param successExitCode The desired exit code on success. Default is {@link #RESULT_REQUIRES_RESTART}.
+ * @param operation The install operations to perform.
+ */
+ public SwingUpdaterUI(String oldBuildDesc,
+ String newBuildDesc,
+ int successExitCode,
+ InstallOperation operation) {
+ mySuccessExitCode = successExitCode;
myOperation = operation;
myProcessTitle = new JLabel(" ");
@@ -58,6 +74,10 @@ public class SwingUpdaterUI implements UpdaterUI {
myCancelButton = new JButton(CANCEL_BUTTON_TITLE);
+ myRetryButton = new JButton("Retry");
+ myRetryButton.setEnabled(false);
+ myRetryButton.setVisible(false);
+
myConsole = new JTextArea();
myConsole.setLineWrap(true);
myConsole.setWrapStyleWord(true);
@@ -70,11 +90,19 @@ public class SwingUpdaterUI implements UpdaterUI {
myConsolePane.setVisible(false);
myCancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
doCancel();
}
});
+ myRetryButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ doRetry();
+ }
+ });
+
myFrame = new JFrame();
myFrame.setTitle(TITLE);
@@ -104,6 +132,7 @@ public class SwingUpdaterUI implements UpdaterUI {
buttonsPanel.setBorder(BUTTONS_BORDER);
buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.X_AXIS));
buttonsPanel.add(Box.createHorizontalGlue());
+ buttonsPanel.add(myRetryButton);
buttonsPanel.add(myCancelButton);
myProcessTitle.setText("<html>Updating " + oldBuildDesc + " to " + newBuildDesc + "...");
@@ -129,6 +158,7 @@ public class SwingUpdaterUI implements UpdaterUI {
private void startRequestDispatching() {
new Thread(new Runnable() {
+ @Override
public void run() {
while (true) {
try {
@@ -146,6 +176,7 @@ public class SwingUpdaterUI implements UpdaterUI {
}
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
for (UpdateRequest each : pendingRequests) {
each.perform();
@@ -172,10 +203,28 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
+ private void doRetry() {
+ hasError.set(false);
+ hasRetry.set(false);
+ isCancelled.set(false);
+ myQueue.add(new UpdateRequest() {
+ @Override
+ public void perform() {
+ myConsole.setText("");
+ myConsolePane.setVisible(false);
+ myConsolePane.setPreferredSize(new Dimension(10, 200));
+ myRetryButton.setEnabled(false);
+ myCancelButton.setEnabled(true);
+ }
+ });
+ doPerform();
+ }
+
private void doPerform() {
isRunning.set(true);
new Thread(new Runnable() {
+ @Override
public void run() {
try {
myApplied = myOperation.execute(SwingUpdaterUI.this);
@@ -190,6 +239,10 @@ public class SwingUpdaterUI implements UpdaterUI {
finally {
isRunning.set(false);
+ if (hasRetry.get()) {
+ myRetryButton.setVisible(true);
+ myRetryButton.setEnabled(true);
+ }
if (hasError.get()) {
startProcess("Failed to apply patch");
setProgress(100);
@@ -204,15 +257,17 @@ public class SwingUpdaterUI implements UpdaterUI {
}
private void exit() {
- System.exit(myApplied ? RESULT_REQUIRES_RESTART : 0);
+ System.exit(myApplied ? mySuccessExitCode : 0);
}
+ @Override
public Map<String, ValidationResult.Option> askUser(final List<ValidationResult> validationResults) throws OperationCancelledException {
if (validationResults.isEmpty()) return Collections.emptyMap();
final Map<String, ValidationResult.Option> result = new HashMap<String, ValidationResult.Option>();
try {
SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
public void run() {
final JDialog dialog = new JDialog(myFrame, TITLE, true);
dialog.setLayout(new BorderLayout());
@@ -224,6 +279,7 @@ public class SwingUpdaterUI implements UpdaterUI {
buttonsPanel.add(Box.createHorizontalGlue());
JButton proceedButton = new JButton(PROCEED_BUTTON_TITLE);
proceedButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
}
@@ -231,6 +287,7 @@ public class SwingUpdaterUI implements UpdaterUI {
JButton cancelButton = new JButton(CANCEL_BUTTON_TITLE);
cancelButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
isCancelled.set(true);
myCancelButton.setEnabled(false);
@@ -287,8 +344,10 @@ public class SwingUpdaterUI implements UpdaterUI {
return result;
}
+ @Override
public void startProcess(final String title) {
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
myProcessStatus.setText(title);
myProcessProgress.setIndeterminate(false);
@@ -297,8 +356,10 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
+ @Override
public void setProgress(final int percentage) {
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
myProcessProgress.setIndeterminate(false);
myProcessProgress.setValue(percentage);
@@ -306,21 +367,43 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
+ @Override
public void setProgressIndeterminate() {
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
myProcessProgress.setIndeterminate(true);
}
});
}
+ @Override
public void setStatus(final String status) {
}
+ @Override
public void showError(final Throwable e) {
hasError.set(true);
+ StringWriter w = new StringWriter();
+
+ if (e instanceof RetryException) {
+ hasRetry.set(true);
+
+ w.write("+----------------\n");
+ w.write("| A file operation failed.\n");
+ w.write("| This might be due to a file being locked by another\n");
+ w.write("| application. Please try closing any application\n");
+ w.write("| that uses the files being updated then press 'Retry'.\n");
+ w.write("+----------------\n");
+ w.write("\n\n");
+ }
+
+ e.printStackTrace(new PrintWriter(w));
+
+ final String content = w.getBuffer().toString();
myQueue.add(new UpdateRequest() {
+ @Override
public void perform() {
StringWriter w = new StringWriter();
if (!myConsolePane.isVisible()) {
@@ -328,9 +411,8 @@ public class SwingUpdaterUI implements UpdaterUI {
w.write(System.getProperty("java.io.tmpdir"));
w.write("\n\n");
}
- e.printStackTrace(new PrintWriter(w));
- w.append("\n");
myConsole.append(w.getBuffer().toString());
+ myConsole.append(content);
if (!myConsolePane.isVisible()) {
myConsole.setCaretPosition(0);
myConsolePane.setVisible(true);
@@ -341,6 +423,7 @@ public class SwingUpdaterUI implements UpdaterUI {
});
}
+ @Override
public void checkCancelled() throws OperationCancelledException {
if (isCancelled.get()) throw new OperationCancelledException();
}
@@ -354,7 +437,8 @@ public class SwingUpdaterUI implements UpdaterUI {
}
public static void main(String[] args) {
- new SwingUpdaterUI("xxx", "yyy", new InstallOperation() {
+ new SwingUpdaterUI("xxx", "yyy", RESULT_REQUIRES_RESTART, new InstallOperation() {
+ @Override
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
ui.startProcess("Process1");
ui.checkCancelled();
@@ -438,6 +522,7 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
+ @Override
public int getColumnCount() {
return COLUMNS.length;
}
@@ -464,6 +549,7 @@ public class SwingUpdaterUI implements UpdaterUI {
return super.getColumnClass(columnIndex);
}
+ @Override
public int getRowCount() {
return myItems.size();
}
@@ -480,6 +566,7 @@ public class SwingUpdaterUI implements UpdaterUI {
}
}
+ @Override
public Object getValueAt(int rowIndex, int columnIndex) {
Item item = myItems.get(rowIndex);
switch (columnIndex) {
diff --git a/updater/src/com/intellij/updater/Utils.java b/updater/src/com/intellij/updater/Utils.java
index 959a93cee1c2..b5ad212ac1a9 100644..100755
--- a/updater/src/com/intellij/updater/Utils.java
+++ b/updater/src/com/intellij/updater/Utils.java
@@ -10,10 +10,19 @@ public class Utils {
private static final byte[] BUFFER = new byte[64 * 1024];
private static File myTempDir;
+ public static boolean isWindows() {
+ return System.getProperty("os.name").startsWith("Windows");
+ }
+
public static boolean isZipFile(String fileName) {
return fileName.endsWith(".zip") || fileName.endsWith(".jar");
}
+ /**
+ * Creates a new temp file. <br/>
+ * All the temp files created here are located in a unique root temp directory
+ * that is automatically deleted by {@link #cleanup()}.
+ */
@SuppressWarnings({"SSBasedInspection"})
public static File createTempFile() throws IOException {
if (myTempDir == null) {
@@ -26,6 +35,12 @@ public class Utils {
return File.createTempFile("temp.", ".tmp", myTempDir);
}
+
+ /**
+ * Creates a new temp directory. <br/>
+ * All the temp directories created here are located in a unique root temp directory
+ * that is automatically deleted by {@link #cleanup()}.
+ */
public static File createTempDir() throws IOException {
File result = createTempFile();
delete(result);
@@ -42,6 +57,15 @@ public class Utils {
myTempDir = null;
}
+ /**
+ * Deletes a file or directory with a default timeout of 100 milliseconds.
+ * Directories are deleted recursively. The timeout occurs on each file.
+ * If one of the files fails to be deleted, the recursive directory deletion
+ * is aborted and not retried.
+ *
+ * @param file The file or directory to delete.
+ * @throws IOException
+ */
public static void delete(File file) throws IOException {
if (file.isDirectory()) {
File[] files = file.listFiles();
@@ -52,16 +76,20 @@ public class Utils {
}
}
}
+
for (int i = 0; i < 10; i++) {
- if (file.delete() || !file.exists()) return;
+ if (file.delete() || !file.exists()) {
+ return;
+ }
try {
Thread.sleep(10);
- }
- catch (InterruptedException ignore) {
+ } catch (InterruptedException ignore) {
Runner.printStackTrace(ignore);
}
}
- if (file.exists()) throw new IOException("Cannot delete file " + file);
+ if (file.exists()) {
+ throw new IOException("Cannot delete file " + file);
+ }
}
public static void setExecutable(File file, boolean executable) throws IOException {
diff --git a/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java b/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java
new file mode 100644
index 000000000000..577c2bc88de0
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/RunnerAdditionalTest.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * 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 com.intellij.updater;
+
+import junit.framework.TestCase;
+
+import java.io.*;
+import java.nio.charset.Charset;
+import java.util.*;
+
+public class RunnerAdditionalTest extends TestCase {
+ private final LinkedList<File> myFiles = new LinkedList<File>();
+ private final ArrayList<NamePair> myFileNames = new ArrayList<NamePair>();
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myFiles.clear();
+ myFileNames.clear();
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+
+ while (!myFiles.isEmpty()) {
+ remove(myFiles.removeLast());
+ }
+ }
+
+ public void testUpdater1() throws Exception {
+ File dir1 = add(createTempDir("old", ".dir"));
+ File dir2 = add(createTempDir("new", ".dir"));
+ File f3 = add(createFileContent(dir1, "something.txt", "Content version 1"));
+ File f4 = add(createFileContent(dir2, "something.txt", "Content version 2"));
+ File inputJar5 = add(File.createTempFile("input", ".jar"));
+ File tmpPatch6 = add(File.createTempFile("temp", ".patch"));
+ final File patch7 = add(File.createTempFile("output", ".jar"));
+
+ createEmptyJar(inputJar5);
+
+ //noinspection ResultOfMethodCallIgnored
+ patch7.delete();
+ assertFalse(patch7.exists());
+
+ MockUpdaterUI ui1 = new MockUpdaterUI();
+ Runner.createImpl("1.2", //oldBuildDesc
+ "1.3", //newBuildDesc
+ dir1.getAbsolutePath(), //oldFolder
+ dir2.getAbsolutePath(), //newFolder
+ patch7.getAbsolutePath(), //outPatchJar
+ tmpPatch6, //tempPatchFile
+ new ArrayList<String>(), //ignoredFiles
+ new ArrayList<String>(), //criticalFiles
+ new ArrayList<String>(), //optionalFiles
+ ui1, //ui
+ inputJar5); //resolvedJar
+
+ assertEquals(
+ "[Start ] Calculating difference...\n" +
+ "[Status ] something.txt\n" +
+ "[Status ] something.txt\n" +
+ "[Start ] Preparing actions...\n" +
+ "[Status ] something.txt\n" +
+ "[Start ] Creating the patch file 'file-6_temp.patch'...\n" +
+ "[Status ] Packing something.txt\n" +
+ "[Start ] Packing jar file 'file-7_output.jar'...\n" +
+ "[Start ] Cleaning up...\n" +
+ "[Indeterminate Progress]\n",
+ ui1.toString());
+ assertTrue(patch7.exists());
+
+ File dir8 = add(createTempDir("extracted", ".dir"));
+ File f9 = add(createFileContent(dir8, "something.txt", "Content version 1"));
+ assertTrue(f9.exists());
+
+ MockUpdaterUI ui2 = new MockUpdaterUI();
+ Runner.doInstallImpl(ui2,
+ dir8.getAbsolutePath(),
+ new Runner.IJarResolver() {
+ @Override
+ public File resolveJar() throws IOException {
+ return patch7;
+ }
+ });
+ assertEquals(
+ "[Start ] Extracting patch file...\n" +
+ "[Indeterminate Progress]\n" +
+ "[Start ] Validating installation...\n" +
+ "[Status ] something.txt\n" +
+ "[Progress] 100\n" +
+ "[Start ] Backing up files...\n" +
+ "[Status ] something.txt\n" +
+ "[Progress] 100\n" +
+ "[Start ] Applying patch...\n" +
+ "[Status ] something.txt\n" +
+ "[Progress] 100\n" +
+ "[Start ] Cleaning up...\n" +
+ "[Indeterminate Progress]\n",
+ ui2.toString());
+ assertEquals("Content version 2", getFileContent(f9));
+ }
+
+ //---- utilities -----
+
+ private File createTempDir(String prefix, String suffix) throws IOException {
+ File d = File.createTempFile(prefix, suffix);
+ if (!d.delete()) throw new IOException("Failed to delete directory " + d.getAbsolutePath());
+ if (!d.mkdirs()) throw new IOException("Failed to mkdirs " + d.getAbsolutePath());
+ return d;
+ }
+
+ private static void createEmptyJar(File jar) throws IOException {
+ FileOutputStream outStream = new FileOutputStream(jar);
+ try {
+ ZipOutputWrapper out = new ZipOutputWrapper(outStream);
+
+ // zip file can't be empty, add one dummy entry
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ baos.write("dummy entry".getBytes("UTF-8"));
+ out.zipBytes("dummy.txt", baos);
+
+ out.finish();
+ } finally {
+ outStream.close();
+ }
+ }
+
+ private File add(File f) {
+ myFiles.add(f);
+
+ String unique = f.getName().replaceAll("[^a-zA-Z.]", "");
+ NamePair fromTo = new NamePair(f.getAbsolutePath(),
+ (f.isDirectory() ? "dir-" : "file-") + (myFileNames.size() + 1) + '_' + unique);
+ myFileNames.add(fromTo);
+ Collections.sort(myFileNames);
+ return f;
+ }
+
+ private String getFileContent(File file) throws IOException {
+ if (!file.exists()) throw new IOException("File not found, expected file: " + replaceFileNames(file.getAbsolutePath()));
+ BufferedReader br = new BufferedReader(new FileReader(file));
+ try {
+ return br.readLine();
+ } finally {
+ br.close();
+ }
+ }
+
+ private static File createFileContent(File parentDir, String fileName, String fileContent) throws IOException {
+ File f = new File(parentDir, fileName);
+ OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(f), Charset.forName("UTF-8"));
+ try {
+ fw.write(fileContent);
+ } finally {
+ fw.close();
+ }
+ return f;
+ }
+
+ private static void remove(File... files) {
+ for (File f : files) {
+ if (f != null && f.exists()) {
+ if (!f.delete()) {
+ f.deleteOnExit();
+ }
+ }
+ }
+ }
+
+ private String replaceFileNames(String str) {
+ for (NamePair name : myFileNames) {
+ str = str.replace(name.getFrom(), name.getTo());
+ }
+ return str;
+ }
+
+ /**
+ * A list of from->to name pairs, ordered by descending from
+ * (to get the longer ones first.)
+ */
+ private static class NamePair implements Comparable<NamePair> {
+ private final String myFrom;
+ private final String myTo;
+
+ public NamePair(String from, String to) {
+ myFrom = from;
+ myTo = to;
+ }
+
+ public String getFrom() {
+ return myFrom;
+ }
+
+ public String getTo() {
+ return myTo;
+ }
+
+ @Override
+ public int compareTo(NamePair n2) {
+ return -1 * this.getFrom().compareTo(n2.getFrom());
+ }
+ }
+
+ /**
+ * Mock UpdaterUI that dumps all the text to a string buffer, which can be
+ * grabbed using toString(). It also replaces all the filenames using the
+ * provided name pair list.
+ */
+ private class MockUpdaterUI implements UpdaterUI {
+ private final StringBuilder myOutput = new StringBuilder();
+
+ private MockUpdaterUI() {
+ }
+
+ @Override
+ public void startProcess(String title) {
+ title = replaceFileNames(title);
+ myOutput.append("[Start ] ").append(title).append('\n');
+ }
+
+ @Override
+ public void setProgress(int percentage) {
+ myOutput.append("[Progress] ").append(percentage).append('\n');
+ }
+
+ @Override
+ public void setProgressIndeterminate() {
+ myOutput.append("[Indeterminate Progress]\n");
+ }
+
+ @Override
+ public void setStatus(String status) {
+ status = replaceFileNames(status);
+ myOutput.append("[Status ] ").append(status).append('\n');
+ }
+
+ @Override
+ public void showError(Throwable e) {
+ myOutput.append("[Error ] ").append(e.toString()).append('\n');
+ }
+
+ @Override
+ public void checkCancelled() throws OperationCancelledException {
+ // no-op
+ }
+
+ @Override
+ public Map<String, ValidationResult.Option> askUser(List<ValidationResult> validationResults) throws OperationCancelledException {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public String toString() {
+ return myOutput.toString();
+ }
+ }
+}
diff --git a/updater/testSrc/com/intellij/updater/UtilsTest.java b/updater/testSrc/com/intellij/updater/UtilsTest.java
new file mode 100755
index 000000000000..6e9e4ebf673b
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/UtilsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 com.intellij.updater;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+public class UtilsTest extends TestCase {
+
+ private boolean mIsWindows;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mIsWindows = Utils.isWindows();
+ }
+
+ public void testDelete() throws Exception {
+ File f = File.createTempFile("test", "tmp");
+ assertTrue(f.exists());
+
+ try {
+ Utils.delete(f);
+ assertFalse(f.exists());
+ } finally {
+ f.deleteOnExit();
+ }
+ }
+
+ public void testDelete_LockedFile() throws Exception {
+ File f = File.createTempFile("test", "tmp");
+ assertTrue(f.exists());
+
+ long millis = 0;
+ FileWriter fw = new FileWriter(f);
+ try {
+ // This locks the file on Windows, preventing it from being deleted.
+ // Utils.delete() will retry for about 100 ms.
+ fw.write("test");
+ millis = System.currentTimeMillis();
+
+ Utils.delete(f);
+
+ } catch (IOException e) {
+ millis = System.currentTimeMillis() - millis;
+ assertEquals("Cannot delete file " + f.getAbsolutePath(), e.getMessage());
+ assertTrue("Utils.delete took " + millis + " ms, which is less than the expected 100 ms.", millis > 100);
+ return;
+
+ } finally {
+ f.deleteOnExit();
+ fw.close();
+ }
+
+ assertFalse("Utils.delete did not fail with the expected IOException on Windows.", mIsWindows);
+ }
+}
diff --git a/updater/testUI/.gitignore b/updater/testUI/.gitignore
new file mode 100644
index 000000000000..378eac25d311
--- /dev/null
+++ b/updater/testUI/.gitignore
@@ -0,0 +1 @@
+build
diff --git a/updater/testUI/build.gradle b/updater/testUI/build.gradle
new file mode 100755
index 000000000000..2c86712964bc
--- /dev/null
+++ b/updater/testUI/build.gradle
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * 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 java.nio.charset.Charset
+
+apply plugin: "application"
+
+project.mainClassName = "com.intellij.updater.Runner"
+
+defaultTasks "testSuite"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ compile files("../../lib/log4j.jar")
+ testCompile group: "junit", name: "junit", version: "3.+"
+}
+
+sourceSets {
+ main {
+ java { srcDir "../src" }
+ resources { srcDir "../src" }
+ }
+ test {
+ java { srcDir "../tests" }
+ resources { srcDir "../tests" }
+ }
+}
+
+
+test {
+ testLogging {
+ showStandardStreams = true
+ showStackTraces = true
+ exceptionFormat = "full"
+ }
+}
+
+//---
+
+// Task : Tests updater create + install in the default normal case.
+// Scope: large test.
+// Running this will display the install patcher UI.
+task testUI1(dependsOn: jar) << {
+ println "## Running UI test 1"
+ println "## Jar file: " + jar.archivePath.getAbsolutePath()
+
+ // Create a temp dir inside the gradle build/tmp dir
+ //noinspection GroovyAssignabilityCheck
+ def buildTmpDir = new File(project.buildDir, "tmp");
+ def tmpDir = _createTempDir(buildTmpDir)
+ def logDir = _createTempDir(buildTmpDir)
+
+ try {
+ // create a "from version 1" and "to version 2" directories
+ def dataDir1 = _createTestData(tmpDir, "1")
+ assert _mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+ assert !_mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+ assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-1")
+
+ def dataDir2 = _createTestData(tmpDir, "2")
+ assert !_mkFile(dataDir2, "plugins", "v1", "myplugin.jar").exists()
+ assert _mkFile(dataDir2, "plugins", "v2", "myplugin.jar").exists()
+ assert _getFileContent(_mkFile(dataDir2, "build.txt")).equals("AI-123.45678-2")
+
+ def patch = _createFileContent(tmpDir, "patch.jar", "patch jar placeholder");
+ patch.delete()
+ assert !patch.exists()
+
+ def logFullFile = _mkFile(logDir, "idea_updater.log")
+ def logErrorFile = _mkFile(logDir, "idea_updater_error.log")
+ assert !logFullFile .exists()
+ assert !logErrorFile.exists()
+
+ // call updater jar to create a diff, resulting in a patch jar.
+ println "## Invoking updater <create>"
+ javaexec {
+ classpath jar.archivePath
+ classpath "../../lib/log4j.jar"
+ main = "com.intellij.updater.Runner"
+ args "create"
+ args "AI-123.45678-1"
+ args "AI-123.45678-2"
+ args dataDir1.getAbsolutePath()
+ args dataDir2.getAbsolutePath()
+ args patch.getAbsolutePath()
+ args logDir.getAbsolutePath()
+ }
+ assert patch.exists()
+
+ assert logFullFile .exists()
+ assert logErrorFile.exists() // should exist and be empty
+ assert _getFileContent(logErrorFile).equals(null)
+
+
+ // that patch jar is self-executable. use it to update dir1 into dir2 in-place.
+ println "## Invoking updater <install>"
+ javaexec {
+ classpath patch
+ classpath "../../lib/log4j.jar"
+ main = "com.intellij.updater.Runner"
+ args "install"
+ args "--exit0"
+ args dataDir1.getAbsolutePath()
+ args logDir.getAbsolutePath()
+ }
+ // build.txt should have changed to v2
+ assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-2")
+ // plugin v1 should have been replaced by pluging v2 in the dataDir1 directory.
+ assert !_mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+ assert _mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+
+ assert logFullFile .exists()
+ assert logErrorFile.exists() // should exist and be empty
+ assert _getFileContent(logErrorFile).equals(null)
+
+ } finally {
+ // Cleanup on exit
+ tmpDir.deleteDir()
+ logDir.deleteDir()
+ }
+}
+
+// Task : Tests updater create + install with 2 open files.
+// Scope: large *interactive* test.
+// On Windows, the opened files are locked and can't be deleted/overwritten.
+// On Linux/Mac, they should be writable & deletable.
+//
+// Running this will display the install patcher UI, which will fail at
+// first on Windows. After 5 seconds the open files will be closed.
+// Hitting "retry" in the UI after this point should perform the whole
+// install operation again.
+task testUI2(dependsOn: jar) << {
+ println "## Running UI test 2"
+ println "## Jar file: " + jar.archivePath.getAbsolutePath()
+
+ // Create a temp dir inside the gradle build/tmp dir
+ //noinspection GroovyAssignabilityCheck
+ def buildTmpDir = new File(project.buildDir, "tmp");
+ def tmpDir = _createTempDir(buildTmpDir)
+ def logDir = _createTempDir(buildTmpDir)
+ def closeableFiles = []
+
+ try {
+ // create a "from version 1" and "to version 2" directories
+ def dataDir1 = _createTestData(tmpDir, "1")
+ assert _mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+ assert !_mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+ assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-1")
+
+ def dataDir2 = _createTestData(tmpDir, "2")
+ assert !_mkFile(dataDir2, "plugins", "v1", "myplugin.jar").exists()
+ assert _mkFile(dataDir2, "plugins", "v2", "myplugin.jar").exists()
+ assert _getFileContent(_mkFile(dataDir2, "build.txt")).equals("AI-123.45678-2")
+
+ def patch = _createFileContent(tmpDir, "patch.jar", "patch jar placeholder");
+ patch.delete()
+ assert !patch.exists()
+
+ def logFullFile = _mkFile(logDir, "idea_updater.log")
+ def logErrorFile = _mkFile(logDir, "idea_updater_error.log")
+ assert !logFullFile .exists()
+ assert !logErrorFile.exists()
+
+ // keep a couple files open, preventing them from being deleted or replaced on Windows
+ closeableFiles << _openFile(_mkFile(dataDir1, "build.txt"))
+ closeableFiles << _openFile(_mkFile(dataDir1, "plugins", "v1", "myplugin.jar"))
+
+ // call updater jar to create a diff, resulting in a patch jar.
+ println "## Invoking updater <create>"
+ javaexec {
+ classpath jar.archivePath
+ classpath "../../lib/log4j.jar"
+ main = "com.intellij.updater.Runner"
+ args "create"
+ args "AI-123.45678-1"
+ args "AI-123.45678-2"
+ args dataDir1.getAbsolutePath()
+ args dataDir2.getAbsolutePath()
+ args patch.getAbsolutePath()
+ args logDir.getAbsolutePath()
+ }
+ assert patch.exists()
+
+ assert logFullFile .exists()
+ assert logErrorFile.exists() // should exist and be empty
+ assert _getFileContent(logErrorFile).equals(null)
+
+ Thread.start {
+ sleep(5 * 1000) // 5 seconds
+ synchronized(closeableFiles) {
+ println "##"
+ println "## Closing pending open files --> now click 'Retry' in Updater UI."
+ println "##"
+ closeableFiles.each { it.close() }
+ closeableFiles.clear()
+ }
+ }
+
+ // that patch jar is self-executable. use it to update dir1 into dir2 in-place.
+ println "## Invoking updater <install>"
+ println "##"
+ println "## Note: on Windows some files will be locked for 5 seconds and the installer"
+ println "## window should display a 'Retry' button. This code will wait 5 seconds"
+ println "## then unlock the files, at which point you would click that 'Retry'"
+ println "## button and the install should continue correctly."
+ println "##"
+
+ javaexec {
+ classpath patch
+ classpath "../../lib/log4j.jar"
+ main = "com.intellij.updater.Runner"
+ args "install"
+ args "--exit0"
+ args dataDir1.getAbsolutePath()
+ args logDir.getAbsolutePath()
+ }
+ // build.txt should have changed to v2
+ assert _getFileContent(_mkFile(dataDir1, "build.txt")).equals("AI-123.45678-2")
+ // plugin v1 should have been replaced by pluging v2 in the dataDir1 directory.
+ assert !_mkFile(dataDir1, "plugins", "v1", "myplugin.jar").exists()
+ assert _mkFile(dataDir1, "plugins", "v2", "myplugin.jar").exists()
+
+ assert logFullFile .exists()
+ // the log error file should exist and should not be empty on Windows.
+ assert logErrorFile.exists()
+ if (System.getProperty("os.name").startsWith("Windows")) {
+ assert _getFileContent(logErrorFile) != null
+ } else {
+ assert _getFileContent(logErrorFile).equals(null)
+ }
+
+ } finally {
+ // Cleanup on exit
+ synchronized(closeableFiles) {
+ closeableFiles.each { it.close() }
+ closeableFiles.clear()
+ }
+ tmpDir.deleteDir()
+ logDir.deleteDir()
+ }
+}
+
+// Task: Test suite to run both tests above.
+task testSuite(dependsOn: [testUI1, testUI2]) << {
+}
+
+// ---- Helper methods
+
+// Convention: all local helper methods start with an underscore to clearly
+// differentiate them from groovy/gradle methods.
+
+
+// Creates a temp dir with a random name in the build/tmp directory.
+File _createTempDir(File parent) {
+ def d = File.createTempFile("test", "", parent)
+ d.delete()
+ d.mkdirs()
+ return d
+}
+
+// Creates a new directory with the specific name in the specified parent directory.
+File _createDir(File parent, String name) {
+ def d = new File(parent, name)
+ d.mkdirs()
+ return d
+}
+
+// Creates a new file with the specified name, in the specified parent directory with the given UTF-8 content.
+File _createFileContent(File parentDir, String fileName, String fileContent) throws IOException {
+ File f = new File(parentDir, fileName)
+ OutputStreamWriter fw = new OutputStreamWriter(new FileOutputStream(f), Charset.forName("UTF-8"))
+ try {
+ fw.write(fileContent)
+ } finally {
+ fw.close()
+ }
+ return f
+}
+
+// Opens a file for writing (thus locking it on Windows) but does not close it.
+// Caller should call Closeable.close() on the returned Closeable object.
+Closeable _openFile(File file) throws IOException {
+ if (!file.exists()) throw new IOException("File not found, expected file: " + file.getName())
+ // We need to actually write to the file but not change its content so just read it
+ // then write the same thing back to it, without closing it.
+ String content = _getFileContent(file)
+ FileWriter fw = new FileWriter(file, false /*append*/)
+ fw.append(content)
+ fw.flush()
+ println("## Open file " + file.getName());
+ return fw // file is not closed
+}
+
+// Returns the first line of the file.
+// Returns null if the file exists and is empty.
+// Throws IOException if file does not exist.
+String _getFileContent(File file) throws IOException {
+ if (!file.exists()) throw new IOException("File not found, expected file: " + file.getName())
+ BufferedReader br = new BufferedReader(new FileReader(file))
+ try {
+ return br.readLine()
+ } finally {
+ br.close()
+ }
+}
+
+// Creates a new File() object with the concatenated name segments.
+File _mkFile(File base, String...segments) {
+ for(String segment : segments) {
+ base = new File(base, segment)
+ }
+ return base
+}
+
+// Creates a mock test data for an idea-based IDE.
+File _createTestData(File tmpDir, String value) {
+ File root = _createDir(tmpDir, "idea-ide-" + value)
+ File bin = _createDir(root, "bin")
+ File lib = _createDir(root, "lib")
+ File plugins = _createDir(root, "plugins")
+ File myplugin = _createDir(plugins, "v" + value)
+
+ _createFileContent(root, "build.txt", "AI-123.45678-" + value);
+ _createFileContent(bin, "idea.exe", "binary file " + value);
+ _createFileContent(lib, "idea.jar", "some jar file " + value);
+ _createFileContent(myplugin, "myplugin.jar", "some jar file " + value);
+
+ return root
+}
diff --git a/updater/testUI/gradle/wrapper/gradle-wrapper.jar b/updater/testUI/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000000..7b359d719bf9
--- /dev/null
+++ b/updater/testUI/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/updater/testUI/gradle/wrapper/gradle-wrapper.properties b/updater/testUI/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000000..97f4761e6349
--- /dev/null
+++ b/updater/testUI/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Dec 12 15:16:42 PST 2012
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=../../../../../external/gradle/gradle-1.9-bin.zip
diff --git a/updater/testUI/gradlew b/updater/testUI/gradlew
new file mode 100755
index 000000000000..779e68d26a2e
--- /dev/null
+++ b/updater/testUI/gradlew
@@ -0,0 +1,179 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/"
+APP_HOME="`pwd -P`"
+cd "$SAVED"
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+# Change the project's .gradle to the android out dir.
+ANDROID_GRADLE_ROOT="$APP_HOME/../../../../out/host/gradle/tools/updater"
+if [[ -z "$ANDROID_CACHE_DIR" ]]; then
+ ANDROID_CACHE_DIR="$ANDROID_GRADLE_ROOT/.gradle"
+fi
+
+# Change the local user directories to be under the android out dir
+export GRADLE_USER_HOME="$ANDROID_GRADLE_ROOT/.gradle"
+export M2_HOME="$ANDROID_GRADLE_ROOT/.m2"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ --project-cache-dir=$ANDROID_CACHE_DIR \
+ "$@"
+
diff --git a/updater/testUI/gradlew.bat b/updater/testUI/gradlew.bat
new file mode 100755
index 000000000000..3569a7be8d73
--- /dev/null
+++ b/updater/testUI/gradlew.bat
@@ -0,0 +1,96 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Change the project's .gradle to the android out dir.
+set ANDROID_GRADLE_ROOT=%APP_HOME%\..\..\..\..\out\host\gradle\tools\updater
+set ANDROID_CACHE_DIR=%ANDROID_GRADLE_ROOT%\.gradle
+set GRADLE_USER_HOME=%ANDROID_GRADLE_ROOT%\.gradle
+set M2_HOME=%ANDROID_GRADLE_ROOT%\.m2
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% --project-cache-dir=%ANDROID_CACHE_DIR%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/updater/updater.iml b/updater/updater.iml
index e55b58d17cd0..e55b58d17cd0 100644..100755
--- a/updater/updater.iml
+++ b/updater/updater.iml