From 73a9e8068986434c9da06c47d30123f9369ed353 Mon Sep 17 00:00:00 2001 From: Ben Manes Date: Sun, 2 Dec 2012 15:08:07 -0800 Subject: [PATCH] Made dependency updates task into a standalone plugin. --- .gitignore | 6 + LICENSE.txt | 201 ++++++++++++++++++ README.md | 65 ++++++ build.gradle | 99 +++++++++ gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 46707 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 164 ++++++++++++++ gradlew.bat | 90 ++++++++ settings.gradle | 1 + .../gradle/versions/DependencyUpdates.groovy | 166 +++++++++++++++ .../gradle/versions/VersionsPlugin.groovy | 34 +++ .../gradle-plugins/versions.properties | 1 + 12 files changed, 833 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 build.gradle create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100755 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle create mode 100644 src/main/groovy/com/github/benmanes/gradle/versions/DependencyUpdates.groovy create mode 100644 src/main/groovy/com/github/benmanes/gradle/versions/VersionsPlugin.groovy create mode 100644 src/main/resources/META-INF/gradle-plugins/versions.properties diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..566b7719 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bin +build +.classpath +.settings +.project +.gradle diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/README.md b/README.md new file mode 100644 index 00000000..a88f685a --- /dev/null +++ b/README.md @@ -0,0 +1,65 @@ +# Gradle Versions Plugin + +In the spirit of the [Maven Versions Plugin](http://mojo.codehaus.org/versions-maven-plugin/), +this plugin provides a task to determine which dependencies have updates. + +## Usage + +This plugin is hosted on Maven Central Repository. You can add it to your build script using the +following configuration: + +```groovy +apply plugin: 'versions' + +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath 'com.github.benmanes:gradle-versions-plugin:0.1' + } +} +``` + +## Tasks + +### `dependencyUpdates` + +Displays a report of the project dependencies that are up-to-date, exceed the latest version found, +have upgrades, or failed to be resolved. + +The `revision` task property controls the resolution strategy of determining what consistitutes the +latest version of a dependency. The following strategies are supported: + + * release: selects the latest release + * milestone: select the latest version being either a milestone or a release (default) + * integration: selects the latest revision of the dependency module (such as SNAPSHOT) + +The strategy can be specified either on the task or as a system property for ad hoc usage: + +```groovy +gradle dependencyUpdates -Drevision=integration +``` + +This displays a report to the console, e.g. + +``` +------------------------------------------------------------ +: Project Dependency Updates +------------------------------------------------------------ +The following dependencies are using the newest release version: + - com.google.code.findbugs:jsr305:2.0.1 + - com.google.inject.extensions:guice-multibindings:3.0 + - com.google.inject.extensions:guice-servlet:3.0 + - com.google.inject:guice:3.0 + +The following dependencies exceed the version found at the release revision level: + - org.scalatra:scalatra [2.3.0-SNAPSHOT <- 2.2.0-RC1] + - org.scalatra:scalatra-auth [2.3.0-SNAPSHOT <- 2.2.0-RC1] + - org.scalatra:scalatra-specs2 [2.3.0-SNAPSHOT <- 2.2.0-RC1] + +The following dependencies have newer release versions: + - com.amazonaws:aws-java-sdk [1.3.21.1 -> 1.3.26] + - com.beust:jcommander [1.27 -> 1.30] +``` diff --git a/build.gradle b/build.gradle new file mode 100644 index 00000000..0ff8dd13 --- /dev/null +++ b/build.gradle @@ -0,0 +1,99 @@ +apply plugin: 'signing' +apply plugin: 'groovy' +apply plugin: 'maven' + +group = 'com.github.benmanes' +version = '0.1' + +dependencies { + groovy localGroovy() + compile gradleApi() +} + +jar { + manifest { + attributes 'Implementation-Title': 'Gradle Versions plugin', + 'Implementation-Version': version, + 'Built-By': System.getProperty('user.name'), + 'Built-Date': new Date(), + 'Built-JDK': System.getProperty('java.version'), + 'Built-Gradle': gradle.gradleVersion + } +} + +task sourcesJar(type: Jar) { + classifier = 'sources' + from sourceSets.main.allSource +} + +task groovydocJar(type: Jar, dependsOn: groovydoc) { + classifier = 'javadoc' + from groovydoc.destinationDir +} + +artifacts { + archives sourcesJar, groovydocJar +} + +ext.pomConfiguration = { + name 'Gradle Versions plugin' + description 'Gradle plugin that provides tasks for discovering dependency updates.' + url 'https://github.com/ben-manes/gradle-versions-plugin' + inceptionYear '2012' + + scm { + url 'https://github.com/ben-manes/gradle-versions-plugin' + connection 'scm:https://ben-manes@github.com/ben-manes/gradle-versions-plugin.git' + developerConnection 'scm:git://github.com/ben-manes/gradle-versions-plugin.git' + } + + licenses { + license { + name 'The Apache Software License, Version 2.0' + url 'http://www.apache.org/licenses/LICENSE-2.0.txt' + distribution 'repo' + } + } + + developers { + developer { + id 'ben-manes' + name 'Ben Manes' + email 'ben.manes@gmail.com' + } + } +} + +install { + repositories.mavenInstaller { + pom.project pomConfiguration + } +} + +signing { + required { gradle.taskGraph.hasTask(uploadArchives) && !version.endsWith('SNAPSHOT') } + sign configurations.archives +} + +uploadArchives { + repositories.mavenDeployer { + beforeDeployment { deployment -> + signing.signPom(deployment) + } + + name = 'mavenCentralReleaseDeployer' + + repository(url: 'https://oss.sonatype.org/service/local/staging/deploy/maven2/') { + authentication( + userName: properties.get('mavenCentralUsername', "N/A"), + password: properties.get('mavenCentralPassword', "N/A")) + releases(updatePolicy: 'always') + } + + pom.project pomConfiguration + } +} + +task wrapper(type: Wrapper, description: 'Generates the gradle wrapper.') { + gradleVersion = '1.3' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..b6b646b0c00c16cb27a2cc712b241d9183bc9310 GIT binary patch literal 46707 zcmagF1C%G-vM*R&wr$(CZQK5r?W(RW+qP|V*|u%lt}eX3bMCzRzB6ZLa;=@2D_88b zk%3=C>`;^e0fhzvf`kM@HggdI`g;NY*X{2G^|#51sS43a$%`|904e^1@cRninC~xv z>feU?e-g?G$xDfgsi@M+i9g6qPRPp8(a*uj&{0oM&NM1BF0$+%-A~euN=?a4(MZw$ zfIbf~O*t&mrfS6?D>*DO9wi2_9Utu<0skMvA^zLEK>rSB?_}|hDg8SQ%zx8ZI2oDR znEii}qWqK8-O0$o!OZFZ(Zw>r)V%O7>C)du@}Iki+PmA?*c+LWGSQpZ7&$xpM#(|< zGa?4>Sh8u;xG@C4tc2wB5jYUh^9tFB*g#21Rdi*-AnfK3qB>si9`oT(`qaK0KoN@c z_hK3g`~2oeo$xIuGiqND?klq9{`pwezyPNf#GP9BnlRPNcHG+l$n$Gh=R8MB) z=g-P0AYms)@%Cu+Z5ahg9_*EVO22khW_!p7fjAc|L_VKVf}mMqSYdHYaDve20XSDW zJl}uY>o_w{N+bI4VhkOWVm zrZjs`45Hg*h7B;)+3v!N+^1uBSfvtOqat7;H`kG2rkv{&>c7Nb3wQ6qEjtT9Ij5YaLN0GT-Tso4-6)3G85e$o7K8&jc8;MukUR=X}zac3J z@dn*5K-6M26k9@2MS%Z@^RSb(oW zp&dvFT`7NjK@mn1%}|dBtb#e|7YQ2=9tje4m1}F2^q7=rKNbEm<~@rx?((B+ZI-ia z)trI3&`-y~$Le_!?SgEX6n#|m-wKF-WaVMCv=avmK`;Q#;!t&t!8X8Lha-p7Vr(hj zA+J0e$Y*s2Ur8Oj zZ}?L4*_^^;?+PrFqU>_%k60dP9+UlCdDiQa|1ve6|RH&`-Tj zy&xg|3TVjK6d)7N$WJt;lPK4WFoF%nS#>OwgBnSQG`EbElG4>J5cnp%eVOXZUV?<0 zKD4GTMEW%|lZrzqlOU~l)YMMo#yI3r77 zj`UO_`W+?!Ni{K%+S)|>v#~B&R%3fZiK;*mCYfe%q{}%CHF}I};+a3%pTlGW#78hb zLEa@?-!Hd>3_B)WFrU|a{rsLi(Z9Y<9t?n%=VXb4Lmhdg_nFueJpyu((|+NPq{MAF zCI!)s)RP>l)bpZD)M)y}?0LeXg*54N&Hl8-Z?16l{qv^O);<$g-nnn@Q9n@aR)5A- zvg9|)*lep)GeT#d>+S_UV1ubyfu~Bt)`c2m)#*IE(@s}8q2Om>7z(@atHLx_3okP_ zVW#{{dHEp6VjX=g&?;pQO($BfA_@Dqz2i!ps_S)^X;>Fa$1kNz;H^QD1?Dcfkcl?l zKGEM-Dh)HLvJ+*``UE)B3?Ho~VKD0yosBbiDp?|CgWiC4*tdwQrbye+T(_wG^nnh& z0V;gZ1nt|*wQDY2LrCR?rQ!)Cvv%ioHr_SlF+Aw9Ge6lL2^Nr@UnRC4#qs#XPM&Qt z#5Rjm**H%~OXkI@LLUCy-52_k5Q#G-vPxz%r-D@B|rd zGh9q=vP@ZEOQ6f3sUc=QV{yLgvogu|b3!7uD-+R$@fLUkIU&?mOp9!tf+7RFHH@^C zChrW|18RH8&|TVcPM+!;G}f&lu%CqQu_B#v8Uw`4*bT;7$P*ZvhOKV`JIHEnr;b;z z$&UNcWf}H*GahmXS?y+;_L%BwB1%)NzWEysS22C%Da%JO*03?-KM0J2zsQvzH4=M) z=STg`WlCipwR$&aJp;NI<$wNUOLFlvP%iXo!yLDvO!eUs;j;8-@)Ij%nP*AB363=k zo-9^q{eX&h7KKR<|Ke949h`}$G)*{3dwj|0$$j4~)ysFqV$wcABnm?{GA(~~)pk~O ziLP21s{jkWW$Pvya{#F%5{)ma6NC9l{5(Q<7F4T?1sww)V6S{m=&^7E?}>p9^#n|H zW^J!HS&_RZy^Cg!$TP>G#90d(K2GRKCMg7moGfIgGP#Z!_l9_g-mT^@+mkA|oJ`n4 z)dlNxfxEyw3O=-n1467HN2xpL4jmT+doKvp5ObqO2!(aXG-MO=qwQG0HH1exP6|s@ zBVbc4PrLt4Y%&catj82DHoBCkC5x*swRDq2<1cfA+)146OJ$ zmB5=oyNP%Iktpx!fU?ymoO;~!p1H_*;5o@z>-m0rU;qleYYcIVD)SH#!4qfA8ZL|A zV0$Hdhyq75xo4zzN1-NHlP&j<86b}WbyTlmlA4xs(hrO|Bc!+Vz+sucG$z^ZD;C!s z?nvmQVBldWzOiOxq><7czztH(u@?oFLMw@&fd&RCF>4QmJ|Dnafc6o2&Qh#1n`{~s zrRSr`avrvc$SPstu`4Qp8%a7LUN|A2stUMf+K>`Oj$ukgjt3hVH4Q=ur!&)w&vCNB z*Htl9z(F69SM7Taa-b=OehwL_!CZ+B14xKZCWX17#&E63iVa7@UImn(IpY}>p#_b* zNL0&C(}k6lFxDNrzMUT48ta z)zJ!*0c)3l)@76J!x5U1V+|Ztt5?gGKo^v;GSHkVA3G}j8L!1F1Fy_rkqm`nVll$9 zo6e8jE5&$7_qAf;IT;lDQM09BS*{PLFcETl#`6V=$gXulAn{Al1LF3}>h>Dv!cjBJr;uVwzhl~VTWtdBoaL=o9ZV7?Q6>uaS zN{xDvxJ5LiH0Mb|Ocx@Hy~fUB+?c0)_a@f&{Gz?V!RD;G{Q_}#oWdsP)VmRo zRSx@c?ms9o*$22b@UhEP{mat$j#5xGd*odqIAn689|&IxpDPcPKc;bdpKL_IMy%5W z5=AZ#YVq!C;UlsXiXc299MoFhc{K7ruEP-$z!*2rdU|)78^8sye%-N^u{`2tonDU>{`y{Le)P-T4DyLhnPaa9_ce#h zEbD3m$l&Xo8SCK7@l~#Vl>tUTSQT7O>K}--Q6K*ZcZaSP@6yYU>4nk$R2a>bu*RQx zf)M`2>$WrWOR+a~`_ekJUYR(XPBXH3DHyJr-u-oBvc>h!2S?NS}N*5~GVP z$mCRlgbX~Ta2dM!T16&+8{y4pQ5J!(lP+SbDcZpuqB`n`QJ~8X>6GLVIj@%A>)Zq? zfm6g_1d>N+#IduVEo|qMW1KknmImA*V5n{Krdp^|`e!W~jOMIYc1NOqd}u4r(N)Oz zzri3Hd0QxK2p}LwcpxD1|Ex0=ja)2+oSn^VjsLf%OjdvM#?e6IGm*hI0P|D-g(UGaw+pOrEgPzA!hx3-R9!w{!DpKkJo0Xcufl~f~r*BdY1Au&t z5`b;;u%wu}%5Es+ZnM8^d2hF!Y^DGFKH260n%*@)jwxt`u&AdN8gLC4pK(yxFQFAa zF$<)yCeBGF%pav8kFBD#xyFMcw!6KTvs)Ikk>m_hka>j_;E6mbc&!SXk@CRLjok-> zV%R6k>6|RoA@1(|#2~{Rq1p728cY@QA&aP$J{?*qc;&|V8JKC`Fr(r5sExX_|Fxmy zLlJQ!{fgf`!)YgR7f9(h%3~kdO0wGzW=GE9DJ5vL-|i$Lm5SPxmO}>Nb=T?NWfEey7GcLgNhX0- zXYXZxes{U5YrE22P>w2n-dUV+Af8Ug%aIY^U6!osgybo^!1gD=e_3=Vz<)MPiLmh# zC8I{3`^ao5OC?2ydc@)uCZhaq(*Sm@5HK^CR7@~0v)3QEU?QSe zo?6zlNzks#C=-C`0=tkI{^4)_bsF)T+>rY2`qJ0m8QfIgWpcjNxEeYxY`|wPi^G$V zP;vLG%WSD3sUTx6qQVS@^B7C(Ji^54S)6<4HSKa>0*4)@>FB%+=vRzqS)a9=ubAEg zRfMJ;4Z%GoUOGo1AoMmB=%|Sn6`p@;&9*4C~(ivC?nlCNBr3E*Z3$}KiUHo z59wjzoVYtE*?B#?N7@4l54~Y#^;30@LQK~tWg#}Rk0e{akX#fJ09McL8lxZ8fd=n8 zn?A@_bnywgQtGD)cyHtT2zL z56}h`3u0xA2eoJ@+1p?!YGUrCNWcWNN#h^X;mMqS872xbguah&Rsc2+SE^+UaeS!| zUjy3tU8D8D4Jq_rG^g*~@c6Sv!A8)|5WCwKE%1s>+1@tDU&p6;Z8d*uKTBq@!zK84 z)x*SrW#uW<6h3;cM9BMq#s)Mx`*_RjUQvk9|@1CyxD6MT^g$MIRLNL#;NRK`$DjUbiII zsN?t@n=y^ZhIUz7;7i$Q>unfnYZF?{b6#s7VY9bu+`zJlRbF7y=$1tK8x>nV8!( zx_+;*9z*}T#2iBeq|tq@Z7r$2F{#0szM`n5 zBjmg_QqVynsy3L`B+W^w`S#Cbtas@1-E^PkiXLwq#e6%(9|&sB-@ylwME&>q)caR= z(DF9NEwde%JW^cTt~*aYzH1E2Ag@G-1M0wj1?G75rMbGfI(lN!D zhQl{vN51RfSZ{A@ByNYHXu^acHJ|xp4&RX1df5hZ0lh&9gYMj9=l6al=+&OJpR|uI zU}Ii`11`*pb^}Rj>Gx~$v?GwNd^CE^WqO+Z3#cSfB8s}zqb|Oj{1(C8jvueJv;5|y zi4jNvUmIcMJE9Zj)a<*{>sr_KeI1e-ceCWBLn}U)uwy(!+CM#XPGUFhg}D`^_43M6 zsUQ^Qle^{}j9A!;uuwl>%dWqyU+XHlz3P?eXM|n}{^^k%&kvlf{I#sBctAje|Jk}q z**Uuy+1UImu8^$>(K}Kn9@fW)$1?VUqu%bg&2Vd9@|91 zHvLR?YrdfZ`y~%2;FPF)FMgovD03@=@Wps;t zvotCInB4e%+notca!!6uce(f6E~M%c6~KKUC1amW9JvViie=PRJdQlF0lq{t1k}zh z9xbT(q<+>UNbe|~X5N3o1b-=$MR(H%_9Sc@K%DB_fBv5Qh-TfPDy@9n0{X0${mz#D zsqn2R^ewrQ*!&YY=DSLG`-SEd;*nwg!y4=}?n^F%0PJ)`_~}OYHWBDk!v9O9{kwSf zC&cMb)OUmA-?QK4O)-AdJhevgP<+Qgsg##0?akS9T4$=BFgrE(>emVSrH|Zb+ry}rXImS5i|(f$ z3Ldw!eYe;7B6}d8BM|KfS0)wLJmtCbJO%A+YfPu4vew8r=vVdCMTI)kMtm8}z@6Dt zi1i9ON;?hpCK9kEL%tLk9|RDnDpdG5*9^DoQ!M`u+h>wq?P;3W;MA` zB>&}Aj$K{R88fMYvux&Jm6$YkLsDaNW-4tG#)mdM^e`hMEjK@RE8~7i%=kd?&hrw} z`S4XL!!CA(M|~co1-ucmTZwqRT@(Tn?HmnBaOCIKc-d?Dbfs97k#s9`XsI=~N( zy7iS+P}$VAF+V-G6p5%ZqV#OaeJVuivBg$OSYNrIpC6#GGMK$?Qk}}d5d*fgD&jQHKFy*Ae=YJXjBmNG(QL9DheUHr~s)b&sjB|4_wIzMOm9wq4<@AE}ofrO_7=H`yG3)Oc>UN%exgNuH59nf2!`NJ5Ukx2pty^t54@1S(<{QZ zh}N7W_lTkq9_sq-f5q??+#z`h9Vl4}3rG;Cy_OBXL==p?w)VdOswNDhMtQmB%^!JZ531#&PKaR8E5`izF9f`tPD>7`qk>`LDehcPr z>LzOAN3D-G9c{=)oJNq~sE)Ifvk(JOyUO1#=L8oQHI*aO5*|+CzZNYO!EvJgUD$nm zNPx)`4uJFICHlf%_DE2$e2jdQ!FD<#UFcd-qo@``?!Q#Lv{))8552n<70yjrFT4B1 zUE(Cq`MtV)njk2Q$5Q>+7Z}x{-$q?G9SEh!dR2cCh0z+qWF5)o0rR0u^pKiaTD4m{>Qzwdzf55j_Qlz0T zL6bL)h=#TTTY%KGQopB$neC=tWiAXR`4G-_og0zukrdb_^bngYUY5wURODFHa$P=H z{(zW@N%q$;mr>BX2PQO$M?|(wi(&wqA5E^>t5Gz;UJKyE%@5VOw9Bgc&g26=dS@)Q za2u7*(gAi?y!IXix<}@Kg6vX3Dqsn%wgS6HM^gUI+u|zu0^o!7CnlHIX9sCa#blHzSjF2g$4`oJ(N#DT{Y!_YeD2zx zfgHlPV2L3rqb(KnfUo4baap&S4pepX5@wD5*=QR>?k{utDS-txrC_!-8RO-+O|#0$ zw0que$RH4Ic*l`KHO6Op5E+&ZXoM$bC7~KL+h~|njO$T7Kj4^bDv}n|E<{vD;mh&P z4M`)S40&#G+V5UGAm3|II>qtIvD!*iIV5%mVO?=0uGL5^s4ex*?G0M@gE2yjy=V%c z)Pbo`8{VN~qM0r~HS}$#{KWLj=pj7RZvS*YV4`}QhuQ&8g~IdTMngwog=ZWU!{e4s z1*5Qq>wD#VZ(4waN(_;r2qpO@^acM5`m4!fbgM4Ch#?I=90uCCLWTt_hwaf1LI#+- zWN$Nj?OXLS#zemKMg;FiNmKnYX0P3OZLoT8mxcLJ?2P!uX#-VWJdG_tVAS* zT$?d5qsW%D&(*lR764AhL%cxL<~pl*zwkO zKg?9RRc+HB4Qy+r_Yh5rk+5}?my55iQ!z#;7@pfQex5hBsq^7Bl5SQNM2F|VD_L?8 zU_*|N4L~i%WYWS+j+0xu4-@Rs-bQ)_uRB(RzM_f}7d#kncYL6Abe@1wo!@*1exq;8 zROs0Fu+%8j6FG8$QJdG!=$9Sc5MOW!8NCX}bn_-I1O0?JBl00CIV7ekLb^ktV>#T3 zEpdU!XpsN;@Ng)ia7GQ6GOd_bIk{3^#jAkU*MLPWpfGYQi5KrTgbN^PY?6FWW@&0| zhn|9^OD{gJ5oBZ(VH-#V05Zzj(Icx_R3QSeDng?YmJN5I=>pw>`-wO&Z&XEh?`s5| z85w0bT$5L*Ps-buf8sNb*UmzhIJ-!B(WJL8=6MCHkExbE+L?PLFV;lxh7(D`s!z^Z zDbU4ZSEUuR4PexCrAW9%#wB~2E?Ju)Qf{h{qrhQhH)POe7P^uwU3@aA9E8=n-ilde z6d%v9K}`5+log9Mr5CH`+kph|$CKOVO5{j8x--JdN&37N%EYHG(~DC zanu%WZOVJUx}EQRHl@bS^XC*X3W&OQV0uNN|8l43N}dKzF$n4movX~#y7da$2KV(( zgYBR7=HY`@O};N&eS;^IIcj{A_rgt4y+dvC!ll%kM(>K;2Ju!GS@!O$jaqgJ+749% z!~PE1zLDlp5XeI?)RiXyc82rmN-t%4Fq(X2dO#ZObzUA|^hGlO+qvdC7i6?Y!%WRB z+_+tv-FcQS-C5Dn*3rKB86s@kT#VB(PCAP-6Tgg2+acVNJbP@O&*6>*zY8f)~;40?6&_@MYm&UuaWC@t1z zBka}@vd{Q~gQ8ZKkmT#UI*_Dzw5g^~Ykm0$;oZWrBX!(8tCY>NcW2Mc6#g8;@&@+` zH@#4gM0lG|ro#fDps|MgWGG^vO1!t zp=dkWE_h{YXXhEadM0s8z<_T4Qq2)h11i->$Nl1Qzk?{fn5d1f4i3jy|ziIhG5d~n@6&A!M z`EH*5rmAN&8jX4)Y?A6$W;OEqv{w2V<}7+=Lcho?57E9zFq3yXI=yzq+E1AAvhw@7 zQ_e+LSXJ+(sGkfT^|IW-vwnEs7jZ8>n(fk{FM8t6H?U>F^_=1Jk=?7vYfqQv6$3fT zL}tQXz2a`)Y}7YAC0kg!Hbz!2C*%B}N1c%GS=>?H85;3Ppd_pwqpAmoCrSbW6B88q zp&5ZZ>;GsUGN8@09ae-<%r2x0Qf9vCL^!fU>ogF`cX2A#zF*Nvc2PrTH)izFCF*=8 z`i%swfYtqs3m4loIj_U38~xa#mrtS`4Kat6%(7b+`s6*M)TKF39cWT#77_zeXkZQh zZg$+wHUHzWJ{~wj3p=-X6c!7khL7Ts!pXvpCr(IG5e=;j`iTNE-8%lUTJn|0aFV|0 z0@T3-mB-$w+l5M(9ZqUM&Y^qIH&f2%>1!<`R|dkhUO^^m}&*x)@R?rF;TzlNvyifrya1S znS3YT40WI+qFzTj|Fm$VG;=kZyp_`zJv5xthewEAWpR!Lj8lYsV>0Et*iG(Km3q+7 z;L&&FE*t|iXNCEdeA;h;e>%kyo7jW>f75iy|L>W1VS9TQXP3X}cR3?~or;T*lgt0) z=(Kb;)Dijm8_ZP6{I!r11+##L%29n?B)u zuVf4|F$OfcOKv_fe9wCCJ0>Tyxh#&ik&(eoS&h{CGooB=Bwu@DN!=g9 z5Hfu{E=NL{`TIwZ`R_!ICg`v<;u7M}cQa>Ur*cqtp(K{U!c@#Npe!S-!F8rBTGE;; z?9ND`2B(rLYAaKQU&Qh)Z!Ecf#J2*>jIm_oE@+<@m0zCI&^jzK+@?#W5-PBubee6< zqhW53UzG*zJy^OcuPd4K*qG~sYyslto5_~uHsT9wt$`BF%&7UzG4()ea9kGVP!mJr z1HjmNR{>T??@55w%if&%C0%;E3V?Wjo_D{Yn~g1*e#w4lW6(MhlqFTU42=V1}XJ=0yiq+mcs| z6GRJmHRCF5&W<|H6@}XB3|y;Ka~G3@!Hf)fLWRLuj1TG&Q=Fv%PtX`g_^3e+dVM^t zbi4ChFlWYm^qNwN)9IW2U*i zW5k5;{{-cf=2)tkDfFq}LR#{p?Ch);OG|R9-eU1H5Yd$UqVKG+bwo9wd_^{(@(8I7 zPsQ56(?`jqBXj0M3gFA zcF5A?;7(SAMdqkoXk)G8c}=vqlX?+L?Gbas)kFaL_&rl9W`78)iA7v%TT`u=pE(eJ zf59)HuT}n5VAeUzET3|v)<(b7PB(BlXf$oUHXf>Wujt$FnLO#2r#+eHB_Yk1hkBN! z(utI`1T=_UX`T8*(5% zL!TJw%q*E>cl) zQEvhKzes--S;Re8<1pYh;mWt598(8h6!>z0hfhJ)r;*`bfCdj_Ip?Dq-K&9uz(2w@ z5D<^@^A0jrx6UAmhIdFhBiPONATzvK4byc>sgsD!*Id)hM<s`KMt%R%(>10{`NCoKw=KdMLaQgYwM)`4nV?fcG z0IN%f#4o;r)c(y`EeH_|77vA#Z8ZKSryYw-B=4Hg9|C!e8GpA=ykvrl;!+cAvrSeV z`USMr>)nLR)wz&F%N@Q8)^jk}_UGRsgyuRMcS3*9D>S160a5FTYsgxtLg*H-yLCn@2S!-1+QjUQKo4I?d&vE0qs?DD17$;cMzn){gxjdY z#<*2vN10|Gk+Am3d$#?)EwC?;V;dqKp*}lQJU0nz`H0(eJ1?WR+lbo~J1-NrzYzH; zcM!%LIK#X}Uh7Uj!fv-Q#35qB)L57^lh;0pcnQ%3FbA_{c_}H}$1V$ncu|KvIWhYO z?tMvvVuNq*5b@#mP>6h(gA~S|=Lqp(Od8{SwYziU_fCa*V`d_fX29;=7`<-6lpy?l^Uu1@jR(=oAduc-v6%y8D3 z8=9GQ)}%PC)3vr5;P^@n%dHKz+2`>@f_>LDHHz9dB^O4yQ|B3ZOzHG5m#Sd#uqQXx zI`t5bTHDDomsqH5`-ybpSXnxvq`)rTWvv@b=I50GT_&}~@uTOM&OLhYa@+GZ1Cw#( zeyM=Dye+T!Yj)b0l4gUx-zmy8)RnyPIXS*w%nC-TNTtbbSQfR*Bs(&z4!1gxtnY3i*n zDvNZB+VWGeg0;lO8x^0ey9l9pda+C@xqF)+?wBu9xNgKk^zF(^p;KGhdXiJ&EaHuZ zZ>iB~;OV?1lRilkNS4y%xMq~d{b{o4A;$-#?alAoDXIN4;p#jbOLbBy?4*SUe+G5}Wygbtfh#&AS8M9(`1* z*ADz}(*Km0z2LOro<*RCpvV_=h;1mUvtAJ!^qqej=r3N($biwAJzg_k(``iBs)-@* z`p58j}o8T;Xsa^J}QHwKH81oFP^5Ps&+Z?K4u2%0;yiz3> z`-m-wt8Wyi}Qns1qXCgXmzANC%-M&o{{ z!=KZ*$O%Pub;;CZ3M-3k$HE7CA2*hVMy+?S3Uyp$*9=KLelS^h?5FI0ablRl%2`*yQdF>Fc%c5ku7epjU1 zd)WM0qGP6asNg)Ibx&GskdcOdsZeup4AwvIVcFcT-IT?ld9trC$fD_CPi;!#M-8gz zzI007H!HO+FRS3!2yfL5N_wkry0%Me;)$x7z?^==xDJ;{d7v|<=(ZFup>?+3qf(b) z3O`JuM{AS3=Hf45{=IPnV_&vE(ONH<d(PS%wo)JL?D z6?+N_S?w_Gm-Rn_DEIY0mUCd9&*{_>o#cyy!GV9Y@nL**BTmU0*l+)1L3c} znjz>%6aPw~nhL}duhAC$>8IrGr!!rIKg)8u6h0SAVWVafo}$+}ClfR)Z};TK?ntiu z5Hn;W53Sg}z)nACPV%B=@~wE$%X7pG;n@xvHD|daca0>j@HTgr=?<6^I5z%8bMvz}bvWE&JMD42z+PPJoZA#PVN}K;tzpkQPVwC1z)(3$J_Os%>8i zncN6sE$UssC$a#hZ9e98#^^K_4iz0Mhu76k&+^VM^6oDM)7x0r+g9#3vKIDJM69-u zoH@BiUfa|;wUCnqZ}HxMJ8jP+2N&P#K`PuC37{#>D41D)7_8k$2khlUbCABB(Ji^t zA+jJ(mYSjB!<(X@2?vzlyLK)-oY@MXcKyt!t72M%z=>&2h#ez+@{Z;SlxowmidDy1 z_RKNJov3ezHgJxBGZM`U`~heRp=*&(SmRBjR$vxOo=xp2t-(1rux9(<2wT|^euK?r z5A{XH=vtu+by;V$U5)|g#=Jk$76^zgB=N7X>#@dTxZG)3cUoC|kO9o9A?F z_Zb6aD2-Xfbk}##+p31;oP?7x5k&XHv23soD)Mc?vk~$tp-n>T>UJDUy=8f=(Ml~1 z&}a`~&K%G$pkU?DXj(#fJ|Ag^G8!>gd1-7BG*(y!HF#XHcHgv1g2dkWXn~=+d;NL` z@}L>Srq9sCSo`nMUuIi>X-dATPvu)=0U2!XNPE}r+FuX_K^)>(Osmh8akD1W#XH*4 zf*O(af#z46nO;zG_lL3HZ;18|^_GD=RR~|zINd8~i-SyU$xuC*Ume88GSo(AP1FW4 zA1TK~2fKq(a%K;Y1EVCi?a_`J4i?59!p&9|J`A zvgxbfB5*G4Z$X>UZ(lptm*>@wEtJi2=l^_K_@__q?QZBt_7{f2|AnE{{~3l#{9pAu z{|!d}%P;@$l(hzg2hI_e-?!%7*h%BTsJxAZRuE~*(I9bE+?;h0*4(K&Ck2mZCromhldNAV%NR+VY0M|w1Z!BEvhrosY$gvwT& zMri(mU3|0+$J&U-)|uGYaTbDyg9B)OqR`x=%$JEN2-3nopRY-#j{pJuzdmXCJz&je zIX2Vun@fPdb|1z=vJd0)HG%iTOrV=Mda$~7{L7kc@#_M*JKq?y^z*gkvgc@|#q1mJ zS4z&d@7!HqphOLJ^fT-;J{G|R9$&+EuVSsB;Vt)PE56kES@~$1E!n(E2iUU4JRTMn zALBfam&5(2;7yUBUQ7D)y4QNn?B6n%4~)4Nc!k!YC2!=jpe~I(>P04^-3#^u-a2E( zc=izI^1={TMS%=fQh1gU3JMn*qLU%9T)ym4Xd5in>hjT~;*mu0!=Pdd<`A^D@pODA z3lT43xy^1=?_W##1Ch;6MHkDcZ){#RFlA!XpY3FdH_D`wqurwOyLP_A%xwUQs486~ zMcRcXZ{#A|(VX#hajPOxLD1{FtZYf~cv7}+@vhQiB=#ZJyj@@3^{S~X2+DOw8BX7 zLHkKe{K)v~$9tHlm_81Tr>n-i#}ITc z)sTUZ@n-4LTH5!*EF}?3r1U)Ki>;w1BZ*;&Kg06Hwx6bBW<_@tSUXO-5!J-yQPl-$ zPy^%KsB+HC=;D@Jj;XzJxWe^ORq2h!;;b^*A_`Dd)J7LF7EZrACJWc+bcwMD*o?)A zO;Sg3pN}Xn^h%=_#Qsd7F5Tbce{X`SkKk(AJ=W?c`ROGThDhla62+)s%kKw;P-Q9J z>cQ;{ys#C;E#HECD2l+3uzf%ZsNbT%2@K7EE_;{?<SzPT@a@as$pC%?mn2 z016|~$bB$ zQEAg*%ABv+gyg{Cvs4=**~PK(di*^Zi+SMctU80;_dK=sOkXnDxe6jt%VPYS{Co(S zs$K|%rnq%EERlMHmP2Dani{wuo*$Pz5MHWI5;;poM0m9LAZh+k?UQYeR2^X4Y>D2Q z#2Yb&E6cNnJ82%Jxv$wD27z+se0!rT8cDA02p5?p@ip(fWgc^au5CF@F6ODHyvEif z%4F#j)m{UjSi_;Nb(E_@o5F@S*3D~cAk?E`8qcets-GR?uFnx8nLlD)83YH+GZ%IM z`onUVFYhbXk-xgJ;Ddw3TlsgA?%9-jc`E{4~7jZ};ENu>i$CvPNm1Ao>O z`}(-h84g6?rSFagWOYG3n0(*NF4f^0IKMaZm5#^iLWyWQc7dj9W-- zTB(@br@SyMt~Ga+K6{*&N4UX#<~%scQNy>$M&1*R;Ja$KcA0Z-7`WKv%1PsYVOvJN z-%OpiI*I(E@>|Nzd=b8l#{W1C*PKrhBm6iO>X=1Z5;ZJ}bFs%v zUqsEj*4}RC<&9h))3Qwb)ed}a@fW+oC4yCD2^oS%H(F+7^;Phy&zP(Ur#C$1XBQ%# zBZ-qN>4(~iVhTaf_hQn!)m^*Z?NSB_zQioseWKeOn7(^^gzI3S0O3Mk_c76 zJ9WUXsEiajOUH>P6F`gcITzI!@9;;O_giCSiP8LF6Uo+j(46>g|N9*9tePi4b&unkLkmu=U04Hbv(45kb??0SA5d z%a2IIAW^iQRP2jUiV;w zG+Bdn$$v0vWk{;4DBAFg+25!}Z)yp|(ipUQgp!VRcoo|nv4-3hh2(t9BjTV&&x1PW zxHZnePpk@oC8FqpB8;t$B6b8Wh(Itq(4rP*-wAvcEihXY`3hDyUE*bSnJWTcs@^qC zr)y*S@_wv)$=$7Yts}y-{hPL}g(<2aCcYzE-|Kg-BaRu3w?-}uK!I`1I;Vu z-TapP*nvWXp?`NnO6I2IN>(@+UuP%?yd(q1rm$qW$(TIt{NqrYkDt)dHJ(=_ekQ zqA-2{(?VblSOO6g@~cDY%)E@+RVAyMR=+wsk>P;ltFly9!J7;)e`Dc)vycT1gGl5v zfvQpu7hK(v-zCgAPSfx99(hxHt$>L2?1|oZQ;Om6wFV;r3a;BM_KKoky7iH zGvk;rjS<+GHsRu6xfVWQFZfoc+3$Okz6a08dOOXa_h|R;+T|%orgFhou&&H`6u?<| zfO}63&8@1*ZG-CC2`T|!gUd^$Iq!&%p{lFuC?!GDomU8Euy{x2qt(z;u-6cidZ)(a zBR8^g7ftw)Tb{#s_4jKgxBgIzOJ~Rm+u+ghhVpepk?!0r9^B5-Eg#&@%56vpf#qv{ z1cz&9FhTiieMD}Vht3aFOsEOuY0+&Ly*=tvIXx#nCCOQy)7&ZeZsYN|#;RM7;BsRwgjdu^Dzq?5y{;6T#luqo(~qas2VN{ge;0qA$* zm-9`Tvs^XAw7SN}xr9kA;|kR@lxgQ<-R&1Ei^-3wv%|w~VOWnyE^{OAc{lWZn3(jb z$XBq?d`Jqv#csnRTb7Ak{K?g2AG`d+u&J}V0h=hP8SUQ%d4>{Xx-uUBi?O$iifik# zhLaF9xED~kySoH;cXxMpNN_3K-6goYySux4a3{dW?Wg;FZ{MfC9`BDms>Z1Eqs}=? z=30C1xvo-|EM?T!Uc?)*QnWulmfOO=w*8UG~a8qy6N zk)FjeOLS%BD!1-Y9BD-zx(!n$au@0(gKHqri-KHNAu7v|B#n%!;?0I)I-Rxo^yf=N zp=1i<*?1Ug(F^<{)qLAErlF@iB90XFRMgbfe@U07!IYMdlqAOgu29imamSyR3)7jB$a*=?nPz%C4s;1;3lDCxgLL$*vHuOt7nRr3l8?JBfzVAuIg* z&wG-LM{CKBHdtpDo${ZNuF5NHu+Dx@h>BrlLd|eEhF>%} z8i}{p9XM~rJF*aOpiWHoh)D*7Yx-VZ7|IIlrk{ckyj{A=Ys_}vjKP@H4AeozP1aks zO?d{(T`;`Nmq_QBk7@@4kcN9+;8=MzrTJ~f&YHyvN~^$XFEghK)@W(G^mA<+ucTF! z)qULC_h-w*HpqDa4qn$p;i8=jh_|1z#cp`i$!(l#LJ94!KHnoL%_^U@J5#W8)xpz_ z)ev>SuO(qz7LU!G!`sDw{XbK?yD5ZPOjOJt+T`9Y^6FmI|Lnu5RYA$BA*cS5O{mGFY23;y&O zYc5+m1LqAq?`$UNX|KG1p!U~P=9&6T1s?Cxev9TXTf z6Q|2#k-o5&43QERG_H#RPo9lrV8IHpiYPI55&<)IiU41I)=;fuplOqhg2>YVtj>7$ z!d)217Im=v32TtdI^NOF%2Ipz)F4zIGTJASnV;l28nP!)? zb!Jtd;Gm0K-zLz8%jr^inPHl6O+kI5wj#QmnX`VD-vLAs2`Au(KU@ z^pLYeMfw@CA~|AGGM1Um67P_oPDJ%s3ddb~lt2)K;;|fayhN!yOTt2s!tufsJ>-JG z2`fZpWl`&*t6Oa3tW-Be9YeY`tQn-vmbF`qvFCv7^sR+n0vII4m7nins#_n%E7#(H zQpR>k%rmrCX6dJLkmBK|eOHtLjtYUgN2u=DW9#n=QG#2uKDB0DP?azmEZ0F$b#MP* z=9uW-y~und;=k5k!aDzw?4kKj9UhwhP|~scI1Nf`_kXlz6eq@IDaOT>#l)pY$404# z$0m0b;3=e)FGuMV=^5qdnQIsssu)>S>|EeJU&BQ-!GvAcD#S^KS^7R$2l@K zhe_N>Fghw)H~&oo=fj-%tC!Cn@;?5?)W^d7SO(7KRz@@q#)ih`c20l$4=f+zKE3#; z0S`I_LVrRBs2zR?43{`*W*)?77*JaXMCs1XsE^T)T`rH)&CWxPf%jMNuiPd z?K%H-V;}eOf25rdKED4Yq4ck3O=oCj{@?VD{<=Km{95nuLklSS11mB7`{n!we^I3j zodj*Itv}=pq|9xMKO{?BKD2=Ti!_y>Y%PoOA^el5qsu-Tu9lN4@HyswMd7<}emyh+ zmN+G{x!51K_RPbWdx;9wc)o4hZaR|bKD@0c#)Baoi*0Qo{w!$dt?2lw{qEP1AIHK5-yNNl)Hs%Q*R!ZZ>ye_ch}G`ToA zv18MG!Kt-m0m~?*q>j1XK7WOD(^F*l$*2Kvoseja3aeSpcI&r5|Bb7@!LT&7cGZGa zxpX4#cSD)tx{Fim5WP3Y;_~pO7dD%?Qi)2q@d*07);B>;Z4MRLc>%$CP!DeNWm&&e z)|K{ewM875Sfy3`gV5|x79*h+jm~NM_R(^9F<{$*8~nuuysJ5eX^8|)Bb6Oy&!L75 zWiF_iuzA6S`oClb3wLe=4~OOUVbhNJ9sK0mqYUhRcjW%Dho$N@!r*QIYdwdA-$S-P z!gmUuRP9=f{-lQ8!mxMl&|-X?^-$K3r-9|n8Ux=4U!;BbP;k=l?zwE+Vu0zTNP*YD z*-+TY`lLmt#WGlmLl((CfT^$;p@~CR1r$XpU_U2B6U72lv>Od=Y@O3f!K(~bF$=l- zB=c4RSC5#TM~~q+;Mlb%q6!Hhyq4J%-d6iIv#XlCVKv{ICj_M~(g+G&i=h+HkJ{t; zQG_onlZk;S<-2vO1j9|r&7WRGB%o00L;~z#;_3#pA=e6d><(i|_+zJsr4?~xT}2p$ z91b8wc(w3vRfe4jD4MM>wrL3ud4AY$Cw>R{4U(sW6|Bi2gjh0(DLi8euk}*Dg4YWGb*hGn4PterVT`AaQh9KCeb z7$dkN+RAUyxV!0!OAyED5Zxzm+X`i}5xPRJ|L((4=8(-0gGLX-UNwxlgh?>`g}ZrNkBn$LU9>2TDZXc&Y^n(()SQojoR@9r$`{dag2btcIa-w zb}mu=yO{V12bh=X5%}g8kQW4|XV!DXAGkZ36t90oN*KS^lAMnS@c{AZ6ZgMIh=0FV zX>&(Ma~o4xyT7Vweh1SJj-`|Fe{Sd`Sjx`op$@)JvbL0;8fD|_q}_EnG3-}fZxIt|A@Ox4Q zoGVeEx3r8_Y1ISsjM&@sj|;R%sg=)6;=)DdQ9ZWUR>79D$f=`tKTPC1k!7Y;Si%r}-*5$0mDG2u-`?db zFiO8QSHvB-b#sNqmUbNCxexF3kk4}mud!Zp!OEXwGInMr!J2F0@SolC-~NPOe2u4R zu(HRbbT;Zhc;4q_ADjLJ&~!@SMusclN!pCuWd+0BfMvPu<~8Oi;lCH`C1<>D$mQ<`z?CM?R0VNi(QelSIZF-lmnCf9hv>gC)0n7n zdV>K>AR7Jk&%gFUV`b2<_W~7Oe_p7!z}6;n-SrgvP-#eOyTLB=PYlgKQbRXO>^fi( zQ-lmbPY+|7%Zi0hF)8aohMf7cpf|(v$G13om#BNCHY zLXYFCW+cV;)i>56@eaxyB7Xaao8$V!B*lH0zCZYIk3of(4y%dfi#>|lUDlRh3wptHU{_ASW-FD;Upxw69eU|PJkM}eAPR!5GW0>@F zxrQpD-Jb^2HKc$yl+q2whWw(TIkxi-WqJ_=iD}CwTWGGTjIhcyqP&(kXJQwDOVt#N zTF#a|8y}GMUOpPqGjTF{gBzB5aT$ht^q1$=MvQ5E>hjZk9#J+YJ~yK`+IwX28;>k$ZBg^KbX z_`}8Hr_kkt79Bp0=bdG(-LL6`iHKdQ7QC+QOBNsQjX zhv=(}=YdGf@#Lkxc`H!VtAEP(EQ$~|>(?+~068g!Z|hv7WrtQ5 zC?eeVunEo5PoKgb93x>dBdZ<_JD5qRt-#Gp5KGSbJ)QyT9`?*IbL(ZnmsRtJWa~aP zg&`F;6T0X2ULfYNS7q`EgF1gsZ2Ao@!1$ggx*cE+kn{0tS(?bidxF?)eZKk*PasaB zv{WwJcm=-+c6I1Sdy58T7>2!mmoX%_z>>g1fTn3k6$yxU1+odmo;HbRitI^X_R{1g z@uN2m@BVTo%nS|TE06+NIk3J1JbwBV9of3PK8K=Lty7Dm4)&Uek3qQxxoQy&?$Pej$ELt)&@nPPo}2DZ&)MUA-2X*5fDM_~iV8F!XL}8wc6**K=t1cQnAFNa6&aN zI2ipQB3RNid}u(BaT&1Hmqd9hAUue4;}_zY#2EPt6MHBSrZzeB_Jl(Zfg&kaa%+HE z+|2A(rxs#elG{rmEU5%<%F}`!L$-RZ_+0_o*Mg2QrLKzRtJUYxrC*=ppYn_Zc*`as%7mz-t}wP5dG&COkMNkJrsz3-RgheS`;Nm0g{UQA(fZl9kQ9 z#}#nmt1AFO$|EC?D4nsyRN3`g{lg8&oYWrCk2zn_yT9f)$o%zZ8Ydp zIh2T?1c|lS)OUlh&W5=4V-r25+KDmb;>I~i&H4v})w(5*9AO&DITJxK3NsdqcD~26 zQa(JdxHvu_SPd3jgs^_mV6PfxrA0wTl$ueg16 zxAyz#3m;!%K}q&O_MKF_yKcfgrN|v**=pvCRb%{%tYi5BcvHjQyP>T;r4<`J6;gMP zBEOeS*2Gokmy;-XP-ik4@GLwwnUFriD)QwoN7}HV&RifB-;+SCc>oo%f~qWcz6Fzr zaU+F(5g`2Kpfx^E@+Z338x7*=dv<$U1^8px2{cW@w(7z?a8|~w8f2Mo;2pF(v!2RN zWNu+IKso>?S@H1v5^q9k*xlNioWW(n4hLNHZLa)mc)=po`x`mgmNKeCf-b(%%U!T? zB6(c!OAam-|3b@8`DdoxycTaYZ0Tw7{K+uOUj*ZG21TD1s3u3DZ&~cLFLoeP$>t@{my-)kc=ZogsypOeRP_ZfclHLS0A(g6*tb{JpwbN;|wk&F@xtu?R;SIF`=dug-i!x~Ri_(wsYkv&z>t!dLs%evHURw5L ztbjbinbZCrX~EYv8;Ub$8DnBqqOEAiOu_l-Sw zi!f5mO>yhKMupFe9UeRpkNfr{+iWg@+qB-7U+bkDA-B}8k)DR2R1YEvb!-O?ItguT z+ZtST2~Qi6iDEJP>$s!q9Q68v>exF_E5S~>n{FARv!^wD?7}qKPq%j8*WVqyv;X2N zD^34W5`zNtdSQ=;o0KZrAKZ(pYsjBz4m+@-(nsc+QE}497T5%@NH@rTF(JnO(2f16 z#6)b`1xwWVIf1qiC@jR5$Zn~r{1eGcTiQ7rU7NQO9BUM#Cp%28ps+sm4|j$9_J(%u zKF)8=RE4=f38&Z=h2LQ*MNUk|k?u7fztpL5#gEh^i4)}xKTguhkD}?FSkC#hC{kDw zZvHIhkqoNMiu==ogJN?f4C3cL7X5yOA-51?V>#$YJW&=LxS&=3uVy#Udb+Dcg%}z;o7GoA zFqU%RKJZ?l{KxoQ11U$h8G=CRi`txD&Ftq(#-V*Z?24i-Yk)bt86UM;X*y>Nltb^h zhX>mGhjTPolF!(^VL(FM^Q!TSU3pE(BImf8yz)KrCMlBj+ONLL`Py9wttu6`<#ahP z0NU|ZRCgO1fFV5-mJ_%~x$(Uwzi^-gA12o^q&W*AHv}T;ws_ae4E>h3Iqqc#Gu6~s zL(~?`?cBokk8OFC%Qk*CNV5lS%HywQ5e-s#gp?+7fDA!1BM9Z$;>ZRW!LSBtBAjvr zX+!C{Oqu;~+(8`;+aMvsZN=z*lwuTF!&*0p#t_qLW$s{fdn{L!2^l2@-!*^#ACT1> zXt;f;svd}^xYzg#9bt8+gWq*ThkGxgOyqBn8^-tnp=EH|-7PUAN1D+PblX9IIUVca zoq;vy{KwR-lSK8h$}W0_6+43WuyL!;SA@h2!YiF1>mAsZKB^9XFn83p=-A+eRW9&pB1=td+G^AuKtA1clCs6@Fvm>x zepA#C6z*kk0ZyJAeA`EXiNhzQn`U<1?|2il2>bDU%Hwo$JW((q13f*$cRTYdGm!bS4i(@PQ_1mB=d z{^L?cqNvs9aYfpH#O%%){xZyhVt`)MZ!8tck&a}$>ueA1i=ldjU=R0>e&JCV5&I;g z=ma14PIX1!uvLqBmAm`ewWggs(9RAc|81n^<;&pm9)74cinY0QDZ;$!cojr=#zQjM z_K&EfC>HPs#RV7y5Bwo)aE)j-7!m(AdBlh7pq#Hxbfb8;#Kgz_IGpqGp>a##Z?mSz z+5~T>=E&XwR~*l|tRU&zSIWoDa&a#{;&+7qp5EW1y%1+V@Yd=_an1JsUSa&Rw)m?F zH!FwgbG|Sw&xvWPcnK~v#=0@`iJzR1y`P#^k5O=EkTF$#rau372wyK=4@T#Yn7+$p zU4ywzJ?=*91HHJN;QLI^3CB#w3wQI**SBl5@1IwZ6_OLCMs<0TQ5fj>yZi!#sYBhU z4b%l;uRUP}rg^6T&m%zv7tALwEjKEwY~oCE z4W+5gMH~>D!4ln`woS0d>qL`P<+<8?GdSb5K!|1|^%g~Dmc@DKYPE)pR0YR6Fh$jp z!W_hg3Ux^CG3;@BXVYuS;1PV4S0K1YLTeEIrBWW!6SDnEhn8M)h>KYd#!-c{zb9Ng zLcO6h150V468B)0g@qoG80(_J+B)A{Y354Bc2S6Ta;Fs9N>c&8-^k}IT1HFo1Xb&6 z((gg%Ve+-imEBAlZ;SHSnfjEzqgA*W1#r2ElrFu$PF5jo!=*GIIb>*vB76XoRTKu{ z`ujmNNJh=|&5Rjv>3mc>%^*S@IaM7R)Ls*#q1=NLlF@mZ#Y>Q3JI}q^SAhX29Y&C- zam20&0Op+sBZ(GWDN?^!@wm7@Z`Dsib+#QJ3eLipc5?;-Eu(Rd#T8l&Ge~ncjWmNI zJA778ZpCq5=6(XM=zuGtzhD~XutGbIPCv85ww;;V`_>s1ahFE4_45iv-Ha9igLBXl z8L|OpzAJ`m%>^c*I{YWh0qaZXeB{6hyijWX)9YJ`okPTpY9?adywfi`6H;jw((IzK z7p=)zSA;Aq-aj(|9x?=3PHj7GpR6Dx_5FrY=%iy&CH9tay z%#cY#=tb|@uX%l7X5TpdHS1*La21upV2$sQ%EidU^QNM#;(g>`ROp}oM(g;i;kNxF z(|z;9Pi#J*FyH@+pD5c{{x3kdU0G5VMIQC-ylyt}_*236ehk9gI>DUy;4u6!p*(1Q zlz8w~NiKkB5t9+8@|)j#e;_e8GKP)xhoTuao6W5&=46J9L||+K?OM9yMf2gydGjVm zhR@^cN2$wgLlvU0#Scl!X_kOuqLAFio~%G0kwRV}Vjsaz>$x_Ymuwiqw_~I3x+wI6 z-&=3BrPb=nL7k3Cs*JrNhDl4O?pCXt(Q#DfSKsfQF!NL8H8G%9CPAOJKSA>~sB?=W zd{x9|+);WpJI`$!ag^RGe)*7M;R=PgMsKCCaVWbeiiwrXtnzV;Q_yXhLcxBW(70Y< zWo~`YYj&nTJpD`KLbGL}58m84F$+@-uzz@9_0{|ik>XoB5MTfmYFZD-)e`6(?e*`h zTTkwvu9Zx6bWS(1W^=lb1RV)3@#Bpm#^w^#Nra(4Wwr?Mei5&WB5lZWAz29=ey}|I z6wBHW9G$o>sD{1i-zEr&tYD-VZ9c#!V3L(xHF;#BJ2lv`gPLKk`~`LkcB`^4a7;Ip zio};B3|jt{dIDV4bU2)v;!lfGSon+S7$$7-}f{U(x-;WbkF`t2o@{Y6<- zA$LRqc-+7L!_ps>*c)kfpk^0Rk4v<~<6_segrmO1pb7a1r`Igo5!PJSw0h(*BZmH< z)_7XnCz;TGOaLz2cT7FKkdiJ&Q~)$iT@jq{j~yZLKjHn)A7|p@KBi@m{;$6Cud?x9 z#e9T{rYedm<~kSyO6+F?r7lS{C3<25tMVk6dCIU{t+E`s0+rxBW)P6^*l4F932!Id zww%tpSQ{L}xx9k+X{!F2>{)Q-oC(lF%w+B@Ho>v^G{NiXyU9!Sw0oiJ3wBA{5pKw5 zqCD0={d1Z2tk(;}X4{aXHRC((H)tZ z-7yF2q0cjOqXk+U)e#Qnf4<0?wP=@=ht||y*7XQ-d8@}2>Xb7YyINWi63LQ=lq2*o!U7yP9hm1-I#U*&FZ!G-%tS8>%{A~> zv33WIZBSa!X3mSyAhp~~$Z!?i#C^0@ENjiE8#V|?5B0#q$QA^*=XUyF9n!E@&3$1Ml1`L=QgBc!}hyHN85Op8K;Yj zvSUuqK&%%(NU6-6yjMYf`Vy_eyo#T4Sf!cLttm(}zBPi=PzeBpz!UOKdp2YD%frIm z4Glu#@C>WmzsCMTV|xn3!QN|aFWSbOx$V2YcQiTEyaXb=>5`?1O;&QFf)AEI@1PsI z8cs8+tqt{LXsRw3Z&Ar3GPOO7U9$oO)eHFuIyZAH3>!A z$zL+y4!3dxhwl^Y>uVc_%0-l@0_)b0?29u2FrI;G_E^EI=# z@Ku5AeF$)~YIq01?aqh28|*s~XM}?`2a$xm&WWW-M?wL+{bN+*DT_xw>|xSK*!-AreP`I6liA(O^F{60Y`oIK6n8qKB7}mIG;($VE}>1Q+RQIzV?gH=VzZ}VoqMtEpbj`X5n&7*}1|U zGeJ12jHbc)cX4TUYvqZs@U2M;{4Q=7bNsw|XWYLiXou8AjAT?zFm_P0mLbAg&qRLF z?1G(MccDrJ_?hYBlR?FP1AmGJSNP)4qPd?A6O&iPiRT_n$Ec~3Z&Gu51i$8+7(CI8 z=zUiwGOVm+Ah9S$z8H<(Y z#kDCI(e^$6W-#%9<|#GFiuuBW9Ugcqh@HMKmws$#|LaH73+h95L=%$iT6Iv7tY`k5 zlo9ata}{BCKvdMqmLt*J^e+`r?3~DsW0Ubef16tJ7xH*snBpz`=!zEpJE8P{-s=1R z>AfW=X#Yhh<*8M#b&-~?OWkn=QHW63pz0D6ntez0gNfmOWEBtkJ!GO{LPjF{D(g*o z+x@{ORc@<=4p9@Uy|FuA<9X0JZ@xLaxG?<`{J2BpFO5gb$`j9R#bhK~5PJY3P+YfU zYKmwg!@QRM)i<8KiS(T5N;pEzx=S0iq9y5xN2YxvO$z(1QC4K&B=S_~C~-T;XTKr= zxdrKp7)gl3W`Gk`VB9kXswD;%%f53`dGa1Gue=dD2RJYk&S7OUFq?2b${C}7D3mR4 zVN-uDFUF&q!MY7(gvFRYAbOwh4=JTL1JEd|Wog*+q8@~iRhAeX2(E-sW)bQK1Op-H z&s4}P@fLoQrt3%KT=Q93%!NU=P|+4>OI!gDyJV7kVQX+HVMS*v{ck8oy>}}z94vIv$GL)4T^RZ z)aw)U3wue}LyuCRTX*QCP#IpK2$)h&ywT|3Ac^dl*M-&BS@G=K%6ZDs3Yva%tcc>) z|9Qzo08>l%->WnK_@MgRkID=k@qf&m|IuGH`deT8KilA{maZR6()GN>q22C*9;m&q zd5HeT1a`P}Bn^fJP;)=56{PH8rDwXa_Ht@O01;3!X{MXwwc^kC-h2F-joMyfHDBUu zR`xV&ud%Obbg!u-?%SDSNi1>F_v;TbJh>%OE#9`d$w_)Gu|*1!7cT4t|jT zitSgUn60`LDKi(M1qdQd`yQ=uCPS~>^{))8Z^(W>Qdlv(rr2FNqIHJsCSg5amb$e4 zzz7_dq|{NFGEdSTrB%MClWC1qrj%o{pJ2CzRnabGXE%=zMyr$742<1Y0V;M+AIu}! zYA{O#@=tbO2K+{a_!b#Mm+J2*Yzd^ z2iX;wgCS)oLvX5Y3ZW9s3QNA3N*xBMDMlw(9fEemd#n4_R2$q;Z=m$2918uS=Zmsi z2{_%8ExEL2M`L-T@WE5+Yb0?RI!#wcc=#8PTsKO-E;T$Bm0K)UlyZd-fDfBsp^vgq z-a{;XND^_|)AaH;Ru{JK4D3{Bk6xUQeV-yZic+;+#G%@cT1v#{e7yE|8KCSiokyYc zdnwVZXn|3n!M;~5H`qW`E!9X6OjOKCaFAHDLTu}T1*+Ft>$O?mh!iBsVl$PagMmbf z#?{QLO%g|#jSfGzsxcoDH}}-lnqiQR-I!GC^bPA7f-iRkD$AY2@G@Z@{z5C8%Pwoz zYJn;Av=c@VpHnEPjyN-uulS;u5i=MUMC_~h+2K4$pcmPg0j)f3EKd1@(Lk>dSG`19-0Kay`p7N+6()snou zJyw#f6GvdN?rAB-QHmQVYNs@qb%nkes4S5h!JV}5AwjM${BVjns1JO(`6a1+&I&hc(AR!Es|_Vn@BSaW$x6}0_7Np4{q9v z5AxB^j_7~;;9CGQ- z=<4m#PAtH^_WRS+k3)9{K!g}=XWPPg_fk@Nza{lmb^4>-jvp{wuk$jATpjYXX$5~A zqAboiN*n(?rfWOENoH?i{@_Pk0?yq+wc#HvA=ObpnTR?D@A$A{Ai44KsZj60zcET( zvsq$7%a6!K?@|Y7r`P(O-n6otE-xHDSaR zz#zfk0#4b_-rqnq<)S0n>NmXRd;~+gLmuc1!z(g42j?_n@+xPvsO+RID$p&*jCS{X zMj$o_JIG)e0ZF`HA?72Q8=4#+m`bwox#aODqaWaf-t;p2KOmS=eXNMaN-C6e^zPWMFv9CpHmO+n2A?TX?)2g2+Pf z_APBQ&J&z+vO`wn^hx%`G+0RU`uvNo9mt;B2aF6gTf1gY9UVW4A@fytY4GX zY3($WHhGgKEfEGQ)#;<-YPURzpHq5lYIfTOz4yU>H#{&(=Hhr;A59=Q7{_EXNe4Iv ztVt_S5#kyv0jzqz(&Ua6=@07(32B&KvX_JV+n=ZRFc3~39TL<4ZS<7YfR(kJ(xGtk zrg!u#J1Q+TT$Ki=pzQdgSpuz!*Es{_bBUJ>$RS_+3qwFlGzG-#N-}>KozRU9; zd#J$8^#ZzjldVT6b2yX-eN&NjG4Ol?b$WV4P@(+WnfkUk$sFH%53rBYq^+Wcv{oq? zPqAFQ;x%O|1BBRnk=>H7sr|WW{G~kMvA8}l&YGq23?w9(#t^8}p`(CSw3N^_?fm-R^JX|d zixLHZxAWaC zgm97*26O*h2{7=Ln2)%J#sF57FNHZ>o1E%UNc;%fef>J3uI>sKhkfT?eU{BGXWL``>{ z9z8=qv+H@f=lPnWY3HBkN9gZxQHoPn_wAA=i>EIepg!&w}A7yCc2eKIvibyYb7Tz zSx%KvV1`{3WW}If9Z=MbChesoJKzwwSSvNU3#OUut(h7Cv^UKz={U%wYwJNC;q>1? zaCM5vFgQ%ka+p1cG?t0EdlLI4&2cV{uU%C5oB}o$`S7duCk{M7?d8i$=|=StAj|jL|(LV4lT*B}j^tW-((uAT}p11NZADLzZC{YhP7$F;UR(eG7&% z(WrwdYt6`0Xyq(@$8InMFzt*S!1d^nIC2Ir+ej_~J-qa>5SPCTsX7)f@;<`UMqD0& zw57ra2S$r@Gx?GL{-1UUf~abz8}=Zj63Wq!5c12PJ0xUJ|5Pv4u8VM-+k@N?Ye83_z0=%8izb z>+|L7=Qen!_tm8hmW{3J4XrhujvsPpxELr8QR$B7A3ZUh!xx`JF0jqlt>eQ_)E^I7 z=t^?_PpQS5G|PpV8(YA`B^A);kH+Cx=jl?=1Ir(g;ELz>DgEN%%^kk^YhUxnjG%Yg z-is?p;OvzsaQ_hx?!7b*883c2AX`dELP@bC^y85J4uZt@L7Zu3=#yl!ob02MRwM>EL4tkkV%$T^p&Td8&mp>OR}pE$AsfL8x$iYnP_+L=yFsj# z6!--SG=9~TU=^OyV7=_8t_i6yE!4)802+8%L4E}@nUNxiO|?QBvt_cjbX;rLabZSV zH$_8+9$8;+exXGj+d$vMmOYDV4aZ0oUzKnv9E&d)7LIr87GI!6mwHG(M^$PNwNA@j zpIrLfZwEAjdEr?cc#=` z@9B(mjioKg{A}JpmXd7BWrH;~Z8&3iNQv`M83NBngnL=Y)7^E#D&vi_UEz_840#Fkvj|n2qb0J13uK-xaiSd@bu+G`f>0 z&EHGFkb(IFW)Z%1mYUJ8Q$~Zje;Kt0MI2m{c_j;Tuh%QI>Xbb=60m6Om%zfIl=dsM z#_lg#!}hH^^hD|u_PlWOciPWXxcYx?n%J1?kW&wX#DTeA7V00|Ppy&aPx zCQ@NUkv%WVh~mpo3HwsW@ZbsLVPf9rVAjlSAf#NkgkvbWPpRgwB%%=^K-RocQm|gx zyH9vpQu!@KwGi4J&nY0=i`m<^@57W3E)E~=$T*vyl4?ptb2(TH{W9Zo^FxonW1I~7 z$H|vcS%HR?QCPa{`!#Qq9LhMq8#EN%Z<#Y*p2+frj*`+7Zw*4!CU@**?RL{(#D4-z z(d3(^#1na0BmSNDuVe_Jg+dmXd|UM0o>$WFdso@M*f~kju;=?AYhYBzt@># z*{XsgQ_mRp9GZK&Fs{(}=Y@u}`clM;hZBOdND38lHCcH43ZZTBC;jAqo6MU5W~jVV z&sg2M&l!v=`$9?rw@t)4>A57auwccZ;H;A6%xpMHjkL!|} z;hJ?QJS6O|MGTP=76mkIqOswc#d-CI$P%vDMn4PM#Aw1j#cP=kS)aI>x@|RaKJB_6 zI*QNKxbgZK$596kWC2Dv8cPqdNnJ4=io7`UoUt}{JlqgFrB%tbk2MQ=!TUVrR5$UypB@%G`SWs(8} zRqt&ALOamoyLhm=8}%Ek@3fc}@RV1ct6(&gx*3vF4(JzN3!|3T;LeuW;}^tLu-{xW z8Q2X~N&ti^kvQC^u3=A(-8M11j7Sxh+>0u~(-{I|3&;y{x zeY5F!Iod@*hXRk$88y%0nZxJ%4IXU@bWQhbix!_TtK6WH8~na1v!7AZ)>?#ryQXm0 z`wk&vE+bQGX(6i;8Yrs(Ntq#Y<d?o%_~lCzpjA#P)l-Fxs8 zZ*2OEBr^TJxCikPTxGH%UzdMy*hFn1(N2Qnv*zT>27_@gzII zP`86mqredmAT8b}oOEK?=?rzx>!8J9!GXSyqV`K$n5JPh!eigrh;{aqvhX4=k&+Fxrg6@l7`TJZ^zt{h0fZ>UD)wM7@wq}0U`?><<7sUn3 zJNhxTyUuPE%PW$omt^qp3cO3-SvGZ^wnm|@Xg&g8$i-t3Y9ul*UNFz{3aSt%7<5yP z&r%g>jnZ5`_{+@saniv(|EY8u$SwrUc9rl%Qqe4t#IBUn(l4ujLSN|3G|IYF+(;6v zOg>5((97O)=gFa>;+x{@)sm~kK*J-Xn-~*e3%jpvn7pC+^+9Vh;End}pTzSs-gk`US#w$5wTEjnnfkpxRMTiC2qFTj(UPa08z~2L8S@Np-C~kh3r!Ny8eL5)+Z6N`y0PCe+~tF)4Rub6~>5@0Rrz zLqRefD4^je%~EmxkrcS!QEvLF`ys?VJmoKn*d14ON$7F4c+|^hz~(dN^$NV-`g%Wt+P8;#JF3-J00aH2 zf8K#Lb_QD0g^^2CQCa57q6EH}-tETSrKwX{octDccna7)dgDbxfD|xPG*( ziZ}Y_Q1YcVrYvI3Ik&~=m9eveYgaNJw$X{N5TYCy-%Gh83~`>S)i$~oFP#%kNIIl& z9h@*X_0Go=U9ZU8;?-Ne`-BZ%7TrE&8RHM+Je%k=v_L(u56W(7nop^B0}`$@GA`J? zoOi!(?JV#p?a0B~n5(aG9*yVbhx8-WG%d#U$FZN+kgrRWh61nK8Ojvo7Nx4xq!G=J z4JIl9-7Aqn)Ttl?ZRmz5eIEas`sGFXFt`9@ld^9lZqgArOz?~rt#TeS{xPL-s@KCV$Zm=%Poz3!EK>jN@!Gt9lq@pHAMKDY z@Eds`rIoyuu1HGn3sha0i_BwBP8Dxhq=Il~UEOe{o_%SJx;chi)s7jPY{blpd4f+u zgtY8-59xa~3ZH@|E#(Gd^twa!bq_gb#_z~W#ZxNUE1qy`ZFrn3h2J;>E?9LXyoQs; z%muL&8_LzaEF)Q>8~c)uPHdS?wLX|!c$0ozEXjlS`a$nRP)tLXfQ?bW5(Z3 zep}X0uMmDOyxvC+h;sx${(B$d6NmpEPvI_}TZGq-BH=;I&szYB!CD9O%(y!@os~}4hvd!igs66KJZPMHc>2I2=Ma?va1*~`P? z0nFpMcd(Rj({vz)!#;VYaWreMv>2Z;woHj7Bf__g=1maBn|5^R)7ZB(lDg+!D88cK=6ofec)wNQgg72; z8eDu?MNr$tDS(Ak$PdhvSHV+X(|KQ8nIY9Jus!!bDyzJuvAySFtK{>(2^ySQSDucO z`Q&@37y|0r@vew%W2@azZStv&Qav;@G&@xgo`Z5}T;%HNsXH|r+A|kqmG+L5()A{7 z_0{5okFUVk9FY3+jV?M%pTvj1)pywP#yazwtL=WnSpFGz`cbuP+vm5NJqD2zso`_6 zqkR13OK`vna%Afz0w`1A`CP%{{gKwtvD=M5lbNxSq-0OlEmdx{ zQUZ*x|6gg}0gh$+zpsQ68QHQQ^Rf3Vd+)t@?43Qbh3u70_6XUsBYW>nWEF{sNQB?* zTfOSh+uQ&6-^Xzuci}qEYuxuWKG)|uKl_zd8hUHb%6ij$*BK8`(>=Qu!6#T7gf1l| z+Op*BNF68G>n>$Bc%jKpv-?F4?D_@#PGF9)4%8~;Dr#^?s1F{#s*61FN{@iue8hP# z@`P>k-r%WbiCRT-#L52V{hc_}maN*~PwDz+5~Dgm0N5}5>t|4>GNbfAcjN-*IBLKl zj^%I6aRMg5k?n7L(+=P49K~_oa%22BUCmSBPL2^y9x7o0%2Fr0^B3ALjA9 zEKu?tttS&7Eb6lk(LESWNrEM_f*D?78+()#WmiP|G08j_+I!`YzUKBJ&C>hy=m3@< zO$tw0+Ctp0Fae~~Q56U>VM|O@Qcz|ZiYllNhsS;%Lq{7p67zmypuWp8!dR7H&ZGN9 zo{HAOo`!+=d|ANOYa^WWFqiZ~Mo_{$UW>zMS@pzpRil{47)hUgPqBS|E1%XzCeyp- zsuZLdEe4N1E$@}NlBkUk)cBgs9g{KAiC08i=q%!`_@O2F&-Rc{y~b#cU+rm$24?n* zf=}a9ZecrBZn{@LWstFE1l6h~^f*Z~f2t$(leY_oWRTZnjpoR)Sviup1Y_z6BWQhS z#($e`*O3f9Ret;h{BUmGA~X^^JZG617Dx4#UH`{bgJHzpgH#Vp+|FB-{sQ0zE!~NF z)4oZZ4?9V5A|}xSs!b(EBR6F_uC^J_o|L=Ny>iLwdl!C(mE2HU#f~miMB6lxOA&=x zn#lMV_if|?f#bs!mpDk)iZBXysbDHm+asG7r$l%Zvms~6He%ZKEsd%T4O{MwtxxFQ z`$Y1?!5taok<59^A7DuE$s46d=SEf?=TNhnI9A^j;bZ*O~P^ofRK-8f0jxVU5JkK;9E3beRj|f#BvuxsyZn}X~ zie)A>R~u-qMV>a!Hx*SkFGZb{Z#4 zJkpM^V|TbDW)S9*2Ns;WcIdFSz~k_NZ*8!@=3aX9RjL&T!(e7c43qMwY^qiu(l$*V zgeFlTGlNQ6BXI`9CaBT@(T2Kq0Cmml2}xyD$7|cMC7XF|WY4+cA(l_B1H%W}_E=U^ zx3F<3_MWV9vjngO3U?G~AiX1>dmdkdj~{>Lcb_wUeO0BdveQ$mU4a?RX71!15gx?FW5md^Y+QobYfoZE$ddHh2r!h!+;4GS0!B~k@H@1j#Ab+ZLudB^Z09vbPJL4kY2Y(|X4{W{3z>+OxoinelXyjVD*vr_kF0YC0H zmbH;0$O%lHFD3ElA<`|dful)JS=P_qms(kAOhiGJSCdAx21D)MZ*7XZpxWO<(w$wR zXp>Lqqif7k8%&YuD@L2QLEu)5Hc7TP0NHepM!wH~jh7uf%GuKwL_L-qTX*Gw!$XW> zC5(JF>rFBn43}ueJm(f?kfV4jx>57v6JOo0Ia$q&(n(e~1JSgv>J`oDnez#^bIZCk#$8t-% zQqY6ss*o2syUQ(^l7XN!$c$4KVT#(B{nFdlD~+zVBW_!Uz*%k!K_^ zC2lP0CMn6cMV{hGjIMRoKjv6Mod{Vu z;Ic`A1Ovl!xp)7e%JDZlXvM1YYWN};XEGI#wu(1o?8J1ru~*^6CA8oyGR+W`4cZ>% z`Bh;yfTYy%oL4>s!Z&YpHEgG?G?X62gb?z19&GPy%Wqr7v-Whdze!AGad|uVgs1tq zfyL!usM-4j_9dnVcnJxebRljybgofCQoS?8U**}yCHKb9O+m5#svyv-76kOk@{vH4 z@|nPf+OCvi0S{2iqhjK_HbN+bJHD+c)*nE0q;0u024ceTnZ~MPZ0->)M7TPpsBgo= zdWWOO9i4K^nv0WNVz=&?3rdg`uTEkrtr)6NPd6lYFg{`Jx1zPANlL|&TB}m`n5&Q> zw=PW*)n&7mdHy#1#8YI*wq`HTi(hgg6|&x2*d_X?$W4pIF>ow;WHrq`quo9vEj-ss zX{^#{_C1r1ytPPQ0d8Ouyo2iOxOQZ*xzOv83b@C_C}JBessdU{(xJ9?q?)_3>5!d{ z10(BNExw`pu&`%yj{6FNHC7^Wx3fxCTyIv#hth%FD$HceHFU}e+Q;_yDs>+;CUfnQ z=JhGFy!s@(#XqE+nNk3|1ovhLKh`Qfqisi?Pg~6%&Z#_+L#5AN5QVKbSq?udOtnr@ zei?IaF(=q~^cnm!w-F}sFTLi=2vvkSE?Zal`iY1}du~@y(qWBR;ARHt1a9jlw^7t^ zn?JB*=-oI-ORko9G0r-;;e@R7B_zSkA(y=_?p?q4{IO__=Yg;Scd$4v982-Ss4II{ zN)g@dR|#R2>xS#kK7$QWv5k?IvaZW?;v5L`#zwa_g+cCSw`I70LE4Tn*g`i!bF(=K zzOEDqrzI@Vd4({Ts+Y4ppZTs(s!caCZu-hi`0hjWNMnzHQn$VEFe-Yc)It)$PGewM zM@f^}-X)du(o)A5lcO@gQ>6x+p9WbJiHpR}cVDOqXIHwGzVh{uJjw<0Jr36VmrQY` zh&gi=nJ?)fU*%BwJ_kXnabKr7#Sw@mSLPu2>T>2UqoZUdBajqme5J1jqQmi=PA+!#Sx=A^XG_P zKgHaO;EFaoBtVT|9leRYp8Xc-uoN@wwY$a82$g7z4e3=wxtCsf5hy3))ttRHsR+%v z5m(@Cub^Jjy>o|awHHF)V{)yuPIk{|i;|0(@Q|QM=1l#@>3AN$pm-drdPMwi#hu(t zbwS&enG%xg;|C+AGh7zOJ$r5lE&MZDxV~ed`mqNa0tgc+cA9iMqXIG8UU49?J71BD zQ{;$Gl(8rDRg?v$*8C0IdNM488tm?QD`3!pYC5@2(Pt&2B5gw;Z${B(ahtkGow#w* zT3vM3F$JHHJIcVd`VtLe=0eu5mmZdXBpV#k_e|(aH^$Elu5+VRr3XVF4qPJ-`X(u2(cUU`@-y;giq{9ck)t#$o<-`NEoh+ z`3WzKf$NBkyl0Bd66bhtC-baJ#w9Y5z{|*Pih4lSa%&V8kZ|Mts`KJ>ex6 zykA_{m9+k+xKLd~w?&$(jUhmVok`alg54-zbd8C`ygdj0;e8<kXC7x)^wGf7M)L9s(j1ZkJw7j;T)`FWquU6zNH-#V|qPzE7*{KQSRrDPsF6{ajsQJIA1Fsh# zwi)R5Eg_oJdnNc)_RtEIK8Pp_d&8Uyl59oS)evCSn^s2Edj3B4l^PnB_lSj+!y4us zJ9SL)G@FSHvskwSPM8~yU+gNl+HgIvZG&RUGH+Oqx$DioO2df0s*a*HD<4Elncm#? zz7n21Vhs&FcwuVZp5A9mwQ&E$#q;D`|m+dd`6*n5#N5s#lC_nb<}**~hw zG_V-Khbt(Yx3~CO7e#>6@N&b?Xq3?(0tcIKp?2rdmQ)YkQS^i@K_w!EY*9%H1xKRB zeqz_u!es4`NRSV!T1{O_r4>U>+ktC@#xd6!Gi|q^5)Gk+>$MnOyjBUfk`ZRU5mq-J z#~YfhhV{JjvTU&*h1-;<%?{2w-2#mb-4mvsK1vvj2>cKPUVwX{l^+)f7As%iIwFp9 z6f@V?d5Cz{(^S-|W6Ao$Q+o8=T9oD6LqF=`Ba4PaD(h~+Rh&SrC>ra`pXYi#*EOtr zk|awH?RYc0beQHf2^ExdBwjuXhM?+-4U(99p?au1 zf+)Cv%aao2(mL8G+E>4W0v)?VRzHgZK(kf*GDXNn%-(-tM12`2slK!bnYrkwi!!b2IOnOJ=9z z`&}fICK1B-H+$) ze4eU(a+bwr;;yTr&N^H{2AOY8M5y}YNaRg!8;EpANW`4FN_n0k0X|ZnZ?D!6uh3>< z>%QbbNV*BmCT6^a3(ni2PB)Lctc)+l;_g&gg4a?>+FmuM=7zW<=_lUO-Rf7gbjr?i zXPyqu&@o+Kdp`S+BW=;xhAq6AR;ezfQ0j@vV3A6j6H8yHqh0=>E#{k;rb7m`gJ-6d zbGgo5C60`;Nf{hDvfG2G@NYt3dvdfNg!pF;6Cw{AF+{6@gcGfpIoz+u8|tC;4iJ!j z?J0$uP)tJ>G9(i(Q$SLn72zr*;X$lQ%MlIYWH9VE)g{x*BCVTYkiT2?g*3{NZK371 z`JS*X+)AuzZOD!EH5gAiWs=XhkgN@|z9y30TLolKk4GQlZtxxv29vcPc&Z&wPmY6N zrO0|IcpPt9&-<0)x9+RT;E@?QM?khvjs_b7*CT(Wc=tmdQU=K4alAI#O+n7=dyoHT7TEnm=l`tB!1hW537gmd8Lu zq+2kxM#8nG(cu1St$PUjRly)$kedGCL0*sBUX$D{%6rXvuVHL&cCp`?whek2;c%By zkkmF+KV)rMiYb4g5(GpZTyA*2+-D?d@Q!Sq&!clys3LX9ic@eH8TXAkmLG8~a|e>; zb9uzhf_uC3REip~WX?$zjomVai3V|vJe1vV`%hm=NH%gBFMzRFV#4-l+jwu_=#6}G zyPYk{%f>lV))ES@pkk@R*5@L+k24q_#uhq=+H{sjXQH(}D*GR?jV3 z>Q(FEbMxbnA668^(LJmvjwM)s@1!vkz<2Wc3~IT}Kaj)p4yb+);N;j}Nq-3%o7}fI z7B#nba8zW{u z{zSpkiaCu=))%0*PWFjzU79Cz0OP2X5d*_n5!WJ79IDhr6sqw-m!v`WwM4!XoPj*gmw-2lH7|v4!i3X&MM+l zZz7wXyjhk2-Cv{|t}44i|d}daW zm1G$7xiV6KUQ?z)(45rXw(2Ge*{Z57q9LN_NBS=7!2W0>jFfGv>Gp&>del^qP?EQl znSKq2$&en7QGz{Rb3SHw&`QC>c#PB*fBk&|p^Zftu=8_`DVeq1m5_y_Po|pmhQ(Fg z*0t_ytH17Os-0@D7K@KN zsL@sDPiEM*<-KB*KpDN&#w51E;^Me4Ar7LAwG!hT%y%cLn|m%wD)I_u@)! z4vxmwe`CjZ64NKy#*Yy=G+kuj;BDdd0PH9%Y()n7cV5YaW6_}76k~!5 zl4^c8iC#WJr!+?`5NOv(W!W1#8%V8d^logr^74vR0x?QBsTD@1hX24-E6fZLV((sF zilG}uvqw?<)qP#!8MCH@3)1swA@1Dvv5MOcq1-|=>a4Qu&r-{LUMi&DoU4K(;4#y@ z#ex7K9(i&5l^6*wyv~REaeT2*=Q<80(vaI%+3<}G5bt~T)QV+{Oddx%ipo5CP|X$P z=T==&?WOKcMeSfKtS>3fKD`dYp)wvTRT}zjm<|%;{v%i~3@W$22>X zA#m+4D)e0q9?V*i<{6ZCcWR}CH!RScHGqMN`Erx~G%$bn1imx_ zjZ$5I}DP+SF)iBf<+S-R|t(Qe6+wG{08uAnCKMQ0V0R{ zwELngW}{X*YmQPV29dj)IGZjs)>NLJtgSJ?AlMS9Pdi6-INwr17%Df+w#gRgZn|ZJ z+Du}!5q{fmCOD7~Qj9OYy<zM1V6=t2LEs0TQRO8c1FVx!` z)enht^SLu|BKa1qoXFlZG@-W*J0L(7owG*7yE8vTO{(Pg&iOBkd%SbMQ*gLWdW%#- zz0_r>gK{ZQ@W_Ti)%Vj}xRM|}j$W>j|1Mi!5^t*oD1X>$6J4^v`{CzzsT2;g^zkeY z2kz`f^M2b3&a$S+Na|;v_b>s&EjSK^dp6N zImZ%eDz3LY+ewcL@Up_uyo;hAK$bu!2Rr!z1?TlN)8YLc+LuOONA(2wiMIxN9oUJN{A z?Fdus&IdnyMnFwy7*!nXg$-g)_z`rmHWzsxhX0sB7cnY9*YEulOO@u}FeYqPD-iLYV} zE7B4N7|5f4b+#UQApfCzA62gfVTX@#BqIi=Iq8tIPw^5?nhb+LIx;1CVv0UQlEi+U3omj3-I_Oq#0 zthL@v16WI>H2-KN+}T=vH&bwSGDEDiFX%KjS_RQEq~N2c#QM?)X2*6tt-_@7{;cQq zkEsQi#c$S^BnSH`(iR%Asg8BMH0Q*~=Ww@jleC~AgP1XWQjuaR{#2cdTkmsCsG*HV zEqavnnc7JK@|$8(Yz#hzQq8=)HN&_V-`O-Z{l_Ra9sPUlDvKitELQIJg|t;FtO>ke9xlt1}IlC$}aB6RpdIawpCz8kyalzY7OfywlD6U|RsX$oT$H-bD!RQ`l z*gMLC=nhxklG85Y3dt2)F-ng+uI4rs;5QsmlMn02kT1d8*muQ0b+*(kQ-^CRN;W7P zOt!ZOtS|8Bo7a3Rl??eLXsseAJsAE`r$bq;Q(1<|yW;L!pvBJ6%Up0S&8=Ii+c9+hl82r=*vD8q%2x6aO+ha~i@173UfKE9? z=l)I3x1wH&9lb9D$ZW5`UhA@=HxnDELv3|dMX(Md(I(>-!ZpjqR^yPcx&2}VZA1*C ziGmxg1Lsf)9D?)ig>e2$B6Ed)S8a7r@@|kfl=pnM_%OCG(7&JGM8N%Bu^l+|{QsfW z&Zu-rt^F5`_A6I0V1ZbX*RR8%1N(gd>px=VK-cj7LWSA--*03@lm+M{WJQ5fyT2wo z+afeLHH^z@tz%$49d?EQyG8q9`2~iOxWqKLWpAk@@h=F15`*lv72>kn82lh`X zfaTIpDH^}0_^!hKr-ZkEq=Px9TKhHOcd7hK%w~Q@CfUHBP5?LAKLF>Y#RDc@KWWzf z0QeF3=7%aZbdLJmazrqJ0p1oU`FZ32xN>|?{{s+uItNVbT-^km9L)f+P;FVD@dz0indkbU=7kEn9y_*73PZI!U^dEr0Gsm|b^S7A5sVzr{ zmDTUj#9raGw*uvlyHvF^px>ei-oNj79z?+QJgzHXhP((J09|+!t+|f^K(#&x0>z%I zs{goheBT1!?QaVIz12iqjSZdt(OHH@g$_S^fojeATU4>%2cw0?g^o0KfjfKmx46GF z)xX6ZgJyw_V|Br@%>P@KKYtj|Q8+H(9K`?W;lKA2zwPCJ&fmF526P;a3&5)q{~lEX z8s$6{(Bb^=IuBa$?KR+JJ0ufT6N_-jh4;uT>`G*!UzhI(N_zR|=J!pV@ z*#0bO4owBEAbmlF2@J*mUZ{W3lZJ+e)Fk zwEwCuXi>Whl5+jOAo;Vz9dwDHRlqLDwhaG7_Vb1+G$yn*&IKme{7;zQ8{`}GxBvXK zKLyPKt-^A_LTP!4<$q|GHCdoBp--q^VCval#{B#9>d-vUr=~A>SR60$T>i}e>I^kB zC-kY;3(hs?|K|LCcLnWkdV$&c=)W;Rmz__cGY#$8cR^4a@)ra@_fo$v0klii1wlsm zC4wKL#NQYup-Teov2a0D7;}l}((C%C&kcGP_yV~s?h^9lm+2ey@ArhE3jw|Pc0rW` zEP(#KC;yMJ6naDH0+urQPq5!Rj6ZBIK^Fkp?tH;yk#>m*dW!y2-Tg;_plzWSG<+GC zXnunIUZ8J}KlFXjhOrC$sI0%h|93MPbbUcD_AiLY^ZuC_{@c=DUJ4FyOgLX^(ZSRJ M^S3-82@K5t0qXi&I{*Lx literal 0 HcmV?d00001 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..cf8c27fe --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sun Dec 02 15:14:31 PST 2012 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.3-bin.zip diff --git a/gradlew b/gradlew new file mode 100755 index 00000000..91a7e269 --- /dev/null +++ b/gradlew @@ -0,0 +1,164 @@ +#!/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" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 00000000..aec99730 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,90 @@ +@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 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% + +: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/settings.gradle b/settings.gradle new file mode 100644 index 00000000..8e81369a --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'gradle-versions-plugin' diff --git a/src/main/groovy/com/github/benmanes/gradle/versions/DependencyUpdates.groovy b/src/main/groovy/com/github/benmanes/gradle/versions/DependencyUpdates.groovy new file mode 100644 index 00000000..ce04a6dd --- /dev/null +++ b/src/main/groovy/com/github/benmanes/gradle/versions/DependencyUpdates.groovy @@ -0,0 +1,166 @@ +/* + * Copyright 2012 Ben Manes. All Rights Reserved. + * + * 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.github.benmanes.gradle.versions + +import org.gradle.api.DefaultTask +import org.gradle.api.Project +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.ExternalDependency +import org.gradle.api.internal.artifacts.version.LatestVersionSemanticComparator +import org.gradle.api.tasks.Input +import org.gradle.api.tasks.TaskAction + +/** + * A task that reports which dependencies have newer versions. + *

+ * The revision property controls the resolution strategy: + *

    + *
  • release: selects the latest release + *
  • milestone: select the latest version being either a milestone or a release (default) + *
  • integration: selects the latest revision of the dependency module (such as SNAPSHOT) + *
+ * + * @author Ben Manes (ben.manes@gmail.com) + */ +class DependencyUpdates extends DefaultTask { + + @Input + String revision = 'milestone' + + @TaskAction + def dependencyUpdates() { + def current = getProjectAndBuildscriptDependencies() + def (resolved, unresolved) = resolveLatestDepedencies(current) + def (currentVersions, latestVersions, sameVersions, downgradeVersions, upgradeVersions) = + getVersionMapping(current, resolved) + displayReport(currentVersions, latestVersions, sameVersions, + downgradeVersions, upgradeVersions, unresolved) + } + + /** Returns {@link ExternalDependency} collected from the project and buildscript. */ + def getProjectAndBuildscriptDependencies() { + project.allprojects.collectMany{ proj -> + def configurations = (proj.configurations + proj.buildscript.configurations) + configurations.collectMany { it.allDependencies } + }.findAll { it instanceof ExternalDependency } + } + + /** + * Returns {@link ResolvedDependency} and {@link UnresolvedDependency} collected after evaluating + * the latest dependencies to determine the newest versions. + */ + def resolveLatestDepedencies(current) { + if (current.empty) { + return [[], []] + } + def unresolved = current.collect { dependency -> + project.dependencies.create(group: dependency.group, name: dependency.name, + version: "latest.${revisionLevel()}") { + transitive = false + } + } + def lenient = project.configurations.detachedConfiguration(unresolved as Dependency[]) + .resolvedConfiguration.lenientConfiguration + [lenient.firstLevelModuleDependencies, lenient.unresolvedModuleDependencies] + } + + /** Organizes the dependencies into version mappings. */ + def getVersionMapping(current, resolved) { + def currentVersions = current.collectEntries { dependency -> + [label(dependency), dependency.version] + } + def latestVersions = resolved.collectEntries { dependency -> + [label(dependency.module.id), dependency.moduleVersion] + } + def sameVersions = currentVersions.intersect(latestVersions) + + def comparator = new LatestVersionSemanticComparator() + def upgradeVersions = latestVersions.findAll { label, version -> + comparator.compare(version, currentVersions[label]) > 0 + } + def downgradeVersions = latestVersions.findAll { label, version -> + comparator.compare(version, currentVersions[label]) < 0 + } + [currentVersions, latestVersions, sameVersions, downgradeVersions, upgradeVersions] + } + + /** Returns the dependency's group and name. */ + def String label(dependency) { dependency.group + ':' + dependency.name } + + /** Returns the resolution revision level. */ + def revisionLevel() { System.properties.get('revision', revision) } + + /* ---------------- Display Report -------------- */ + + /** Prints the report to the console. */ + def displayReport(currentVersions, latestVersions, sameVersions, + downgradeVersions, upgradeVersions, unresolved) { + displayHeader() + displayUpToDate(sameVersions) + displayExceedLatestFound(currentVersions, downgradeVersions) + displayUpgrades(currentVersions, upgradeVersions) + displayUnresolved(unresolved) + } + + def displayHeader() { + println """ + |------------------------------------------------------------ + |${project.path} Project Dependency Updates + |------------------------------------------------------------""".stripMargin() + } + + def displayUpToDate(sameVersions) { + if (sameVersions.isEmpty()) { + println "\nAll dependencies have newer versions." + } else { + println "\nThe following dependencies are using the newest ${revisionLevel()} version:" + sameVersions.sort().each { println " - ${it.key}:${it.value}" } + } + } + + def displayExceedLatestFound(currentVersions, downgradeVersions) { + if (!downgradeVersions.isEmpty()) { + println("\nThe following dependencies exceed the version found at the " + + revisionLevel() + " revision level:") + downgradeVersions.sort().each { label, version -> + def currentVersion = currentVersions[label] + println " - ${label} [${currentVersion} <- ${version}]" + } + } + } + + def displayUpgrades(currentVersions, upgradeVersions) { + if (upgradeVersions.isEmpty()) { + println "\nAll dependencies are using the latest ${revisionLevel()} versions." + } else { + println("\nThe following dependencies have newer ${revisionLevel()} versions:") + upgradeVersions.sort().each { label, version -> + def currentVersion = currentVersions[label] + println " - ${label} [${currentVersion} -> ${version}]" + } + } + } + + def displayUnresolved(unresolved) { + if (!unresolved.isEmpty()) { + println("\nFailed to determine the latest version for the following dependencies:") + unresolved.sort { a, b -> label(a.selector) <=> label(b.selector) }.each { + println " - " + label(it.selector) + logger.info "The exception that is the cause of unresolved state:", it.problem + } + } + } +} diff --git a/src/main/groovy/com/github/benmanes/gradle/versions/VersionsPlugin.groovy b/src/main/groovy/com/github/benmanes/gradle/versions/VersionsPlugin.groovy new file mode 100644 index 00000000..483b8934 --- /dev/null +++ b/src/main/groovy/com/github/benmanes/gradle/versions/VersionsPlugin.groovy @@ -0,0 +1,34 @@ +/* + * Copyright 2012 Ben Manes. All Rights Reserved. + * + * 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.github.benmanes.gradle.versions + +import org.gradle.api.Plugin +import org.gradle.api.Project + +/** + * Registers the plugin's tasks. + * + * @author Ben Manes (ben.manes@gmail.com) + */ +public class VersionsPlugin implements Plugin { + + @Override + public void apply(Project project) { + def task = project.tasks.add("dependencyUpdates", DependencyUpdates) + task.description = "Displays the dependency updates for the project." + task.group = "Help" + } +} diff --git a/src/main/resources/META-INF/gradle-plugins/versions.properties b/src/main/resources/META-INF/gradle-plugins/versions.properties new file mode 100644 index 00000000..74bc0014 --- /dev/null +++ b/src/main/resources/META-INF/gradle-plugins/versions.properties @@ -0,0 +1 @@ +implementation-class=com.github.benmanes.gradle.versions.VersionsPlugin