From be7dd129b6e85d8da4543c01a4f7b4097c188594 Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Fri, 4 Oct 2019 23:32:13 +0300 Subject: [PATCH 01/32] CI: add configuration for Cirrus --- .cirrus.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000..9d288c1 --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,40 @@ +container: + image: cirrusci/android-sdk:28 + cpu: 4 + memory: 8G + +task: + name: Run tests + script: ./gradlew test + +task: + name: Build release apk + + depends_on: + - Run tests + +# environment: +# KEYSTORE: +# KEYSTORE_PASSWORD: + + build_release_apk_script: | + ./gradlew assembleRelease + + build_apksigner_script: | + cd ../ + git clone https://github.com/fornwall/apksigner + cd apksigner + ./gradlew + cp ./build/libs/apksigner-all.jar /tmp/apksigner.jar + + sign_release_apk_script: | + echo "$KEYSTORE" | base64 -d > keystore.jks + java -jar /tmp/apksigner.jar -p "$KEYSTORE_PASSWORD" keystore.jks \ + ./app/build/outputs/apk/release/app-release-unsigned.apk \ + ./termux-boot-release-g${CIRRUS_CHANGE_IN_REPO:0:8}.apk + + release_artifacts: + path: "./*.apk" + + unsigned_artifacts: + path: "./app/build/outputs/apk/release/*.apk" From 1e7c13c02145e7b85ebef6f870e41a115bd65d21 Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Sat, 5 Oct 2019 00:26:55 +0300 Subject: [PATCH 02/32] CI: add sample keystore --- .cirrus.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index 9d288c1..f05bddd 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -13,9 +13,9 @@ task: depends_on: - Run tests -# environment: -# KEYSTORE: -# KEYSTORE_PASSWORD: + environment: + KEYSTORE: ENCRYPTED[6510e0b810884250a3756992cf19030ea21c99c24c2014c68cafa699a19b0bd3f9607ae7241220b02c8c3ee90f3622bc] + KEYSTORE_PASSWORD: ENCRYPTED[43942d98f49a1675da29b88d74ee60666f81945f2168126023e7896d137b0a21c4540a0d96fab8f0ca03428e5270642d] build_release_apk_script: | ./gradlew assembleRelease From 80637080a8b17d8fde030c4110e4b7c821547f5a Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Sat, 5 Oct 2019 00:27:10 +0300 Subject: [PATCH 03/32] update readme --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 196bf91..0676f1e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ -Termux:Boot -=========== +# Termux:Boot + +[![Build status](https://api.cirrus-ci.com/github/termux/termux-boot.svg?branch=master)](https://cirrus-ci.com/termux/termux-boot) [![Join the chat at https://gitter.im/termux/termux](https://badges.gitter.im/termux/termux.svg)](https://gitter.im/termux/termux) A [Termux](https://termux.com) add-on app to run programs at boot. @@ -7,14 +8,15 @@ A [Termux](https://termux.com) add-on app to run programs at boot. - [Termux:Boot on Google Play](https://play.google.com/store/apps/details?id=com.termux.boot) - [Termux:Boot on F-Droid](https://f-droid.org/packages/com.termux.boot) -When developing (or packaging), note that this app needs to be signed with the same key as the main Termux app in order to have the permission to execute scripts. +When developing (or packaging), note that this app needs to be signed with the +same key as the main Termux app in order to have the permission to execute scripts. + +## License -License -======= Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). -How to use -========== +## How to use + 1. Install the Termux:Boot app. 2. Start the Termux:Boot app once by clicking on its launcher icon. This allows the app to be run at boot. 3. Create the `~/.termux/boot/` directory. From 103bce158b3dbbdcafb7055ead2a619b01cc22d3 Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Sat, 5 Oct 2019 00:55:08 +0300 Subject: [PATCH 04/32] CI: remove tests task Application doesn't have tests. --- .cirrus.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index f05bddd..fefb7e0 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,16 +3,9 @@ container: cpu: 4 memory: 8G -task: - name: Run tests - script: ./gradlew test - task: name: Build release apk - depends_on: - - Run tests - environment: KEYSTORE: ENCRYPTED[6510e0b810884250a3756992cf19030ea21c99c24c2014c68cafa699a19b0bd3f9607ae7241220b02c8c3ee90f3622bc] KEYSTORE_PASSWORD: ENCRYPTED[43942d98f49a1675da29b88d74ee60666f81945f2168126023e7896d137b0a21c4540a0d96fab8f0ca03428e5270642d] From 354f00901e2d7f67835bb69b5f5e328698b5709c Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Mon, 7 Oct 2019 14:44:03 +0300 Subject: [PATCH 05/32] CI: development builds are now signed with publically-shared key This commit adds keystore which is shared with community. People freely can use it for creating own Termux app and plugin builds. However, builds signed with such keystore cannot be proven as official. Signed-off-by: Leonid Plyushch --- .cirrus.yml | 32 ++++++-------------------------- app/build.gradle | 11 +++++++++++ app/dev_keystore.jks | Bin 0 -> 2097 bytes 3 files changed, 17 insertions(+), 26 deletions(-) create mode 100644 app/dev_keystore.jks diff --git a/.cirrus.yml b/.cirrus.yml index fefb7e0..4285ac2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,33 +1,13 @@ container: image: cirrusci/android-sdk:28 - cpu: 4 + cpu: 1 memory: 8G task: - name: Build release apk + name: debug-build - environment: - KEYSTORE: ENCRYPTED[6510e0b810884250a3756992cf19030ea21c99c24c2014c68cafa699a19b0bd3f9607ae7241220b02c8c3ee90f3622bc] - KEYSTORE_PASSWORD: ENCRYPTED[43942d98f49a1675da29b88d74ee60666f81945f2168126023e7896d137b0a21c4540a0d96fab8f0ca03428e5270642d] + script: | + ./gradlew assembleDebug - build_release_apk_script: | - ./gradlew assembleRelease - - build_apksigner_script: | - cd ../ - git clone https://github.com/fornwall/apksigner - cd apksigner - ./gradlew - cp ./build/libs/apksigner-all.jar /tmp/apksigner.jar - - sign_release_apk_script: | - echo "$KEYSTORE" | base64 -d > keystore.jks - java -jar /tmp/apksigner.jar -p "$KEYSTORE_PASSWORD" keystore.jks \ - ./app/build/outputs/apk/release/app-release-unsigned.apk \ - ./termux-boot-release-g${CIRRUS_CHANGE_IN_REPO:0:8}.apk - - release_artifacts: - path: "./*.apk" - - unsigned_artifacts: - path: "./app/build/outputs/apk/release/*.apk" + output_artifacts: + path: "./app/build/outputs/apk/debug/*.apk" diff --git a/app/build.gradle b/app/build.gradle index 9fb689e..8e6db7e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,13 +12,24 @@ android { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } + signingConfigs { + debug { + storeFile file('dev_keystore.jks') + keyAlias 'alias' + storePassword 'xrj45yWGLbsO7W0v' + keyPassword 'xrj45yWGLbsO7W0v' + } + } + buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } + debug { + signingConfig signingConfigs.debug zipAlignEnabled true } } diff --git a/app/dev_keystore.jks b/app/dev_keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..174cc95acd605bf557f9e63983f55fadc5ae44bd GIT binary patch literal 2097 zcmbW1dpOgJAIJCIMROk`WY(HSNXCZ42syb#xvfbXBITaTl-rTawPUPoP84wxvzSX) z*WsklYK7d&_2d##Bndwpzsq@^^Y`zM_aCq4^E{vDb9tWE*22~T2m}J}1o%&2J|TfV z^c@OikDxq3AQ*sWKsWI+ViG!H02I&$%K-ok1Z6;H@f7nw;XKE~r-Rc}UysG8b8`+3 zaKmS-jr5o{SCP8uu-J*^GyFYRWhu#0 z>t<$WClxHdNaB(zFReHwKYsVzqu=L%i!WGRZZ$pf#Yu6ZsC9QL5?Q;;{^9wK<&0DX zmNu_>81-1Q>Z#=y4=1WFfT+3S>UR4SO7BkZT+dH`z?dc%PuSvpeuPv6|!-(VL zQ^%PiH=6;~;fxshnQJ)l$%_Sy6P#FyTqWbyP>t=M_}R}SXYn_xQIwBH^PG6a-0GB2 zL?60;HtO2fX;T;X(87|~0+Xc%yo$kU>6XS*3{4#~(zS>~Z$$XTsXmgoP0Tx#P5nXG z*U>26+8Y5;Nd9qR!q^9%=&_|A`=*=kp6)-zCn201>!oE?Hv{DYR75qdA|-EAcLzkQ0^ z4L@?sdV*7{T#(@@M(@%cCuOf!pT8Z?9D<$ZY8ocpxYjs1q(l0QB)yp9kSA+FoYLTSkVls8Uw{^G@haj;DuNC7}h_X;^R+~$L zV-@=2`u7B2Z~CVY9^3TQ7hT)aN4*vvmDgIcSs|pKEoP&vvn&|L=w#$b1MX_?HqE$c zpW{q|bEe=un!~bliG4?rX}5khF5bBwmiCQ960)*8UBp7iU8(g03D}xKue`e}ieXW% zjm8+l`Vf^@7j}Ho$!=_%QCvTi-g^$wmc03kgLYD`npCbNwlffW*2AI8sc}_DXwCHr z-@8;~J52g?$t9uGoUAWxq&pEXaBY;HLgpE&A*Spt%{x22X}df;g)Deq>z#p0EB67j zW?-LWLJxxJ`jci9G$!c>eZd*6R15bVuqxH*&-4A|R^65U#O)S6cn{Um9v-PTj?;VH z9MZr4yLF35(5bW+{^2tD0FS<$WaUn^#8=aPC@l1Fjxd=$6VdRd0!O3adhgf{_4VW} z%dYR=5@`1;>H~_~1hS8{wqnH$C!95bZcbcYm#le-#h?H6;;BQ1c#|Dd&fyv0X*>fE z6+^%P7!1`CXvO2D#l*GK?9x`HcjO2I;SKd=@KR!slTZmM*ioOzsDQs&@^41s<^ElV zNJ&^ZJ7C-b{V$x0#G{p@^-b_5c!B|8C&bfA(nJ$|yn*5W@c(Vg0I>fYa7W(|1|SRC z*+Bx#007Xh&mlofl_28n{OOYvrmei(5x-+yIrQpFpKOC|9hel40EfK3H?pz+bGf3Q(Mm1cQ|0SMc{5q|O$1xYI6K~wZbHQ@LY(AB9xR1p zx{#m))|5T&e2aFropN%LDHU-uG^2A9Hrt7$z z$&)?RR2OfPY?S=Y=~L0zh$PV}&9$UxQHh-tOW-=1bQsdgTp~e>6!Gq)xi*X8w#=U?cKT z8*?>+z+Zj0>2M8GE4X=J=Byb-5UB%N{6dp0RQXbp<3u4JlnE5@$Y43o# z_bJkeeSx@OVPD8{OyQ(G!Ef=G0Ir^B^L7S_e^tXet#;c#NCUT@4=iL}$h0=yR-Y~c hj~#VhH9HJD9eBKXgx6a9(6#$et0J;JPJugM`WN=>nzsM| literal 0 HcmV?d00001 From afa7fa6e6dff2cd83921c57f4cc6b01e3c4bcb43 Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Mon, 7 Oct 2019 15:20:01 +0300 Subject: [PATCH 06/32] update readme --- README.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0676f1e..0fb1e3c 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,25 @@ A [Termux](https://termux.com) add-on app to run programs at boot. -- [Termux:Boot on Google Play](https://play.google.com/store/apps/details?id=com.termux.boot) -- [Termux:Boot on F-Droid](https://f-droid.org/packages/com.termux.boot) - When developing (or packaging), note that this app needs to be signed with the same key as the main Termux app in order to have the permission to execute scripts. +## Installation + +Termux:Boot application can be obtained from: + +- [Google Play](https://play.google.com/store/apps/details?id=com.termux.boot) +- [F-Droid](https://f-droid.org/en/packages/com.termux.boot/) +- [Kali Nethunter Store](https://store.nethunter.com/en/packages/com.termux.boot/) + +Additionally we offer development builds for those who want to try out latest +features ready to be included in future versions. Such build can be obtained +directly from [Cirrus CI artifacts](https://api.cirrus-ci.com/v1/artifact/github/termux/termux-boot/debug-build/output/app/build/outputs/apk/debug/app-debug.apk). + +Signature keys of all offered builds are different. Before you switch the +installation source, you will have to uninstall the Termux application and +all currently installed plugins. + ## License Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). From 7fb45001a963c8e8c709ea501901963b313c159e Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Mon, 7 Oct 2019 15:23:25 +0300 Subject: [PATCH 07/32] readme: fix section order --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0fb1e3c..d668eff 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,6 @@ Signature keys of all offered builds are different. Before you switch the installation source, you will have to uninstall the Termux application and all currently installed plugins. -## License - -Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). - ## How to use 1. Install the Termux:Boot app. @@ -43,3 +39,7 @@ Example: To start an sshd server and prevent the device from sleeping at boot, c termux-wake-lock sshd ``` + +## License + +Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). From 29e53e3d95b5e263ee983158622c2bbf98f08078 Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Fri, 7 Feb 2020 14:22:07 +0200 Subject: [PATCH 08/32] CI: switch to Github Actions --- .cirrus.yml | 13 ------------- .github/workflows/debug_build.yml | 18 ++++++++++++++++++ README.md | 2 +- 3 files changed, 19 insertions(+), 14 deletions(-) delete mode 100644 .cirrus.yml create mode 100644 .github/workflows/debug_build.yml diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 4285ac2..0000000 --- a/.cirrus.yml +++ /dev/null @@ -1,13 +0,0 @@ -container: - image: cirrusci/android-sdk:28 - cpu: 1 - memory: 8G - -task: - name: debug-build - - script: | - ./gradlew assembleDebug - - output_artifacts: - path: "./app/build/outputs/apk/debug/*.apk" diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml new file mode 100644 index 0000000..d6c8dc4 --- /dev/null +++ b/.github/workflows/debug_build.yml @@ -0,0 +1,18 @@ +name: Build + +on: push + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Clone repository + uses: actions/checkout@v2 + - name: Build + run: | + ./gradlew assembleDebug + - name: Store generated APK file + uses: actions/upload-artifact@v1 + with: + name: termux-boot + path: ./app/build/outputs/apk/debug/app-debug.apk diff --git a/README.md b/README.md index d668eff..e1485f4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Termux:Boot -[![Build status](https://api.cirrus-ci.com/github/termux/termux-boot.svg?branch=master)](https://cirrus-ci.com/termux/termux-boot) +[![Build status](https://github.com/termux/termux-boot/workflows/Build/badge.svg)](https://github.com/termux/termux-boot/actions) [![Join the chat at https://gitter.im/termux/termux](https://badges.gitter.im/termux/termux.svg)](https://gitter.im/termux/termux) A [Termux](https://termux.com) add-on app to run programs at boot. From b63afd76515eff0b2e5de18af3bc13b0f63fee6d Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Fri, 7 Feb 2020 15:17:28 +0200 Subject: [PATCH 09/32] update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 28 +++++++++++++++++------ .github/ISSUE_TEMPLATE/feature_request.md | 17 ++++++++++++++ 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3894b4c..ad9f3be 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,21 +1,35 @@ --- name: Bug report -about: Create a report to help us improve termux-boot +about: Create a report to help us improve Termux:Boot application --- - + **Problem description** -A clear and concise description of what the problem with termux-boot is. You may post screenshots in addition to description. + **Steps to reproduce** -What does your termux-boot script contain? -Please post the full script here. + **Expected behavior** + **Additional information** -Post output of command `termux-info`. -If you are rooted or have access to adb then capture a logcat with `logcat -d "*:W"`, from a adb or root shell. + +* Termux application version: +* Android OS version: +* Device model: diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..61292e1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest a new feature for Termux:Boot application + +--- + + + +**Feature description** + From ad4038275b41943b1293b2ae2105e47c65ce69bc Mon Sep 17 00:00:00 2001 From: Leonid Plyushch Date: Fri, 7 Feb 2020 15:51:52 +0200 Subject: [PATCH 10/32] update readme --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e1485f4..170cb6d 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,10 @@ Termux:Boot application can be obtained from: - [F-Droid](https://f-droid.org/en/packages/com.termux.boot/) - [Kali Nethunter Store](https://store.nethunter.com/en/packages/com.termux.boot/) -Additionally we offer development builds for those who want to try out latest -features ready to be included in future versions. Such build can be obtained -directly from [Cirrus CI artifacts](https://api.cirrus-ci.com/v1/artifact/github/termux/termux-boot/debug-build/output/app/build/outputs/apk/debug/app-debug.apk). +Additionally we provide per-commit debug builds for those who want to try +out the latest features or test their pull request. This build can be obtained +from one of the workflow runs listed on [Github Actions](https://github.com/termux/termux-boot/actions) +page. Signature keys of all offered builds are different. Before you switch the installation source, you will have to uninstall the Termux application and From 3206ef2d159d3c61aa631d9e6d1feadda1ecd225 Mon Sep 17 00:00:00 2001 From: Leonid Pliushch Date: Wed, 3 Feb 2021 03:04:29 +0200 Subject: [PATCH 11/32] readme: remove links to Google Play and Nethunter stores Both offer outdated builds. --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 170cb6d..56bdbae 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,7 @@ same key as the main Termux app in order to have the permission to execute scrip ## Installation -Termux:Boot application can be obtained from: - -- [Google Play](https://play.google.com/store/apps/details?id=com.termux.boot) -- [F-Droid](https://f-droid.org/en/packages/com.termux.boot/) -- [Kali Nethunter Store](https://store.nethunter.com/en/packages/com.termux.boot/) +Termux:Boot application can be obtained from [F-Droid](https://f-droid.org/en/packages/com.termux.boot/). Additionally we provide per-commit debug builds for those who want to try out the latest features or test their pull request. This build can be obtained From 761c1fcb772bc9c37c703c16975fbb3514bf9722 Mon Sep 17 00:00:00 2001 From: agnostic-apollo <31106828+agnostic-apollo@users.noreply.github.com> Date: Fri, 2 Jul 2021 09:31:59 +0500 Subject: [PATCH 12/32] Update debug_build.yml --- .github/workflows/debug_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml index d6c8dc4..16e3719 100644 --- a/.github/workflows/debug_build.yml +++ b/.github/workflows/debug_build.yml @@ -12,7 +12,7 @@ jobs: run: | ./gradlew assembleDebug - name: Store generated APK file - uses: actions/upload-artifact@v1 + uses: actions/upload-artifact@v2 with: name: termux-boot path: ./app/build/outputs/apk/debug/app-debug.apk From 1ac4cf96ad79ad7caf25e9039548585ddc1096e3 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Wed, 30 Mar 2022 20:28:59 +0200 Subject: [PATCH 13/32] Remove notice about Google+ from termux-boot info page And use termux.org instead of termux.com in community url. --- app/src/main/assets/overview.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/assets/overview.html b/app/src/main/assets/overview.html index 0383e88..6f6bb3e 100644 --- a/app/src/main/assets/overview.html +++ b/app/src/main/assets/overview.html @@ -19,7 +19,7 @@

Example

Learn more

-

Join the Termux Google+ community at https://termux.com/community +

Join the Termux community through the various channels listed at https://termux.org/community

Report issues

https://github.com/termux/termux-boot/issues From 29a116f062d43eeecd0c17e14daca7e8275dc561 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Sun, 3 Jul 2022 19:12:08 +0200 Subject: [PATCH 14/32] README: change termux url termux.com->termux.dev --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 56bdbae..d218db9 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Build status](https://github.com/termux/termux-boot/workflows/Build/badge.svg)](https://github.com/termux/termux-boot/actions) [![Join the chat at https://gitter.im/termux/termux](https://badges.gitter.im/termux/termux.svg)](https://gitter.im/termux/termux) -A [Termux](https://termux.com) add-on app to run programs at boot. +A [Termux](https://termux.dev) add-on app to run programs at boot. When developing (or packaging), note that this app needs to be signed with the same key as the main Termux app in order to have the permission to execute scripts. From db789ee9a2279f01ed3b59b0b222f7fa0f79a084 Mon Sep 17 00:00:00 2001 From: Leonid Pliushch Date: Wed, 21 Sep 2022 10:30:24 +0300 Subject: [PATCH 15/32] rename dev_keystore.jks to testkey_untrusted.jks Hopefully the new name of keystore file would provide to potential user more info about what it actually is. --- app/build.gradle | 2 +- app/{dev_keystore.jks => testkey_untrusted.jks} | Bin 2 files changed, 1 insertion(+), 1 deletion(-) rename app/{dev_keystore.jks => testkey_untrusted.jks} (100%) diff --git a/app/build.gradle b/app/build.gradle index 8e6db7e..1a69a44 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,7 +14,7 @@ android { signingConfigs { debug { - storeFile file('dev_keystore.jks') + storeFile file('testkey_untrusted.jks') keyAlias 'alias' storePassword 'xrj45yWGLbsO7W0v' keyPassword 'xrj45yWGLbsO7W0v' diff --git a/app/dev_keystore.jks b/app/testkey_untrusted.jks similarity index 100% rename from app/dev_keystore.jks rename to app/testkey_untrusted.jks From 54e1311c134d9bfdd490715918be94d83755c630 Mon Sep 17 00:00:00 2001 From: Lucy Phipps Date: Mon, 7 Nov 2022 01:17:52 +0000 Subject: [PATCH 16/32] Create dependabot.yml --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..a83ef38 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: +- package-ecosystem: github-actions + directory: / + schedule: + interval: daily From a81907cc6f61c811f28298dda41faf3dd396b26e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Nov 2022 01:18:14 +0000 Subject: [PATCH 17/32] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/debug_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml index 16e3719..5e33753 100644 --- a/.github/workflows/debug_build.yml +++ b/.github/workflows/debug_build.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Build run: | ./gradlew assembleDebug From 8c4c16913dd680b0f34f975815cec4c5abbcba60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Nov 2022 01:18:16 +0000 Subject: [PATCH 18/32] Bump actions/upload-artifact from 2 to 3 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/debug_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml index 16e3719..7d856cc 100644 --- a/.github/workflows/debug_build.yml +++ b/.github/workflows/debug_build.yml @@ -12,7 +12,7 @@ jobs: run: | ./gradlew assembleDebug - name: Store generated APK file - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: termux-boot path: ./app/build/outputs/apk/debug/app-debug.apk From 8c1c6b18c53f1f120290bb1243f98060d2bd0843 Mon Sep 17 00:00:00 2001 From: Henrik Grimler Date: Sat, 11 Mar 2023 12:06:13 +0100 Subject: [PATCH 19/32] README: add example for how to start termux-services on boot Similar to example found in termux-boot wiki page: https://wiki.termux.com/wiki/Termux:Boot --- README.md | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d218db9..c2974d8 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,10 @@ all currently installed plugins. 4. Put scripts you want to execute inside the `~/.termux/boot/` directory. If there are multiple files, they will be executed in a sorted order. 5. Note that you may want to run `termux-wake-lock` as first thing if you want to ensure that the device is prevented from sleeping. -Example: To start an sshd server and prevent the device from sleeping at boot, create the following file at `~/.termux/boot/start-sshd`: +### Examples + +To start an sshd server and prevent the device from sleeping at boot, +create the following file at `~/.termux/boot/start-sshd`: ```sh #!/data/data/com.termux/files/usr/bin/sh @@ -37,6 +40,17 @@ termux-wake-lock sshd ``` +To start +[termux-services](https://wiki.termux.com/wiki/Termux-services), which +in turn starts enabled services, you can put the following in +`~/.termux/boot/start-services`: + +```sh +#!/data/data/com.termux/files/usr/bin/sh +termux-wake-lock +source /data/data/com.termux/files/usr/etc/profile.d/start-services.sh +``` + ## License Released under [the GPLv3 license](https://www.gnu.org/licenses/gpl.html). From dba8cc852f85480ef72e09ea704db5e10e4dbeec Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Tue, 27 Jun 2023 13:57:20 +0500 Subject: [PATCH 20/32] Changed: Update README.md to add termux-app installation docs link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c2974d8..9963f97 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ page. Signature keys of all offered builds are different. Before you switch the installation source, you will have to uninstall the Termux application and -all currently installed plugins. +all currently installed plugins. Check https://github.com/termux/termux-app#Installation for more info. ## How to use From 925e20c905fe9f73fc86ac8b5ed7ff6ab589ee3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:45:50 +0000 Subject: [PATCH 21/32] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/debug_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml index ef15998..90ae830 100644 --- a/.github/workflows/debug_build.yml +++ b/.github/workflows/debug_build.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Clone repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Build run: | ./gradlew assembleDebug From 8cda78a775fe4b790ab6c08fd9bb33e3b00b94b2 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Tue, 17 Oct 2023 02:23:47 +0200 Subject: [PATCH 22/32] Update gradle --- app/build.gradle | 6 +- app/src/main/AndroidManifest.xml | 1 - build.gradle | 10 +- gradle.properties | 2 + gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 4 +- gradlew | 285 ++++++++++++++--------- gradlew.bat | 38 ++- 8 files changed, 199 insertions(+), 147 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 1a69a44..5b2e2f1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,12 +1,13 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 28 + namespace "com.termux.boot" defaultConfig { applicationId "com.termux.boot" minSdkVersion 21 targetSdkVersion 28 + compileSdk 34 versionCode 7 versionName "0.7" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" @@ -30,7 +31,6 @@ android { debug { signingConfig signingConfigs.debug - zipAlignEnabled true } } @@ -41,7 +41,7 @@ android { } dependencies { - implementation "androidx.annotation:annotation:1.0.1" + implementation "androidx.annotation:annotation:1.7.0" } task versionName { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9a1924d..73422a6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ diff --git a/build.gradle b/build.gradle index 64b31c5..53213c3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,21 +1,17 @@ buildscript { repositories { - jcenter() + mavenCentral() google() } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:8.1.2' } } allprojects { repositories { - jcenter() + mavenCentral() google() } } - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/gradle.properties b/gradle.properties index 919f4b6..6f28211 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,3 +16,5 @@ org.gradle.jvmargs=-Xmx1536m # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true + +android.useAndroidX=true diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch delta 45054 zcmZ6yQZ&`nqh}wr$(C)n%K#duE=!&-~{m-z*HK?e*&L&sjPLy#k+CM^di>Rv_B zlbmNSQOjFe$zbNVE&#hO3UL;QaI^z&E&|(G75E@_zUC&s_;@r{JFVLT`i{?c|9-#v z&LIkV-TDD>L_NdkmmfNB7YmO>9X}X%bc+tisHsXig6jiH_fKH#UyjiIyOlxoOAc2& zV+h;c?zO?|RFo)@FYmm)-XPH14mrTvsx*%S_sS3DJey2EF*>@{7#vibAa@zkJl^i* z1$Rph<-2u4`hC#4H3mLas|P;S*!DqT1j-AQ8aqKfsJTwZc4#v1iO~s1C63o5P7)KQ z+6htpw~GLUD6f;>#gTCb-I1S;eUXrNPUw04l<0ir`zkcr_g3hfhphg->L`52V?!_k zl!Ahch<*8o$i59Q27^T~1WD-zsdUgkFugQsbro+sy#fO}RpI-*AW>Z(n>-{r z5{TlwpRw+*H!W?vh5v?;`q zTO|V+2Mhwl4oFKVco*Gl(!VbFW5Ji{PHA0b@;67qGw6LxoPx?$ic%*;c+HE+M1M8N zF5QG9w;8LpDMJXVpI&lf#kDkNMFi*KC5{p}I*yk+&&%dgkV@6Jq!W2_nBhi%aw~bk zZI+FXi!e)EV;!9mFD9@iOGrFzsv_%jj<*09?Zyu2mmICirY?z6t~pSfn@H>t5M|8L zyu^qP@e*q(V9)tX;7aY1-fX(>5HXD>M2iLGheMZA8RSqbGXtvm2~(PXh+XKgIiHCG zQuIyv@i$zscV}6HLN7VM_smevL_|hz%tZ%xW2t4s26LvXQw~Tpoqm?h+$J&AaTx$Y zk7HU8wWN*I>1q_TaHR57j7_gu*G~K?7fkY3>`M~`@>9JOO*t}8ummZwHg#;Q{zoGlj&}GWc+Visy5?Q~&`&aFI;P}T0 zT5?64T64uP!#nXQ3=pz^K?7FrFuzjthSUtBEA`6v9dLeP0g{kEDuxvr_v3(fq&Un@ zmy5gK_HoT6%Ho04rcxAt6Q@u?VhF~4)~QuEI2XO91=czNM^eD_f)$o|G96Z(8`76dw$VBSw^A_n>L&BFIUo>Z|k=DCBtAOy|eJ zj<9i(#kiyaA@b?!RF_FeWwK|%W)#9fc;REu$;j5aS=QUC@yR`7b*vC}a&+iZ#qB4N zngtOlhah6XYz;7LP1n=9*O{91ljsZi5$wkFODfeWqD2&gDC=ZNA#{L11+4;Qb5`7w z=4ie(%lFu%9X0~aF$4+)3ayMDl_e{=b}I(bhQVo;o@E!ux&A`VwO8{YqsZv93Jx2t z9Hzt<+sczSb$K~Tiqp-+Pz~$oZ19s=Kf~HpPlPKzmNJ!k8$?|9pDRrkc3x?T_QW0| zsH+T-sM(`I_r{_MOGZF_zf5%ZbMZCD1_8){F~-xt#fF8TouLpO13{EMX?weA?(8{> zk_=-D<}T%G*xxkV5RK0V;gp)m`d8eSbgP^z3lpZLR+lj|`sOf;bng;uC7AOBf^H(d zt(>Dx?2~Cv{0AO-%kx;E5l6l$N4$G!GX>4 z17p>5wEX#X?Rr_s#7%OBeS=uLmuALR6H=*k?cGlPxaj%Xn%dDcHh)ttThr$(=$ucZuTJtd_5mcKKYCA-6c+feuVg zfgkC1`Mkuv#4-Sn2`5FF7jzdWd1H}dzv#NE-4ZsNSo(v0H`$)nH)$$21!HTh zhv{2k5NYURJhObsGZ%g{6X9M?18-(61<00?u*H6>kLTZT$QX@d4DWeqxozr9(?1ha zfhxADCARC1=1K)pDj0uAlic#rq)Y5rKMCAe)B+ZZWq%6GMqS6`8Q-cO z$vC;!X5f<)2xxM@NrN?BuW3Bv#AP2%y^}R+?^fi(>R}!jC4VCdT}d#4Avkg(s%;yj zw5_$@PHn9@63%R`4bC|Tkhc?%6o>Q$_MOZerF*mmIj7r%fWjSE>9S)2gSKb(rEmq> zgo_#91El~m71m8qsiLa$emfARJ$xsXV_}6YUci2^+z}#tOwJWK=hG>obuV}`Ntp7$|507eq-f52qZV%7h3^ZAX0ZrS7 zYdzSo9Fbd($ZCLXGvu_lc)J-S;EU{u)yTW`Mo<`Qk=G%v44M|( zkCkAJP?t{YSrWNLCbZyhfLP@|(x=EpV!fx`w*}Z+6Raa?3L<>ClH%V0t)2px;;UW9 z>jv=XMy!N$iHGWP#CkjS%JYa%)*ZzrRQdwO%t!2J{urYN^-g?y)KZc9JhC)S-eZj) z+Qy3MU^p}^C)sMh{T=KV3z)&S#U2|OxhnL!!Z=;OkI6B6<;vlS>-z?#SXzZ+nAl&0 zYt{3j{3AiJ!1GJ+sy&ay9fD!XaLrDWBp_g?_p#kKznYsTpw;QBqt6TE`ZZr+c`mafdu+TXHpw;l3~MsMB|Ry7hIODoNN?;lQ)5N zdWAui+Bg#bcB*Us$Md2Uo;g#sAm!(xvbw5VSxPr4 zF2tN@%3o<+>6K^Hxwi4;04vk2Zk`6mz}imv%pOvp289usRTbGlR`*A0F?X@a*Z$BCLV5AOHL(vqFa}W%9QOj+E3)D|AuTnZ;RVj&RGt)* z-QEtv_u<@WrcgX7ER$wR>F2X04koGJi2L}E`b^D5z-*f>g~2t3)5bFLOhFOaj)ejj zpgqehiQQvqnnJBs9M?BkYOtMxc@5w?4MDWSi|a`rWE+ddZ1NnOKXGM;BaIc!wZYBo zt-()1%vn*@*BwO{vdu-=SQyYn_XMzu8N@)FQzE6PzpKw{BZ*`h-Q`(Vr>5J+9c?uh z;KfvAk~n=77HoUW7NREga}@F=HEES7Lcxtu$v|3DMd$04imA*NJF>TZq^H{c)Ci}s-}Zfrgx2XT%eg9&=eJ!L(x_-w6E_%a2# zGebid`;-}ZuBLIY?O>X;7XV%|lXmG{+hvcZK*uFMj1QnS%68H`rQ1PHHo7N2iBEzz z>2$Uj;?}6r9DYe!pS$W{(&p!vYuZc?y2e29E+CV+`B9cLLm8-gvnc6tcjsSbaGdjU zXu}s2HM(eyV8GiX*#wCkf#1Tviv}o}d}K_QiqW~YBXjY^_lWY>b+t2S{r4kDCHJSb zL#p3KXk>4OzhAVlzS|`q!8+^;EYvBbY8QNW=nqYB-S*6X-YdbDTz5CCIg0>dw<+XUK$ejy-L7BvbiD3ECDfcGVDuHr=_Qmd}BSCLVY^>rLx1U4CQSkWi-rEd;EvrWT~;kz`U z08ssu*>{vWB{rk|TtaFMdt?I#fM&3v>1Y)TB~TDW;xWhm$aH3|ypo-V++1zODZdOwYzi6BeC9A4 z>AfxQ#j>z>|` z`}~cW9}U8vX5}q%j;zQpri{t9Vqtntd<|@cGlQLU{fjlqAYq+CO@uL~M{<7l^vsyi zus&@(!7l$imM<1GptwF7;7>VED12(EuCINl5|u)Nt4TgMuMHPNM+rJgG#eZp)*Mtw z`U*N>A@&H1LNio5_xT$axPIQ%4%mfQQOZJUQBoibme`xQdP8yfkh6H2zp_AG6W@x0 zqymS&ae?eq?Eq6`SMNdTUd7xA($>cy)FuH=gC+)lxDCtJ3 ztRb#je!-Wg;^$j7yR0K0=$-8wI5YkCJ>-9K6i#Qt*Y`i7a7*g{EeTLZ`iZ6Iilsw2 zfIH9PUmpIcYX1$J2K0h(w^$Qb_ z=G`IXHXMV=(hdNDvSc5g&zG#N)YGKD_u?IMA!x`orrABYPDUKp>a6PaLt{+o5Zku5>_tkO~y1=1&EmaoN zq;{$-sc6?^YO`Out*lRIz<<|Tv%AttY-&`Aujm_V=Dnx`)P|66o6k?oTd|7OTqG>G zNWrpZytUeHDo${u2E9~NY;-Es&_7cZQ5>v~vCy5hM2%hIY2J=gA0En3FJ?L>(a(-CBFvf65~bPjV7%+a z4D@YUt~h4!BCau~IASjn`H_=PnASV!u`(Fxb@On~`-**F0h4i0?@os+oIj{V66U#r z7m@?uvQVl9EW>f`^|or6Zaei3d@E1t1iF?P(ap|eS^(0X@T}hn6%(V&bRuU=TCgV) zo#rmSCBMY9JeRRB_(e9kNb(nUAqN@IqiFxua6N&JyLEhtwmixIlEA0S{%TnweUx7_ zK^;>wUO%fMdHyUnRa<%zC(X<)8gr|Nd*wU&u-;tJj*JYTg2M-?v_{`CZ(m1Pnn_Oc z*b)naVgY~*mm#GVbf${AIjAp=^kRdX^_$c5YCVM03!7KR|84gL7EC!MOfrqiuMLyBj%- z;D75Y>p^r_@YK$3V1v+v5K0}{BEv0VT^!@u2n941YD=?(zB)FTJu^DO%~#)u(2Stk zB7$Z$5bpcL4h+LO68eh}(Z)#ine3wHeIOk8jhArQ1u-vb!H+EIZjl^N zqN1mODul-0M5tG;QvqIC2xW}ENdnuAr6RmcK_M5JnS3W;7sk_m#nGg5XmBrhcL+-% zfR*6}8@(Gw5 zs;Zm~cfa2JMr2(`>+HG74cFgJpH|gDAfVi@Q1-yt^g8Q|U+_3j}?5-uU~| zl(w!S1P7}@ZLFDfgE8d$B98zVS|x%?ng7PdsPkm~2$_yufU8B1j3X(sToV|0lf(rD*LLBtV$v<^$pT>tLlG;bpN>Q?ppPv1_ya!ueS%n@Hut>C zQ&ye9l)^U1l)y@N43ArTKvvz-%wn?AC6=5dPrhB8BgER?924rP$v2p_I5H7Du=%fg!&Oe~Q zXjcR#8V-MGS2ed(xxbJ6?Qi+Q)unU0&FH8*9+Z1KPIH;PYBD%&dlmTH{ygXW=gsHC zAF-q!0AnlhQ5ls*1C%XKL^no6vctd-c@VoY+R+4qWIGucz{H*U*V)~TyBO+#q!G}*KnhK0Ipc%c5Y;?V~cn}=$WSo zEV1ibM3o&PC}UFPZ7d~OQJII9Z&z(4+R~0E>oB1{F~ICQLdzLNw$bnD8h(dckR*^w zl9VVQ&@1SkhCkNwyBdjg|B~=$rH}Zzsz| zrpa#Z?gJ><0WSIETpqktTZZYOTMUks{-NdQ5|vy`th`^10s)F;Dfvq~{dD{l1$v!+ zajmpc$(8BoYl(iDc6T1X;5vdJgw%RQn#JYzs`#GPFg)_>sfa0c%)|KOaTet?3{AdO zJ=12`nvv;?>Z~hy0SF^9Aq%YHU zPVr;O!jgE3RR5IVnbn>kT)eF2t0o&UW}nYdpRJJJ*1CZWcUjF|_5o`FG@9P7@Qgp+X=70Tu)u!gH-7|7DtSY->bK#*{|4sOKClS!GadA^`XD67( z%bn+;E!R+>HfdecIcZYSnfbVIg2DoEKyt?TR@PS)2^{Cr_ z1DFHY*Sz##n&q12AA|p(<+IP6jUriQOLf4~Q0rm{kqr2EYBLP zIW?eh#azNF)kL&%Wv`>3H+3JTSi^bF0qHT(FMt@COzPy`NAPa#EXO|<#0jq^M@cGP zGB1}?ReC*>q^Mbt1ud|r#h#^LxV9-x0RZF!@R#g?*IZ~_Ji7RG03e*Jn4)FEQDbgn zT8o{|+fyIoT!s;ap z<9?#6rpB4Q!Oq6G%q$)HIh5J8z{*7M)(C=9) zpd}~y+!y^EaPt#n$>G(o>I7M_Ref4ptL~5dMaDF$Zz>uQbPp+QHK(E{^NW;S+3Uru ziWFf({2G~h0wbIXP}GtfD#&vQRqPp=qC*nt!ZgKA0CE9yvKa0tQY=TTP$WkTF-nfY z@WW$nY~Fl35(-glfh?X-30JHa;1JAuxJr{uzEC}T&~CVCaV;9b6=XM(AAL8{kN#f$ z%C4f#7$DLN;N<|{#iyj5UO~kV`(nY+6&3@epnO1@Kc|T^5^aAnm>Uek6LLfsvGnj; zTyWG(;ZP{51zs0h-f%B!UgQ*p&j0p=PxQ>;1AxkmXf;Q1E|Bj&$SYn0bmp@2AwBlx zAM99bM5wfy<5%_CY46<2PWcsOUW%QzJ+U4)9>4;EhSJ@jSH7bk5NA(#nX}>;8S=HG zg-ZN5s^20(hO+qe3s4gD1p`_*GBc=AGA-<~v{+#}r3>~^H9Np7GdPM(pzF2^ z1|A+urxh5WxmU2oNHYot9Q=MmH8G{u*YI{K-EilUA{NWF{p)@ly+_eWy5i z5y82+pux)jjAZy-s(|;Hd;Z47EKxz+Kv96D74n4iXgA;2^vUOBsOqym$ToT3U*UFc z;c5U$oK%->;fE%ZMI-EO4iOXg{F6Z40K34|gBj!pFfwv0^5F5G>}mUW-c|NbusuN} z4g97|np?sJxEDgfk3jqZ{!tor*AZI#&2K>YA#Lzl4l8un4c=Qk%4p#IEJI z$SU=n;I!l6)^ciX@0l$rdAeiz)6+n;lVFj0sa=RcbUUG~xng`v*XgZHea`c@-YSuz zXP-a}Frl{lfUn=!QJ%8OCuKkN4j)RD#-6fQkOdbM%k_KxEbt8Ey6%%&qMFB8Q1znU z_ts;o$0I!mcrn(J)r+c9)rX;vU<_~QvX^3a%VKmda{RNgbDBvOZzM#>zy-&7%Gb1l z9-H5kwI;W-X03GEPh!ZT+^5Xkw~it zFBU}{Q+ECW^wf?4(N5k=t6e42$#z4V*sIP$dDfuG_>;4E=&rt$cilo#aj8&ZXm}=4 z4qVbpdNb5_8H_Drg77_MVOO#EIG!m1`5XkqI)dv9LfM%u8`GFo;=T;b)R_l_39&0R zAlN#@7`4HHK3Dv8K%mvB8AD=7EBleVnVk5PdZY}FN%Jkh5*2i$f};5rzgo(Zmeu{Y`kV1#s+>u+9{>?kQ5YOP-A+L6O1CwlB zgU|vj6qo@%b1((z;Wu58(9lc2J8xowgdKV-r|qCacVg{frolq-ZAMXM0G%;gHcNE+ zM_>vw$n!VN5z4t1xFqGz|4#}IxFg3^{sZ$c#Q&9ohB**Pg3B05_KDC$?M{d7WXT-5 zljO{ zc$!kxWA-luAk>IT z$9Kfw(Kl%8*>?gpRnK6O-vY`-DGk~Kyn;No=U^QY?4ERD_f`xu`+kA#(@JH>d%Eo# z#)`a*yz);bd5r4XIdw%jX+Ux8Qu@*YAWntH-dJ;_J61D} zZ$h&$nb*XCP8~veS4JyhZO(<<4h2@py2f+3FAZ7 z9VU-t)fL}7-4HUsRbvt$l~wfvG&eegcZ*mfUX(VQ2D8NVN*E(H$n7l)wC<@}TPFsf zBbhbfcZP`U1lIYaywC_2#i`QhLy=w=*B#*1K$IYtoobPbGJ|TMz5iuqk_yMFSt4^T z(u+EC_|IGS#V!jq>z{=t^{-0A`7iEqaJFEya5gfvO%hCD1gPyeFNvf5tfrERQH^j# zh%6Ek1#3$iXM;&wW|u<$nX7TKloJurNsp;vE{r@*FfHvl!@UFX3*2>F!YxxV=h1x) zz~Z6DpOvPOGeKU$_L;lcxc$0mtJ?ef^UMh((@uE=ijLZzf7p&S+CXl23D>o4wW(1QgYN9r)8rSCOKqR?>3+TK0PC0}h&hPlxZ5OHrp)vQ%<^5ES* z3bylj!Ni)*uOT5hgEG4kkG0-zY#JI`_UWCRIJ!a1|*D&^aJ z5F?OGJs1Wnk>}ZS8JMOM*xtePiniQn57KD(^bJ*YPz5A z&DJ5<1Ez60)N$?CY%(?Im8^RizqAfA503NM*kupw;IrB%>c2wiB5?Zh9Nv%N55B6S z=h%E>A&{T< z|EAkt9cd21g>xN!=4^3*N7q|*iY=@3q&DZtt~4&pSxxpMwqw4v)$9w1EqyvvJB1Ml zY`JcN{6Zw`fgSSq7>na(uGNSswh|!*iwiPJ>_tUUK75$Jz}HTZWJ%1};4cQ0O2OPNa*-upVeb}oU;sOUERkj8%bHH3 zIj0iu6m<|3Q;yp<@xy(Cyi+HC_~u!Q(fkSZQ3MQEP;xc)K+@~RJ>97zO1Nm@cyqm= z790C1MDU2Ar1@u7K z@DQHhuaTKs-1%#slA>9r4pQ}oAq4rN8ycsYqx`W1z%9Zqn^8UKl=U?TiMR)KvJkep zX4o#0NtmDJ8vEw{@E;QrE^a1J#n26Rq4K`Ro6-oRsXlZZllE8Pu(+nfHs_5RvxXZC zb|~hKQ70}X{{_3wEhZ8Jo})1xpqfYXJ3cpws7U+I!`!Q$)|bSS?h1fQXW=7ie{$} z2SY^*`pa-#N@wqpwKH;7^al15B1-f>p^u9LCfFvJi zmpu&k5?ypN2fP-=lZHRH3xX+rf{^wI@8yP-&9F}syTCe(j`oVL^hd`cz z*sS5A38fh1wok^%m zAb<+%!9@qwnW&BcP(%8L7qJC6(6oJa{c&#HtoJnI$-QBiM6NDLRLK~P75pLULJHYL9) z<5BF2tIxjNle?wejzBijY4C+Nc#~?!U5oIY`H;|$7JjKpZYO{uYZIV`o2j%%O(2*r zpKF;4u2&7ASB$BmO7aW9wcYQvV^^6a4?vSOkFo@poCf zt_K@KCMDFGe`^+$j4S_wq9%_2XYf|0FUOy4DRP)OZIE~Ub9e(N_k7Qz7~?ICpH}uv zqdnYdBgJfd&$i>ZU2Z$dSU*p;KI4E=>nn>0n|NG1EXQrqmkNya84%g&#_bwQL&f09 zLytqRHxDR+5*e>p%F!JFd&XFm8@12PZp{|&b0fJT83&nbNVBzfcGw~jv8at2qtsT+>AN%azgJ83hy(1P_} z+s`SJaN4Ai<>$7&?o{%@=TL1{qvOsVrHUo2`l>Z#8y>(6ZE2E#;Qjtbk->&EL6FJP zivr7TZ<1KvC4H;zCJ#&Y!TNr;js&6^Vch&7A&@*_~uR?(2nQ2xemC_OPhwbk&rg6xG z6Or@-tK)YjX)hb^u~&gLrTlXCteAIPsYq*V;C!J1-HoRq!WChjpsmf<9_nLU^hmY zFX-EGcie1z;a70toeZ?9M( z9~GeIuxN++jr=gWAU0}FR$2RoVqMNW3yJaA*=MnB(3Z*uFz&f-bX>nMgo z{|)p@Y4owxwoxdM&1y~}?=kx{yY2h?^pp_@(sDzx$eJ|B8biTux!%lZOgJar>s*S_ zTTF5VcMPlv6;5x^dM)YZV5I%FGOqB}r4+CX4>2f+F}ZY4W+h&xFFEdqMB}Q)h=NS{ zcw6GCHil_*_AsT+sYq&3JUs7_6L8C&W5|c$T+U18)>84nQNV;@@WCKK!^0ET{R?IC z`6lCy49{RZVJRw^QsR0Pn)os#Ek0S1w8j}iLKFHJEh_|~ApLF4HE-IArR@69$sEwG zCBhIN7SN6MX}-%Rb4wks65r-*X_Qv4Vle&KT@$zY_7$!8Nys*E1CD9E-~0GfQ8#0# z?VZU-X9}(U?Y6$|z)sKhxGu6VC}8A}vEkVa*y6s(>j(;WtpD1CUKttEvq{ARpJT#U z*jEMgq=>`mDfw8a zDeDwucC{>QZcWJ_2#=TWna}Cw^Z{gS4IYplLb95p-|3$CxY?9^?aFJ>CcO?cTiMFu z&}Kp^0-0#NhBmUJnbZsl=TZjeQb)|W!)7U1eGyx>obiX8Tbj&vwd-W4Y5nwZ~(*2fS?` z-(f=ZvN>`QLf)r9qe{pgACw1}P(U1c_WmLx^dXbrcZPS$SZA=W^OS|d973v#P)a;S zSLr#e3M-+4$T&+L(8n$m53L+yVprZzIan4G_bi!@PoSVULefZ83XSGa3Kr47Z%9d6 zJ~AC)7Uv(O0RSH*Z{J@WXn0%qsyy5`$|@onwHm{;!7 ziBvu`=$iYO#S*)ydE{!l^=e>HtyJ|iD)un4m^MVL0FvotMAws=&cIumR-7A&EqqS! zT3T>W)5be0J#sZtX+T#pl_{rWwHQu)PC#fx(jgaS%iFQ6yQLpbNkFP}qxwnEaK9%-4cV+_^BKAsL%|P@zM4w$FX5 zz>65+0Bs?pSwpkO55L&VB`%Kw+U>@1YCU(M|E$70*?hg+q#^dCTj57MK@x}qRz58I7^9=uKdDj#~8gcyhqZ`ugS zk-`rxu2ILeq}0*(t0%_`_Yk!zAkS!W`Cw>bL$Rx{jDW}#b{8|D(oCqISu|XC=iv1r z0GJ`b1`8+5v<%R@s|;?-x^#NC6U^OlT7)VnFQBhDL2dADd~)r!@W9#5i7Svwt@>*hbR;i$oX*Ps!uJEy918EFk*f7?4N z=kXPw#o^l<+s`wz!v#vRD8Cb+Va z_9ad8M^8WbS@QnW5_Ik9Bta&4??XO?a+ z8p@t$ZJB$ZATg)_O|Bx06Qe z2!r;>HoL)66XsHS$md6t?MD+{9IhoD?18Y69kf*)=PHV;B~C3$upyz`k!W&YzioEF zv2A}KztRQyic;X6%0-D}12|y`1*6}fvctF;V+iOIT)!p_vNDm9dCQ~z#w)!PEOHs?$9Nsy7U-%!cn7dPN~;XZ~b%F zaapSET;i(joT6(t!QMENXk*4(P-N*}%_YR#);*kfdF(CrL@#3>55R?v^VXNE((;A$ zXfTwDPN|_~G}>CkeZ`j{h=*itRmP8j;6Z0$C6oTf_<`#jBY$$yj>@A7`&mvbQ(aV}hY21^ zXcwGcPF`;v0>})3CAL0s^00Mth#mdR40u)nq&JeCVLA83MRHq@vAtH~`DyNXz-%C> z7MOia$nX&7Z2}a1Y>1|>MT25~M%BH`m3YG$4zxS91WUebRED5gMRJ>pWvE$7Ew8_7 zY_{sk5tMFHY?ON%pD(2&={IOUEtma^Qb)c6{Ubhl084Wh8p9E_|4Mw-S80HOCkOu% zY^d$L{h@*AfCBftTPRSm*j)ouu#&xF61I2~@<$m_doE>)bZ_HYI%v&#P{a@E;vPY& zA_lYjoEnH(qNR8qt|mn}5*b9vM)yZBMVmvPRlH{NmG|YPPm?M?y+gS&#IXjd7r4ig6 zz%XY4p&-MyxX?>ezDg}Q=lyIZJhGAelf;9Z(DRGb>*bsq5wi**q!&Ufoq&QfzH&90?;-A`wMRkyBx z$>YE7axE(UtVUFBly_&?C-CtTBd$p!fZSezt|LnXzhU)wU}4IW4-yh9Gs5Ph+M(FS zeA*mb(0hG(#ArIAxLHSdwCw}UR_vL)Q(~S3!}qz9$Dx_k_PBnHN4BX+vQ};qH<3c_ z8&PE3ve9Iqd?&fHrULACKX_sMY}$FK<>%B3FVDRSIpWsq-25Vj9HcCqjc#_&;t0a3Njb2>DUe|+QL+a-NXALjB_+#pwc-?rw%D!XUtJmFW+2-Xz~Gdl;|a}6M@(H4m~V`b0;cTfYgCTbLiaN z{ft}0AN~+oizKT+a~`p!&TVMr$mb4z>dyN)!$WzrL~oP|50XCIr1MA>12Wi%NL?WvY-RAVJA8r2#6E5Vr)2 zm>V^#n7~LYDBO0qWHGi}HzIvIx}7f)!7K1~u0X{IN*=!jZt-%A0-52MK zPdEm_WYCYa2l`kpvs8W88o?<5h^Th zj4K>HMI-zX{x6unnISR8eKG1I72e+N8fa*Nadkmi8#PGYVA5_6ivLecW@djru3!}v`Sa`nCpDXh}S3R;FVd?CUSYd=rfE)k0-LdF;h4OQw!Yk%(5(<6t+Fk~M zFX7RBc&*^bP93 z0j~Mp*>@@a{OPA;JixC_h&pe?{rd}EcliyxTc+9Vl1};k)bc@JI%yB-C>#AJ!6Y^s zQ-#G}CaTi53ppsR$=kW{+7Fb~Z4loyGvKWo%zO_TG^O)z00mEA$MEtHR|b?fnh9Gk z!W_RmX@^e(NH%6p|MaoYzn55DUrgpyPXP86%4^XM_wbsq>y91GnR+di%S_H^H&2*Z zJ?%z9o25%CS@~rpwVMXs1dYjf?Y2tQoEgk2{hRKcF~Ag-_Fj;S8GISJzJ%^Xobwn% z`Cht|N|2tWb4=qJvl%j35>k7tW)FXJAFIa<+OhU2m3qF8_+7s|X1>?rXN=AurzbAN= z2Sg;b2h})dvp8L#c3r@*&P`czzRT3e9tiGEYo)t*8?ZI90*P*B*u7)Xogeag85l>{ zy&5x1AxMaj%l56#c|(IiaxX~!7?XaN@}T2Hi(jpHHi3>;0Nbd+%+x>UC4Xe{cpCMe z&RxkG9aQUB>#Mf=w!AC);!ats_D1WYtpA+TB4}6a|GrQ)YczI6o-ZczrJu9gwls7t zr39bb){(y5+xCHnmx%^2NWt!x>={>PCBVE=!-wz79MbGA47pU?e|6N+$(M7HCT3Xk~IY_R_SeNoZK z)l${j$lc7@#mE+9X=Y+$=FDJXYvkgRqN<~TtA_R-3T_SsVpIVdAZWzB17+8-y@h28 zn$nePN~t-7O2qWS95b`sSx~351Nffy@`!-mG=XwNYMHd>i#X@DX|fWl7(@!2obj!f zv&;3Cr_)P=k1vi8+om&df>fSwa|1i}ZJLC~ zqYsbA#QjCjps}hhgi?l-qE$atJo6CCR8vX9v4csXbxoUS_kF{G3i**lRX3FGN+Z3p zR=Rn>Y$C`vB`wc|+o3mhRi)NVOr2Eluncy31>qJ9LmhZcOeCqEIDDrk>1As0@IDTe ziA>4cwzx-VGa=E3-5$g~4!K?F_2h;@M>X=5kknUC*r091S2B_oEeI4w7DU-~Z^EV2 zB6*Rew*Jl1L(4X0S%<|R18NV8QH;Pbz-%B=mNCMr7^H2(xtzkOg6+Wy84^dLTO8_) znfII?W&@ldDGXG)F~K|ggUGe47Cg&SduVUHvx+#~7;?uVxn#a*r7jv-WYB30AxtNh zY>bPu=uj4FZ2WNILjRW9tTpBdNRS>%9?q4q6@=IBf`KSun z+Sz6x`*kxfxs=Yrv|Kcy0ORm|qhr9k845m>dhf5c-nr7X$xv}&s-ha$Qq@#}w|mco zMh4xr11=xkZSfEtfxX9;tIBp1dL1@arQBAzsy0=sxq;tU?^#_nHpM(ZBb;aBmI zFtY$dniqzLoN|j?9M|<%KkDZK;El=k=PZvfXP!GqW;2b+zZ68cRpv&797`%wwaGz* znbd^12RG$T;Lt1UihA+&`JdAXXE8^%>$At5L-EGkS4jQ-*ZH>yI^~FE(k3u&@4qM^ zQF>dHjtGZVdD6Bq^WdPLGl5UJl2%1pEf7Fe1Z*wqib!dM)H1d-LeUQg&fV52M_7q} z%)S9dFHG}-Bstzr;R51HUs-?eu*lDNc))2;r`p`*9UHT(519sN^SWj62u+KGO(2Gu zW}AR7i2^4fr+5y1R>}m~s1deBM1(l_3VPM?6Jo*h-#qA9EbYqp}QY%iA1KzX$1cNFhRrF$kEZvS=7qK)!EAU6Nen^)tmuakc0gvOnd^)f8j%p ziruIE1j)adQCBApb3BTKq$IyNfPav27zZ^dGaZdBd*RB-M{jJe!K2L{`nl=~mMrmc zaqyFw{JE^HZ)?0q&gsHBJ;C~u)ko0Z?+wxrUcvdd(Uu5v7&u0>W|QOg(Rc3R>zVMx zkj4=5&;sC4S?Vo_Sc_&ETNzhag(-Te7)2*%AT)gIHdGy%IY$OqXz%?F)Ib^=FLBwdN%sjJ%C9$s(*2wpp&G&eXOrB3NmnmfYmC%l!jwD0(_8 zcwc&oLSRa3q;a$gX@6fpbkl8jmt%^fdm}oK3dj&n#G@D|o|G(0o9gWzyn-4nSmBOR zN_6M^V$v$b6U8@7Jw^tI!${2yxsbU>5CLs%&XEfq(Rrj@9kSaXi+cG4ZY}PDa?^?I zGCacw&(w&9pl|B?G$9PA6inDHT7zizN`L7}owByTFXB1D{-HudRbw|Q|JW|MTy4Gd zNk4Vd|Kk6@h{T@yxr+9$pDXn9pX)#T`u`)~GGp{e$|L=rB>xo+AY=Zo^%tW&Za*)C z#y{Wc#$5VCNN23*NAnC>ymmdjv9KChJZw}x15#E5zg(&F@T})I!J$xiNxH``0x(Wz zqTfU?^(Hn(vR&LRx^8cm9|*tX8VmNa*w^g22k^F@nyioT6UqgqSgct-=;kk3=RtXf zc~yef4zHDS&I8v%s~*nr%=6*5qUMxyCoH*?{G4+kLXTruW{9j>Xpy@`TrC5ZmS&k1 zM@cD35skA^d>$btj{d9899eH6UWh>}F*vU}}m1(FEOif@lfrc@m;%;w;Vx__?0 z`J6u_XIRtL|6@#+j>glV`5=V`fAh6QRU?6DopiR(f_yi&~f+Z~2D0g}7%vnzg}t~_>BG!knULi}UY zOry`XP8xOztRrV#hc&TdjIHhFV)+Wt;lnznoz~ng1yJz4Q!>Qm*+hih8o5U3i_%)A z@op1!s~S#!y-cB5?K9ijg%j!!mzgY|9+ePX9&?Vvl`&9y=@hzDzdL|qDNEa8XRGue zTy`p=Y0ziptd~07rD%2x(HBbAaJu?m{65?+2WsY%AxX}zspqT4P|f70QgO_!A&e47%bU+-K#Ms1vuB+4yQ&fF>ju|WKiBC{ z2UIjP9x|lJps&B#c4au~7m zCE6VzQr)#wqtj~mL*|I>N8*iTgK`5m)@kHOTT#_KX&1U=H93=w4QasEJh7vY$vx%B zRD%5~T~R+)b9z!KpQt!CQTg0xZMD}ya>sj$^AuhpOPlvw$6Ed{!Y38brgNrs>SM!S zFNhOUW1Wk&=HAFOhFaN6F=A>@Y%j7eht^}iiD)vh689fVvNYdIEWM@1jI;hr-Jd`) z4A+S1JVl3;3U;4`y~cMQWR3h>ZN=p~?=&x;VI7;qbau|vn$+5mT&WZ>2_bSGiG{E{ z=q^UmG{fj@u{ptfw}1s``pO+@QSKi9zR~1&(ix)h%89WrlQ93?9o#y$rKcK&&g$jP zIvy2kj??_Zjb<{_{ExEr=LKZ_4ZLXSlOSCWBUWQ!aLhK|1x zstsZoQ;cG4MKn`ZXev7N(1;1U#6F(cyEFRnRaG8PHQ;i6_#5bwuA#MM3rQ%|i&Rv- z@rE>1d!*2*-*97t5;Y;~iFb2@R-18J$0fMW2)2aG10U})Sz;+jdJPz8Dwi@yE%N?F9s~b-LY3DWrx+?Vciroz-u9f26V+;ur z@D9t%^tE$BN550)cFUhPwJ?{GV6Hek66GLO6z;Hh*Id2pWJ?Ro7dSH1Nq(Kw^E_lL zd;1tq<5+Df%+E&5M#JASIB+qi>|bZ2svyty)-+2fbJ|_R^a-hVvcj>!bsSh!r8vyJ z)^F;ZV}LpU^X2FkjvQCxpRMgDo7mRE(fm$oLpY^mdfSx81ekyT6Z5kreqkLrKQ=!Y z>AGRhoD8gf>90lfP-fYxJ#3;#EPiZpCTaDijC)WakdL-4Jf70fGus7gK=J3{BT#4< zQ{gh-4RYg*a_i9;PHZ)($WI?s5k(Trn6fs26l?jh-fo%2|ptpDJ2WreEu$2@~F)s90QM70Dlz8N2lppi%_Pf>S@3Nk`k zS|aol&yW;wBf63kUt^460ev z*UbR?$6G|3T8ZF&?_znPcXI7m*j~_)S*86?(`2`^w-XHg83~Hh9I<8M<6PHB!FNY~ z;ajtMcV^AA2I8j7@0dJ$ac@0BkuUQ6#&H`ckxf2OU#KG7VF)NtLUn(mGDs$v|2PYE z{KD!PrCjJ}?@aW9ob3Yp0e)unwHe}Y^VtB2XiO-1?tFJH_~X9>`ALqDdzk-kQX*lM z-2?sSQEuf^OCkK9pb313{w``}Zsca`nskaq0F2^V%b;@x*7-hfOq#-+v z@`0Nr3=C83*9(bF0D-m(`*SDOTkQM_s4DYrw4^P$$3wjp2PQFa|V>t)%2ZjDWFwVzH8?EZ9h!-d!7k>2?Y(?(MT`4 zEK(ITd>*c*$Y?JV1NPm9Z@$qg(Cb%isfnJ-NL52QW6s6sVJGcpUUBibMB#t~v6mUj z2=5#69kP2E41Sx*^h07%>JE8p@0nD;^enmywc)c2ZLO+bz7!qYJz8-)@AAdRiqsNm8Y zsi1f8yohCkvYI6w2%^puS!K%$C!j$SMWoKcNU1rD&Nhm-9{>+$L>m+vnYqWrlmod4 z-N8=^H$D``4f{X0$iKi$M%)o-dfQ?K-aRrTH#J7>$Q-i^nNX?*Kp>maXlp_#l@ZKkLI^XN-ai8$P(|(_%prAh-va*KF)F@?<`SI2T?m(4ueyj@ zvLYeA!Pu##e~8G+nwa{AI6?)bkZ9e5NY#-=HPN7#VhJ!tpk$1*-HbEcq};9MWGv;} zSzDu%O*w;=8X^B!%jV*i{emG!KFzoD?#4+r;G{Y<@%A>fM5Jd1Hn-B1lTKW8NzD6- zpGlv=4~yFob1X;1^$XYo7G0G~=(>g0qn~+6Y&K5_3W4tA9hLOZ*?6a~Mv1dBQs*GX z(-AVXR&5n+HRX78iN477E{0Oh}vPuvmEYEJJOS;#DWOhIi7({0M zx1_qs4*KoBiew?rJ^y#jh!Lw6l>2!a_x}VLw*Lkh5f|M_cnv93s;t{FZtpIa>BG=h&|8N3PLo*WV}$gZ1`YAEP>m|I z+rK^0W>juAXLk$to{XF)bN9>TG{HBx9Xe^qSR*#+0WB~;PmPMhLQlj?+G8*- z^x^DT>L_B%X#Wzg=t?*-257+7vhFutvQXIpK#!-}3}*Wt>k)n=LB9`Uv64)-dwzDb z3xVq5z46Xs)OX-sTFxi+lqp-fBytFhst4V4cw)pZ(s-9wL2(uV3k8(_z6!D9wCq&y=K%2Mk@5|ihulU-u!G(0KE7t*GwgiwqO~)d0(>U_PR@$E!7V+n z!~>{{31&AwD`8=)=s|qmlHcvY*Q2b$m|niZIvEXl`OMM$JeTbaBP@n|uh#<>IPK56 z;%ksXRH5lo&M)1j%uW&Uh7P_%c$n3h+;eh^l7tafNsHuplAD`KD4n%64J8mBwE=E#U{D-lRcm$v1;l~2`$;OQ5W3R6pw7RG5|Flc zLYS1tUVxVs#ID3~RqsN3mxks6#m2@Uw{{5+=En z$*4uFV^rtw0Pr=LbRO?!;3Hr}7!QFRE1fJjevg*538GmL2wo2lRUsFIS7FyAiXp;P zCC1b|xW-6+KvJ`hK4XJPd*4HbsY9ICc>efbmGvAL(JasB*@2Dj%NOGR-p5eDe-+Y` z+R(nLi;IGk852Gkowi`2kY6Pr;IvX`WP*@Uf}qL1vO=@v&q>@QM$4MdX=&Onu0^{4 zG%ktKZfQdCm(&bBUr zVB4k!?l*{{VhGlT5513QeRGG$UHwzSFs`2(odc)F|GI=sR41FK0Bmw|Y&M^~A zzkj;fCrn2bYZcvUKiMv}$q5|#lm{+bZPea+=P;%!g@xrF$XjvzKE`Fgm}^}J*|d#- zY&?^~a?$OlVOlJ_ezK)W&Yu<>a_#I2T%?&tP3iDAMJ}T!yjBp=>}uQwgyrtq@i;tO zmH1|ywd$HPEPIAc0d=#h$@KU*muNNLORy7%6U{Xm;Oyj^$o@0j8|c}2)^0Opmzx zmSED_+Wy&KF~5|Hue0U@mXqZzwB#1jwr&fTv70a~#D@bH$Htn{EY{!9iXH2~41$(9 z43>>r`c-GJ4s0*B6qR*3oR)6I@ILc&taIK!oF84Bot(fmwb-3#VH)mDi4?lfq)ThR zEY~?)ZXzFTEX7t>8`G?BbR6$({Sz{j(E0v{3hjZp4U~|8jQn_4E9qM7L}rZ;Qa#MC zClh7G7+$VG^q)OK{h$IjhNpVqS@rSL*544Y=q}$#b=lG$Xz-R|hZ=pq-|! zi%Sg#7Yy6G;E4_e?ntggQx+oa1Z^xX&eL=Gl|on~htxdgO1f$oI8H>8?J4@XG2unG zF#S@W&VQ-E>v4rms-kBxjX3M8UrfSUw-S4q$RU=|#lvO;=}cHE4o?-+3gG-Gg*9iv zFtvZ#2Bep$3v)QIpf5w6z~<@v>A+`}f8cv)@!~x{MO)qHd3%R_?Pf(}k8sg1;FdXjIrq4U(-T(l zvVbOFrl`kX6#Ske$%P)P(n-?&wgV^zs5B*p174HBoIDNG#oLDi75Skr_^G2Kc!j++ zgc5d3y>|GRiMnU`085y6%`!zb*0+keuN;ZGCV)d(PNE}P^Tc$u>)`(WTbEurqtOo- z1n?iL(h@FAb1Q8XewX>5mL_zHLSfUXjUpv@KXAkAIxRcAc9*m8+LY77w9KXtB%K_midB@nP2Jc zkKhm`0-|%wC$#$H*7GPAt3E6^FvnTR6o!Y91}Y1+vn_Fn@)Dc9tyb0O)V@ zV%dd@XGUxfwSO02c0>;tR?zG?iwg1;Cr1m%nqx?G6U2_xnS>9Us_{=kS4uE;DtM98 zs2qYL;;~zv=To_8d-9wY)l*@sXww8@K~8Rg99!A@Xx$m+8i)LSq%Jz~RDVvij1jYa zbj-}D`43|U&v5mf$Wr;+IC!{dfaUH!;T>Ss>o9kGA)Yg>^pbww0TIHdVH`D_tS~rr zkdDSRvR&8`zCG(=_K_j@^1ugDvu z`gbsh-=HQW;M$WeSdM~SXYwVElnkxWo?4A`Z#rA&cV3>7Bso}c$7Kh$Se=3_K~S7hN?Tdrk&1RwaC0ttCc zk1|5Aeo?uiUb1!$Y7qT6V^c#&q#aA9jH6ZtsRy)>fZD`0yZ;=pQ+I0t{|*VL>^oq; z+P%m2ZU04NeNw)-xnwqZ&tLd-a`D;2vs=FM2lq@1GChX9l2Xh)jz9`Ryxb~)lUQ_$ z&!3r$T9q2v$%|wKC?==H4$4X%qS>Yk1GT4#`OK*>>tDQw zK(8G3;=2UgsqcUk<8Demk?qy(D{SeT&ho#{9Dm)j%eaVed_TXex5}|cm+@%9Ac@Fr zxB)(98zf93pfnLGN!99~Nz#WgI{Z8FpaxqjD={1V`y}zWDiicb(3f<<1amA)p)q9l z1j{Swvhp@NVz_7eF3T&%Ck@Dt%&$){v+crj5}+y?ElA)a)If;J6b3oSReFl^vE}u1 z&7E~c&GC+%i7a3?1o!SH>BX|W=k)a)3ikTH`JJ9>;Jiw_t03rEpH}m+M~;4)0&xGu zhTynE4uIfKCt9&bk}4QxH`FjZ#0=c;Y5sg}VXLyaGI(%oW84%i~ux z`4{8mK*<*6s%pCR6mv@9Y_JuW+TZvx zI7)>$CDtXA^O&l%84k4SdYnJ{fpaaqoTi(WU-!NF@ZEV1vN?r!TQ~YO)D^aQ{3tG; zaDk6$f)r;L20Ub1x=~Vj{R7NNU)U@wr&+H^BS;>V?()0A>QnRaG7L^#8aA__@pa^nsQM3mNdc5teoqYx2%ZrfUSsYdRHcXe@tMq$ipIL zJNVk?=Wt7+2EoFS&tJJ3flEh$YdZBjk9q!lpr`QT%djVPkwI*m&oRgn(WohB<4@vh zrgm+Wpg6=xxnq#-LzNt%_-P;I?31cE=8VKlRm13U(H-->&bTu$1$U4uBF~&*anh4 zdja8#K%?NhGUL*V_WeIb=}z1{`>`uAeJRG8B&HH#jnd6apC2=Qfx-;%Cfz@IC-sab;C7P# zJ=r0)5)}rolC1pf7owrvHygV@-VvQR`141PWc1`|;)rXcF>o}Bn|?_v$sLN8j62)g z_2ytZKW>IW%|=Jso&$CrUA0?>H|T1)D!Y$`OyiiRJOA8EWTND9m(PP*g4n*m%zvp5 zB%z{H&cs1@+nlKbej}gGOIL^CH{|wqQhY4tn+J8W|B|p$mwQvn)Z2H#FX3kIE-V^k zr!2S5Z?+GT=aqJ`IcSYbL>#D(UbJ(^@9L#3+nB+FVNDy{nGGox6jt| zg{n%m2*UafD#h8PQaB2RyV^IL)r z9A}~oBBxp7lLWO_S#vGR%PvNK~zVU})5Hs&W3 zuD0Tso>}KPB%>!u4i!Sncyx|j*q~w}V z6F8x^5sfaX+!0CFV~HRj=CM-!@`|PhsGzmK+6V%*uU=d+0Rwjs&m^s3$gyU@ z9Q?5b7*rucarFzGV!HclaB8%r4AjIe+ED}ziYW2%9#jfGJ>(DlWWQ`{kO%dXrQDi1 zL58fM{#-c>&Y-hXX|!X%;O>YVY;%Ykv#iN#N5+N358wJwpVo@sPA*9=;5C8A%LoBZ zr{KV^`^ODOpQLf8X0CQA)U=l-vKkrgPX0wLM){uBit@%xg1IbLY&W_Gv^pwkeWerH zn`5aHJWYLFM@&8UXbv)~{Tfy8Aa!`p4vO*@Q?=3Ty|;tN#7gCREp0WPEbrk+#4TaS zRK6F)E%Doh>|cdwX9r8hwUvLk?A%ql6c~YQmF!{}1i7u)60NN*G6-L>xP%K@X=Q^q zlcp{KskgB5Iw{mpYDYT=U(o>#FN2)#s%zlz*|s#(Kt9Fy=P?E8M228B10mPlr0IZP z20N^aW$^v$@w(xK^*(saDPI-|w4og6N|(WYXb|7km72FhTHV4+vMrM+Z-;;L!8Zij z2nzsyA}_G>QqJH#`o|adKe;2tG2y>ZQL! zeWpeifpq_e;l%nD?T-MPa?OG+YLCvNpgc;ZnPRP4G0PE?yL5ydle>7t{UeD+!^s%4 z-wCCF2^F2T@@EwVac628LQ9_1QTk8GDHNL~h_A1&WR)Uf0^bf1C1+$sM$`6z1oXJ} zSM6S@8;!mxWv&y2ndYy$T+OVRGS@EH{tP422(O*yK@+5Ui3DB2zY=d$^IsCC-4DoK z?XAw&iTCSM-Q_tQ>DlpdPXA%iJ(#_de!@zq@8=}^oOsKiN*81n+hXN zA6`tSK`V*!CiKT_OCmjAg<$G^$cg-VN6VR(1S`OEb8?ywX^`G9uvGv3iFeUxLpEPe zDOU8z@t~73awxuK{n43=)|yvVwQDz&z$N`{FC&{06b*mU_M zHerHy5El4J)Ze-_-rl$I`Y}vN*lDm{s<}r5h4a|Eru9B`LA}^qS*@2trV>AjeZM>W z_6lE4Q1vBECSRX1$Pn#cE99;V{Wr-oH)=X2OthY&?foB+JX!Anxv;D*$8mR*o{nf7 z&4;yOqaUnq5MBCYnLUM+09G5b-6?L0UWxa4SNQQ;dutO(Zi1&F`aZo+}&?Tc5L3-x6e%sgOTcdp-s%e}^F6xX&D z9Y~L$uH4TP*h0^6ZyypW{lD(-YUWJHP)Pg5v@a@d*5aS7(i*YL|xn6>($q1nHt^A$#^VvQvAlL4u*y02x)Ad~0Oo_^2(4_llX_De2xR zut1t)e6Epv6W2k#*X{r06q2q+v6EJ?mOeGFb=Z*KKPP6?k756uCaU}#tdV3zfBb(? zo4Z9GR-jKkNHy%2FC_oftz%ZTiUQebL`zkN+pKba$ujDZj( zAzE9LPqe_wm?&mNoo#mCei&lN{^!zj7o`W4?JfT@r0|yHy_UPhn&kdCT`)k-nrEK za1>awEUo!QNGdqqP6>S_-h5Gqo*r5Qx1NDouI5sfk|ZU-0_o~TmMg(kI8RJP z{i+E{M%0#_rCD~RISZ3f;_fp{B|-2Yje8sKh5DjsLbdu>FXhlvc&ykUIk5?56z=Kz z8mAFml*VFAe8Q-N8F6z!W^Dj zr(LVvCXBl}N~Bh8Sr)}DJ}cb-Z$U3~-LNKs3VHR>GuX?DKmpN$Lm8DBJSdc0!a3uI z>(nWh)3O?hYn&07Kt2?yf^IlGByT9YIvHL zDpgr|eyU%(LAfusSyEjrJAO13?HWX(N%(O0XQDorzO^=|JvUh^c3mw&t-kFjx?r~NY zXX<;~^d`Pxf=k^Rt8y*%1O2{QwWK=3ZLnsTm;kfCGTjOL4{2p06!;ZB&H)FZL0gd; zzi!BNR&N%Kx;;+k=WrLf1M=Bb`z7w8byw4cnZ0D|?P*K$S$!|ByHG-IK68yMzLP=J z>`J>7$s&J_2$^!Ul2;zKI}E+N5Not=4a|f8V`0$$YciWs!p$KQrHC?Vu0(2C?k7Xn z0k%59Fb;!HpDkk6x#py88<~VkGJkJlij9_*yBWPqCY%4jy=mwTIli|^Go4ecvMIq3 z<-Kgg^7qx7Yjzz5hX^@zTSZDUY}Sgr7S$6p8b>>6AagEhd<)OmVd?#qj-TtVg^icL zyQ(2Uy#@XJQpKX0Mi0pdesFHOW83Jzl)7J3L&x4;?gpKL7_{#G%yR>HR);tw_m|d= z_Y!~Tl4e8-S_36c=XGpj$HA4E{(9kws+{LjMKHgbnnnLj zgCblffFhbX?zj_47fXTyNta1JYZBPV@aCa`9d7*i*tu&=-f2ikL4 zo3w?ga9cFa_Q58vVi`$K0Zm*xZ+V_}0EXe|4U*g`^q&T!z+9kE{cx5mjP&Jpg)5AJ zgi00;Arqs)s?`KJ>rhc*JaxUtkhW(1#xwj8$fAVZP`iUgFSf>L=n|E(MCQF&X{#;^ zLDX6%aZiZdObRraOzM8;U11%9#F)7$%M+aHhh{^} zAFs>8X`>Jhh;w=khkpGb^(u`Q)%wSRF$ih&ycZeo{?@Z4euT-tm$|Y)WNtHLeqVIk zGWrB?5)P>>d~mRR{9e>VtRUo##<#j6p#{+VZZ|NfRgoi$3vq{I=g*R zDBL#q?l>lhTdasUTN`2NgZz4rau03!zv-a{)3SN*PiZjbr(NK`1b6@g6d+~q;%a33 zU#@`v_5>t9(bD4Yybd!aQ=1Us6B>sbN0W&s6=1T;TwPS-i5E2eJYV?u zjmyB6V99np2m3*_?;{V3YXX^ScFFDFle_)W$zS$%`!K@z1y++IUQ8=A1204i`(oTx zUP3JP7SdUBrr|eW$OhJZ9Etg!Ylu~GarLm_?0ed_A1UE#6vb=Li*!l?=ar<6wujE} zkf}}&gI6b2b!Unm{4@tkdeLsP-oK?*K^erJ7FGa-tu8~kIIkvXsoem53hLFNN7jTc zS&=K^SAY5rd z$eWAGZe?|^;tD}24yr|JAxR{Od)s;0vwNj5Q5Qo3PTj4n)2;>Aie4A)OBVO6l$8| z>LAoq22%pSX=J!E=(aKQ8C&WmE=W%2u&B8_7TP<{`EIR5 zF&@EEJ>K1NLP`EY=rE~~+>#9}I`6lA{SD_)UdjpIP<7`(W~-13tA0pSq|tAR7v!;O zM56~RV)vv(c#0qJV{>e=%1;G16JMKd&c4nW#4>hdwGB`EkOYaEH61C@8(LF5y%uI#Rb$4Upf~C zaR2Q4Yu$5aJO+djERo&0ezeu#$&#{5Yq~{U_j zEp+z}XY_=y<)E{^5YJ0%0Xf8N~DV?d*RqrHWJM|X&X80UFl=oS6i>u#ffot$!W4EXN_dauQ%J3;K;Tz z#74P1IPC4Ct9gV-;ce3g7)WSRO;7&<3}p`R=rWBiPT>#-K|T}k1@&6%t5(DNlYNqk z*XlV@A_Gd80ogusR4CHbW;`8tSkCx5i5?a{v+fiYdQIb|nG0x<>GWWJ_~y1YNWsRr zmKIE%{8+G~Et|)(ccF$$THGGZcwaYscumZijF!Uopi39I$ybcJjLt638zxA5jhwXH=`HLaucEMmZ5%GRQelaR;8|*U&tyj{UpYI!+bfw zkBicVP1*5nwJg}-ntp_KCMCki5)OrN^YTfLkmtX+Ji&tLZ;hW^!Vw2*PS+})E#qWq zJpDv^!~PN%pP|SgTgTpg#g|<`?~!%rcO*qKqJ{z1NgZSrH9;TXRO-L(9UMN>94OFg z?}0=Y5KF+y%s|CdK#zRJ*TcP1*C}~Oc>0R^V}gsAwLIJDRX>UTxls3Wob%m%8QXcN zi@TJjyh4qx;LN7o@IW%K zYo%wtBAXsLwPXn-wT=8>92&%w9#L^}jgY~PsE$ZtJzE6l5O%Y6heP~FxxXT4evx^` zzqEAp%9;ZpT(=iB$h!n=aY>nUPo6=!?fFfEx-(Ag=-r~AE09X7VZFqgOx!TtEn z^!VCfe9%Zrim-t{rYQ@oUEI%z*0mwN5euobkksDy-J9z~?VBG8(IsP5+e5Z~(>ew5 zm(E2M=_t|-U?jW;g1a*Zf2LmXKz`Nl6OE@v{8O`;Fh15dBXr?xjK?rJ?VLHi~P(p zsn=m5C3Ta#3tjneFUKe*vN7Wjdg;+B53*jKC#Qa_mQ18$p2@<24^-AXXjzAe4`9Fr zF$4Cz7Tz^7bP*Lv?iLD*tHJPVBK!%4#zc^fQQIL)Ty^3TBa@;70*_)M-;AQLPhp4l zF^;VFP%k_SX?cKnN$#-1U&J`4uoNgT*x5#8(y|wqUxLgmEoA6usQHdju15V!3$IbF zmHW!PaY>1AagV~@S#}MB%(~kx4GfsRg>f)Z)YI!XhlR#i((PZe$(<>+~ zjAfSOKNNuInSb=DBPd>UaxM+Jt>HOLm>*#xp!F76g7NvzY9xIcg#b+AeLIyMla~zs zI_Xku+nG4HXBfZ5e9j}eV1hr}0q@Z0+l@ypkbbcQOh-h1Yx&bN7VzzH7o3kCuRb{+ zM3;g%uaxgU`+!}+B6*%rsZ^-89-LRscV5p)v>{*zxDxzIEMZ`K)#Di|TsKz-_e}g} z54aVC$AQ524(X07kzkyL^A6OPol<6Cbq+ ziIr_=iE1Qbm&k$r;{+n5z~YE4^apkfyfJVpsqFqryKX<^|byzOD;xp19wy^!s<78-QrrlPnhNWEs z>CVyBF^Cf0myRSidNJJqlU(&{2=Xn}-@;O+sbr#Sy<`E#jb`CiqQj-;Mu)Q4i##Dw zlDD4jFuQw)=+!Om_>yTdToC!}G!6KDbqP=IT_sHdqif>#F6zJ(7Cd!T8`YQt0=Y$HRey zNvdgPlmc}yO&9o9jt2Ig=qW{Zyy4HC@jHGohsC5!FAFkRSZLUw3TDg+tQ}~cm`Syv zg|jPZrok?SfwM7b*vU@@Lfs?5C#~%&`UITZ93-fWgXvGwix%y*-ZSam^>VuWl+cW0 z)oAO@di!f}KsrS^)|NIyA%5JI;J81V+}5mEdN`t{Rn?$ZknklHcSKnaSB45|7qPXw zmJBU%!Jo$Fgno=+Y~|6}y#a5>YwApl0m|}m!&M|y$ZqGZp!IV0lQjwuFUW?a$-D+) zz^5i?Zid4~2ku<92HnhY3TJ#rxn^>vInuiYx>ascPxE-q9kgD+j)WcmR znVlP9ngJ^8aG%{{2u{0F2CdgjnreGymmqzPwW$Y(mYyu3^iNBg0Jhw*lYJg^Qxw#l z*Vb^OE`G`Hp#F@b88t2A!9i7S5dW)wi*>j%v5~A*j}h&1M#pN7HYls&tk!TM6eu#T zwzg7^aL+Yiacb;*T-e}Y_3klGJvPZ{YaH^ z9kI}Vk?#jyHR;8e5731yfOYJ<4!Wh38@xyL5+w$;1@7iHVd-AvN+FU=}?wY5!)=pM=CaNRW`^Z}Kd>_y3=B_6%E7x2n3QXV{tUstbkL3HQ($(q9*kiqx=f#3Lb~h&RS! z3QMh^qHQ~+D#csIb{nlouG>qdFe%7 z`Kt4>ZLw!zFYGnh(>$*@T3rY#>|)+3489O{`~r&Eu!*l85o)hke`zF&+v_zPok$kFLYIIuYxxE#kdJ_{7D=WEL+hI<6JdGU zVVklh12^jf)-cyneh=Z|EvzIU3I%frOFP42f8U0{hWTrcukR-!#t%+Y2tHeF6VtI0 z_@yz?9SEKZ3V~MUkxNX`$TW5Oz>Tat#}4>R2&SpYq&T2Oh2>@$uM@;%EwDoa`5O9y^+Kz?l$k#9Sm;`KRxG z#kv_=ye+R#b6lKdO;O|qeC|p3qzk5vf%e8T{S@jBKQnOW%ho;`bsN%X>Y5gpSlvBq zBsPNz{EqH3K2BED)fgQyYM^tEen6%p=ubLBus`gEqf=MF;Ew36r|d>AMyHMv07+$u ztNcJIELEc4k5!%KTw0lSc_4Oyj#4aJu_fsfeHDF0!I?GDBX@5NP_nKhE{cMr%L78O zy8HUqVPvfvAG+P=;2aESu}g)is?8N*`)N{O&*=-P7Ds6z;jV-p_ztb=+l6A=F&)DT zBhwl-W%Ni<6|g7a&Qsm+>19K435lypWDq((MEiU|sfd0JAXbI2kpGV(ilB~9vo?A_H*(fpH3 zpEqVC!ipx6Nc!?NUtg6<>#!)U&0~@XYAM?9JhNJvb8~jZqc@f`ffMF!>x%AylwCQ= z&S=jPx|n^I3!t35k6*ZB;q*>9OqMM-%Z+w_Nb?n`r$s+~e#%0S@flW#YaxhjHb#f| zlIpz@G9P8$iiS-!4r?p=12c1TihxuM)HDX8Z9RSwrypY00fAx{6JB2-6L+QW?`WWv&w5UF#2!*%kqApq4ZRn|HTADpItp`FR4B3|D% z4JJk*3(>OzBAjA;FZy_1bp5i@()vQ%X#yJR(uL`UEh54sc(g4#>)5ttGvV`!=~Q4% zTRi5Q3*(Mp*b|wKP!Wi=^%CX{#Omqd^YIXs8eg?>v zjo%|l>;UtaqO)&aMfSw7MKpe7oR?{6sH?g2pHEC}wY;lt+L}=Jim$I@@#Vo@L@I zba!i?jVP3okl5O>=c+iFGDQ)dIEeY1So_0tiUz>5Ov0=j@tJZZWkQoouI=Vva>>B* z%j1X}Dx$V`kenf|+2cV-<=nbLO3g|vsc2Y?Am}E{I04x1BKwi5){Vo(rl#FW6hYK@ z5jVYaVEAq4WfzfW4_uNzn}gV@jZ~F9A{UxB$UH1=n}TMNmIf-Bs%w|-M$`F`>xQs0 zFCVbBt4w|F5Vd7;d^5qDVgddEY!BUIUtWS5)pX@vlDd}ELV;tGjIXkl#IPmPP=Uk8 zVD8IQ5GxbGy!q@oE0_|=JFfxE>!HMFva=}OC5m$MgW0<~frm=iL3VyU&YeK2Ux}_I zKBbG~#%|4M% z0l818+faSg;8)oZB*PSAG{Gt?VZZ{hdf1hH6)-&(6Jh-oHD9yi@S<&g2u{`{F%F=B z8r&}b@_9jlS)8wd?P`40>jHRQY<7e~gP=)a5^-T7({2bv`Y^;a3Xi%FqGy*PC>H{E zw=$6c+W7-V>PchjNF<1pP&w2K$*m=4OZD>?m-kQ=7q<{Ta23-fqO)X$dB#EG`P-3> ztB9+B;fl6zC^vZYFLp0&ADF(OMCSse(&x8M$hHHhG*(0#mV<>?X5Sre6;KZANj%WQ zcVfFf%9gJLk-pL!2rEiRE6>y&%gZ-JD^Z!9}KriAM>o9%fP7Xo8iWH6NXYy%ac zgCR^XH$lU%v$*IS{#-z!6U}s=dGU>x>9MeR1Tosehb){zks}O&BLXD>uSseE0X(U~ z(7_m^bT>qy$?G;YinSi(gh$lfBOCz|h&F<4S5|b1#rE}G_Jhg|PYZ=pmI_ViRJRj{ z!3t=*qj^Ebw1qiFbJ5mrZ%qD8O3@;Z@OdQ++yu@KI}eyVm~9o+{^2%5xADBsoI}-7Qe&TElyen4ksTF!{mRR2h--NS{xkWVuL0v=NkVN3fbq?HqqC0m z!~2|}Po<+@AJD^46V*=^$jYvtuey{Hsow&}o1&_FN$2dS^D@yQvXRY|gBi*saYbM2 zqfprPeWz_|4SHKrsY~TaP3fMR2eh?rjuRnxA#R0sce|jmb}X-HAS|z$p2$SDlrrs8 z%*S!;DLmu@wUiT~Y%^`Q4=`(pAHKiiN+ythn@l;UDfZ@i=nLXIqydPJuVC3fH+Pbi z%5@gABl6OpMPT*fv04+AWmMQj?n0)|a7#r&H}x^*z^)$n&9I+qH!r}ShkC-*ezcMI z>%D%ie0>szr_Zr>-GnkHJ!)Pboy_LQFZY(Y@pP6Mo;;D2q-dgKuN%OUstOe4vg=|q zg427k$6mr9qwbC(p}5%!{t06KsedPgya#nhSSUE!n-b^RLVp+rdt2hT9sVVI*z`fA zyNGJ>#CuuYhWxsnOm~)i0?e1tZ#j02S51edjEoTu+UTQe>?`lHc zyr#RN)@x3GWuD%-1DF6*q$0fmV!`{t;+eAH8O5|~yx=?0d4KbQRmbLIWeS;4X@53G zdqnRFP@w~^cVnYviD-0>V5q0^f#3(Fz~>VolGOBg2{K1MxPTD<=}CF1Q}r_Y`IBUX zK=055tM~Xmuslf>OpINR@J1k?4%f&!TShkjALvFbGH^kd_@)dj!?y~?xrlG2Gx*`gCZe|W z3X+qc?bASp8QOY)dilyO8Ex5`MZsWVC(Xj?Yws_ot6^ zE&B#|`8(>dWh&x%1d9hP(Xzt6CrX=1uR>vYoM{z0p z;i#H0*vrikgJViZ>DNtjV07rMM;Et8FMT182!i^K1h@JGjanIz;nWUrhfP33BSXFWAaQ{f#TZ{m#FOE{fLbf%c84Qg0%@csIS|w7?*+0soE^oNQf4 z9=aTfx|QfQYL{{gYg1)ES~GJHp()4`h#at6MgyaQ?aFd6d!F_sbz0EcOuDofpWS_= zZ%(w2zyMMRZa%DnvD*i(-3Jfn(lKku3i@`Y5XK+iD5K9NFK-B*@VYynIwO zJ{C;rM_3;eqn}Jz(k<<{k3$^BKXqe)R==<9Y0v#KHAltW!_&3INo(CUhH)rlE33c! zJ@auSn&OE7TuCFu7@@KG=?-(J&Q*v-X%2VO0Dq-^h>xaLH$#=NTC*c!moxWiS?`41 zlCroUqq_Nwhkq7}Oz$vh>!MYTpD2>;dgZtEFM)*Xdai4}9h#W~!O(^rH7C-T&ENg7 zQ6KRSzTy2*pv_dF`giJq6U>(x@!)ba7f?WQWl@0on!x^Q+$TlhT1bSa6wOnoDJLt#z;0Uw^xUgIUfT206s8p;_sO? z@Mn7aUh@E1%Zw)3+q6F@uv!33-z;wP3MIO{VUuk5z;Z4>l(?Ckq|`!ih}5mzZG9ix z_aP2Y9YUd-oWy5uk{Tv(aFECu$WV8A8Ov1Z!h1sP@xctAvsqZb+@d{ql+WxEwMedF zBe7LKM4v~Yp$dk3sJal|5yy!q3=zD{WUKH22Srm+G<+5%P?_39^DxKX^!{t@i;u;+ zvyr{>>pD1dkbyJF+*8+yeKipxZKU(gMw1+Xnja>l2po(Oq)Q>iu98}qu$=`aE<5!$ zdL^n#b2Ivv&9Kq_ERkI(G7pUwUlDROBa}sS{b8Bvg!&lkMEU~RwPt3C8$BA6tx=G7 zF`-jl9M8g|LDJ6eWk%gd#F&u{Y;Z&R7%AeAnQj13RkQb-364DoJD>?<0%_K^#=PD! zC9=d43Wf{$1XP7G%%|S}Q5o;=ig&t|BOO@aEM+lN2ngC=vwQYo|49*aj0@m%2da5*Tr@ym*^- z&{zw9+#w|DWyARP{hN=B1g;G=%$d;~wYqu(9>pIkN0u5TSbeL)1C1E;fK}qfj_bJS zLiM&)9^$8*h^=A-~5OQ`c{BRh3PyrgoVzkKZ@;JM*tteo*uI#PU$C^5{O~MEjY2up*&`j>j#s<7LB~_I!-UdIndL+HWXB%W1<}sF z-gG2LF~qEdM* z(GpE@S55YHKq=ym`AS@MeL^oC?1dD?@e+LvCB@!?Y70h~HMQEc%Ju2360*^)mNw_L zx-uB}l)XL@<8mHEg{3_@YXJ&+a1A~@$Nl{(UF?l;jX5VqO`^1-Ow{whDN{vq&)3W@ z$J!wiJBjIls4~6E()%+JZ1!$NnRfMywblJD1xxZ>I;j4AUghjV`_b9&&$wrz^KUbd z@!Z$w>AU2@da7%N-%IrK1v2hnc}w;43sLTBBiKAD^=k{!?8r|lWDH}ufAQ)_zjW)O z6_?5D=ryLdF<`;Nk?d#FJ4(O9;Q%II+U3RV@nQx7Cgv|Lvx2zDdagc<_+Y$CzZCdR zzMFvgeejcO2F~_`avl!I3IWh(Li31{jk(#o1#=^S&a}^$s-yT~N<$&`f~4MFj-6%T!q9C>^{CYQyLRaOS7>x~ZNh4c3-sj)aB1*j<-azLD)DN}+Up#oy z(&-yRbP}_4!bSOJ#>{26;m0>^zf3-6KIMeO0x0_^zu?q@lrMet;4L%{i{#pMUqIPjeticY>~e zo&vCPXt)0aI?}nh8%+(^W!~cxPE%RHno1B6ihYZI$&uAeA%2~3k&!^zzmc#H&nxy2 zeUp%d9G5U}ALj0Va~{7!F^J_ghpW07c7ZZ-7h--`4x*16nT@CKpueHBq4}7#!=VHb zKWO?)c2~@Sx;zQg-xUJ^1N&(Zi~H^rejl(qCJ^!#G$%!}%l`vcg6XlkJN^<^K<8tk z_3{fz-IDBZ5m6NGn?+D>dvA-QMf#^;qmK9#dqSAj+0J>qW29vl=eJ1)q9M;wHH|qW zghK|TY{Ti-#pcIcR)^L{L8!DG(ge*5*`Hk~+v95N4XMXuTX5z@6@@J21Qn5=jV1tI zD^kPA1M3J9kbtiyPn>fg9xis&P$Evfom(T~dpr0?ctaS|3APZ&+-yh!;-N@0l{K1zS&-}Q5EkbI;y>rqP;_Lj_0KBo zKRaI<`x<|=ck^0A<$KnRu*}{w;mZZUap7VF{S`v=)Ey};VhDaOF{|byYSFP~2HhGK zHQUR%u~#+0fyj!e50=TH=vS0OHhWB~k^#BQ?fbr1NePS2ALoK~G34xN{h_&$xnz4t z4t%3{J|RSNhN?6=rP(=A>9dKPOJT{I!|2i{Xs33X zszeIK7HZEVzA>pbEg|@ZZizh3A$BjHVv2TvT}YhOxwIuVn@|oy9)jN{*U2?YK6d87 z%?~Xl=?7q7xWw(u8VrVB3$>f>PSa67qrXR#0P)VXWJbpFyy{Wj%FjXmd(vH)P6WdbHsvrer z1kfB8nq{X)8``ql@I_ryc|+T)1#tm+Hx2|dHAmon$FDtAQ$Z7(i6e3mcSy=1$K#k9 z-xM`gsd1hX{5ZyU%``VY<1i3^lortFkn>Sz%CZ*`xkJ=eySS#^x2JG6-e~BUG&GH1 z;Q9IsSl&jePUI5l>R6h!nD9!cMHMu6KY)Q?g>Tz(q0YvVeP~{&@|Z9uF)WqzL|p}r z0h6xB=k?|3X?KHw)34GKk1w@sTV#wtC~Hg|+3#HSKxgm(!*kU9lu_d;ie;6$6ab+S z-a%cSeL0na%B%XLXoasM6DyZq3x1oL%sdfQHhn%$O=kwzEu(6FF_B8|^_mh8z+`U7K z62sCS)W+%#IRXZ&!t@AUp7c`19AUr(K;h>Stp@rF^aX?mQs0v3)$PfUlo-k?l2|yA zfR^VBDY5DYrgF644ytu+Asom?tvki~hdJyCM`Rf6J&1@<3P}blcJU%Q+n@n$q~U(z z<~YJbS#DbepC`78STJuY=@ZZEMKwRFe5bEBEtrCfN zd;yS={h?iwQ(w{1AHvl42vo1H{zVR%?#K>(jsPz86@?2-GG+%L_+wk){7`Kivk#Xi zCrVDn|Ck0V$3r1Lj#8>Dk;u|M=@^1wn{%d;96UAc>6r$xtZz`+%=o!((RT?tp{js} zCPEIL zB>ETLbyG4=%AIw;W%;34IMBBijcB ze)k_uK)b%f_)dJg_bh?T@^Kotyq3 z0YdhrJgq3RDQ5nzaDLh)ya?5fdXA;ZjQkxl>E4GUYJXCb%e@#V+tvuGxnSp!m(SN% z1O@nJg;zyqSGKs(NpR7RH>=NdS1}b_i&)GE^t{TYa&(bC=;oOowm$0zO6@bj^~AiEB75 zC1tIkENTUFUsuCy^x4H)A}j~2a7@(-hlTLuq5y}^a{!owXbeBP@iUGa6hIugu;Z=jJb~X#MaB;7LhT@cs`Sp`#Q@!7v8h+DH&Zy!{<$7I%N~cM% zKBsby+Swe$tER~kr3_|P#Gw1a-gL#sC% zmaw1OtaEKqu$8dmnNseIoz8jym2@^rmjP_`;C3`)5u#;MBTzXd-crCUnkZ1f z1WZEzp!B)0K@9tVyH=^1G=oI%KW(ahRd1c+lygKep(0Ourj2h|Jkm2E9bLVrK++V5HAJf?;oe-ha-I5Go6n& zdIw8dZufF}D_CiMv24*W6T#ZW9&tJtZe%QDd;H)ewXaQOqQnt)30f<>R?FT^FTi}g z*TNrb%gkY`EYCfYn~o}^B39&P!W$LVq5@!VhwMVI)#oMcuR08#9ge-egS3h5BovEC z*0Fp{q(R%IB@i`h_QCuX&Cjqm!VJQCrPG<2Bp=4wF84}dSk)oc!16J6XkSvFQ9`z8 zl`wF6-DID`e%pj|Pj|AS0QGq-(bpnuRbfe&JMO@NNZyG%mOxoun$jd(U8SXs-U@)j z_?RtwNz_>t}PW+Gj3Zr2pZIVF>g4R9s z%)RO7x)%qvfHV-^qxSF?pA%*VCdiB6N3W>#qvG&8P)Y2MZ3Yb02`wuqme-W(^l32p zYLo@tx@h_^SUJm+W7{I13v&5SQV0PH!`$4Yi^+MzCZi3@NEoBKP2iTYVhkF^^h$L|Q+ zum))%tkucVya)NKrna-J8zctzxjakaK~@%x%r1qEt@a+^F03U?C$yi*hU^`9<2Lr`?i3l&?HAGz7( z6&Ed;JPfy&_2)I~@XI1;Rw}*01SoLKFP==sq?l!#Y$ibB5%VXirBc81!e?#0c}?7> zedFc~`3>DTNZ;KQt~O7(nzE+&v&u?G+V}pt&l>t$+xl=e-4o4@1s<(-fbQgF;X04V z`y)yZ6pFdv_Gr=*Ocy;z z0=2>18a}LsDC3va+dK6~!We}M^Y^8xS8$n90g1aPDojHWVrDvuN)hskwz#3yUS+H5g(rlxv-(-!Bfj0lSWX}Xj98m3t)*^;__bRSp2N7 z-Z>nv&n4@ijcYfPL+%yo{miOiIBEsOy{4CY{}GXSP@lO4(?M9?VbImSAJ)F?`D%!| zeOQ#83tY>Nv0=nsTb{E3LM6%3Y%m@D3;tya34sX0WI&+@=278GA}4n1T~^a4A^?(_raJ_{}?MX$Sv=7S0Ba z0%uK*#aOQ66#a+_bT;&ysgd2ulie%n`9yj|)~S_?u=WM>>IEBwN@vi7Tkiq?wkuR% z6tsT~opS`t`U`lW0D@jNk02+Hpo?Ohd{o{-i00HsR<- z^v^jcBVp}k1~QwW&NR`75)vqhecTpjnEkaQ4uhg+0{7uLEGYa2ggM8cGoHq1)gDx~ zw<=*15)vRFd?cTthKxq*(e%4~#00M;g8)arsD-2O01LoUm|_t*t5=6>k%*OIw|PuZ zy1|v#Bc2+pA|wo16SEL#sf3z0xL(Ufn`*9%xZsF{QF(%+Ayoj&-&{>nM0_+pTD+};8-N!r4NC19cz=c}p28w4f07Vyx ze>3*QAsZ_j+%|c52ngOMes}nQ!Hc558S2qVe+Qgi#D$s@`eg`h3GX*U@CDOtRp6*v zz)8VR`*d0atj_(P4vMe8y-EWEyupB{EglmG1K5D;OSr#z|H)vUyo?LgA@!?`ss$Lp zpat096n+v{17CtQP-TBti$-83X0SgsQO;~*R{>?lQHOz z?dMenvU_rs{o)V$=R*C(AM}qhh5dh(|7H{V_jT}ZHle?~mIUknzh-{t76LpW7y7q{ ze{+-kXKW%uD!TJPbT=^#mUgWj2xGrMB2y?p8D;$c0G~`~ zJ^`MO{|O`jccb1E6_nKcFG0Qz39x<&_P4Hl@*?+%4Xu@5kjp9Z-_-wj(e(2@69feP q6ZL0nf2zY#OM6?Id$>FO$pWON2m}64@v~`s5II=j+x)@LZ~p`NUfc5k delta 36991 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4b7e1f3..3fa8f86 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 8e25e6c..1aa94a4 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,111 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # 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 +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac 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" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,92 +130,120 @@ 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. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + 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 fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "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 +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac 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 +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# 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"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # 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\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg 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 -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 24467a1..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,10 +25,14 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @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="-Xmx64m" "-Xms64m" @@ -37,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -51,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -61,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_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=%* - :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% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 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 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From 3f9a106fdf6573b1cd1b785be4e0d46fb1fa824d Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Tue, 17 Oct 2023 03:22:07 +0200 Subject: [PATCH 23/32] Setup java 17 in CI --- .github/workflows/debug_build.yml | 5 ++ .../java/com/termux/boot/BootJobService.java | 51 ------------------- 2 files changed, 5 insertions(+), 51 deletions(-) delete mode 100644 app/src/main/java/com/termux/boot/BootJobService.java diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml index 90ae830..3bfc69e 100644 --- a/.github/workflows/debug_build.yml +++ b/.github/workflows/debug_build.yml @@ -8,6 +8,11 @@ jobs: steps: - name: Clone repository uses: actions/checkout@v4 + - name: Setup java 17 as required by gradle + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' - name: Build run: | ./gradlew assembleDebug diff --git a/app/src/main/java/com/termux/boot/BootJobService.java b/app/src/main/java/com/termux/boot/BootJobService.java deleted file mode 100644 index 55474d2..0000000 --- a/app/src/main/java/com/termux/boot/BootJobService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.termux.boot; - -import android.app.job.JobParameters; -import android.app.job.JobService; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.Build; -import android.os.PersistableBundle; -import android.util.Log; - -public class BootJobService extends JobService { - - public static final String SCRIPT_FILE_PATH = "com.termux.boot.script_path"; - - private static final String TAG = "termux"; - - // Constants from TermuxService. - private static final String TERMUX_SERVICE = "com.termux.app.TermuxService"; - private static final String ACTION_EXECUTE = "com.termux.service_execute"; - private static final String EXTRA_EXECUTE_IN_BACKGROUND = "com.termux.execute.background"; - - @Override - public boolean onStartJob(JobParameters params) { - Log.i(TAG, "Executing job " + params.getJobId() + "."); - - PersistableBundle extras = params.getExtras(); - String filePath = extras.getString(SCRIPT_FILE_PATH); - - Uri scriptUri = new Uri.Builder().scheme("com.termux.file").path(filePath).build(); - Intent executeIntent = new Intent(ACTION_EXECUTE, scriptUri); - executeIntent.setClassName("com.termux", TERMUX_SERVICE); - executeIntent.putExtra(EXTRA_EXECUTE_IN_BACKGROUND, true); - - Context context = getApplicationContext(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - // https://developer.android.com/about/versions/oreo/background.html - context.startForegroundService(executeIntent); - } else { - context.startService(executeIntent); - } - - return false; // offloaded to Termux; job is done - } - - @Override - public boolean onStopJob(JobParameters params) { - Log.i(TAG, "Execution of job " + params.getJobId() + " has been cancelled."); - return false; // do not reschedule - } -} From e7d2abd1a762a63f36b2f713b3460fd5885c5395 Mon Sep 17 00:00:00 2001 From: Fredrik Fornwall Date: Tue, 17 Oct 2023 03:28:31 +0200 Subject: [PATCH 24/32] Add back BootJobService --- .../java/com/termux/boot/BootJobService.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 app/src/main/java/com/termux/boot/BootJobService.java diff --git a/app/src/main/java/com/termux/boot/BootJobService.java b/app/src/main/java/com/termux/boot/BootJobService.java new file mode 100644 index 0000000..55474d2 --- /dev/null +++ b/app/src/main/java/com/termux/boot/BootJobService.java @@ -0,0 +1,51 @@ +package com.termux.boot; + +import android.app.job.JobParameters; +import android.app.job.JobService; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.PersistableBundle; +import android.util.Log; + +public class BootJobService extends JobService { + + public static final String SCRIPT_FILE_PATH = "com.termux.boot.script_path"; + + private static final String TAG = "termux"; + + // Constants from TermuxService. + private static final String TERMUX_SERVICE = "com.termux.app.TermuxService"; + private static final String ACTION_EXECUTE = "com.termux.service_execute"; + private static final String EXTRA_EXECUTE_IN_BACKGROUND = "com.termux.execute.background"; + + @Override + public boolean onStartJob(JobParameters params) { + Log.i(TAG, "Executing job " + params.getJobId() + "."); + + PersistableBundle extras = params.getExtras(); + String filePath = extras.getString(SCRIPT_FILE_PATH); + + Uri scriptUri = new Uri.Builder().scheme("com.termux.file").path(filePath).build(); + Intent executeIntent = new Intent(ACTION_EXECUTE, scriptUri); + executeIntent.setClassName("com.termux", TERMUX_SERVICE); + executeIntent.putExtra(EXTRA_EXECUTE_IN_BACKGROUND, true); + + Context context = getApplicationContext(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + // https://developer.android.com/about/versions/oreo/background.html + context.startForegroundService(executeIntent); + } else { + context.startService(executeIntent); + } + + return false; // offloaded to Termux; job is done + } + + @Override + public boolean onStopJob(JobParameters params) { + Log.i(TAG, "Execution of job " + params.getJobId() + " has been cancelled."); + return false; // do not reschedule + } +} From 6f3fa43fe950c5a2d1a188312a53c11265ee6bfe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 15:28:01 +0000 Subject: [PATCH 25/32] Bump actions/setup-java from 3 to 4 (#176) --- .github/workflows/debug_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml index 3bfc69e..24a5754 100644 --- a/.github/workflows/debug_build.yml +++ b/.github/workflows/debug_build.yml @@ -9,7 +9,7 @@ jobs: - name: Clone repository uses: actions/checkout@v4 - name: Setup java 17 as required by gradle - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: distribution: 'temurin' java-version: '17' From 809e42932ccb7001a5e3a6485428b87e6a04b42c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jan 2024 15:28:19 +0000 Subject: [PATCH 26/32] Bump actions/upload-artifact from 3 to 4 (#177) --- .github/workflows/debug_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml index 24a5754..67b5a98 100644 --- a/.github/workflows/debug_build.yml +++ b/.github/workflows/debug_build.yml @@ -17,7 +17,7 @@ jobs: run: | ./gradlew assembleDebug - name: Store generated APK file - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: termux-boot path: ./app/build/outputs/apk/debug/app-debug.apk From fd04a4c5ef14ab4b4b747238484cbd474a07e9dd Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Mon, 15 Apr 2024 22:29:57 +0500 Subject: [PATCH 27/32] Added: Add `gradle.properties` file for `minSdkVersion`, `targetSdkVersion` and `compileSdkVersion` properties --- app/build.gradle | 7 ++++--- gradle.properties | 5 ++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 5b2e2f1..9a12876 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,11 +3,12 @@ apply plugin: 'com.android.application' android { namespace "com.termux.boot" + compileSdkVersion project.properties.compileSdkVersion.toInteger() + defaultConfig { applicationId "com.termux.boot" - minSdkVersion 21 - targetSdkVersion 28 - compileSdk 34 + minSdkVersion project.properties.minSdkVersion.toInteger() + targetSdkVersion project.properties.targetSdkVersion.toInteger() versionCode 7 versionName "0.7" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" diff --git a/gradle.properties b/gradle.properties index 6f28211..09ff688 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,7 +9,6 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# suppress inspection "UnusedProperty" org.gradle.jvmargs=-Xmx1536m # When configured, Gradle will run in incubating parallel mode. @@ -18,3 +17,7 @@ org.gradle.jvmargs=-Xmx1536m # org.gradle.parallel=true android.useAndroidX=true + +minSdkVersion=21 +targetSdkVersion=28 +compileSdkVersion=34 From 16557303c94c4cadafda3dd18574781a1469a56c Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Wed, 17 Apr 2024 23:08:51 +0500 Subject: [PATCH 28/32] Changed: Bump gradle to `8.5` and android gradle plugin to `8.3.2` --- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 53213c3..6deee41 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.1.2' + classpath "com.android.tools.build:gradle:8.3.2" } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3fa8f86..e6aba25 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From f26515ea7762adad5b5afd100e3c166b88414221 Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Wed, 17 Apr 2024 23:29:41 +0500 Subject: [PATCH 29/32] Changed: Rename `minSdkVersion` to `minSdk`, `targetSdkVersion` to `targetSdk` and `compileSdkVersion` to `compileSdk` in `build.gradle` files `compileSdkVersion` was deprecated in Android gradle plugin (`AGP`) version `>= 7.2.0` in favour of `compileSdk`, so replace `Version` suffix from other related variables as well to be consistent. - https://developer.android.com/reference/tools/gradle-api/7.2/com/android/build/api/dsl/CommonExtension#compileSdkVersion(kotlin.Int) --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 9a12876..3ef84f8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,12 +3,12 @@ apply plugin: 'com.android.application' android { namespace "com.termux.boot" - compileSdkVersion project.properties.compileSdkVersion.toInteger() + compileSdk project.properties.compileSdkVersion.toInteger() defaultConfig { applicationId "com.termux.boot" - minSdkVersion project.properties.minSdkVersion.toInteger() - targetSdkVersion project.properties.targetSdkVersion.toInteger() + minSdk project.properties.minSdkVersion.toInteger() + targetSdk project.properties.targetSdkVersion.toInteger() versionCode 7 versionName "0.7" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" From c2780dd85531ed42c1bf94f9e97b81f46e0e4cf1 Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Thu, 18 Apr 2024 01:23:56 +0500 Subject: [PATCH 30/32] Added|Changed: Add `github_release_build` workflow to attach APKs for GitHub release builds, and update `github_action_build` (previously `debug_build`) workflow and `app/build.gradle` to use semantic versioning for app version and add commit hash and `github` to APK file names The `versionName` will now follow semantic version `2.0.0` spec in the format `major.minor.patch(-prerelease)(+buildmetadata)`. This will make versioning the prerelease and github debug builds versions easier and follow a spec. The @termux devs should make sure that when bumping `versionName` in `build.gradle` file and when creating a tag for new releases on github that they include the patch number as well, like `v0.1.0` instead of just `v0.1`. The `build.gradle` file and `attach_debug_apks_to_release` workflow will now validate the version as well and the build/attachment will fail if `versionName` does not follow the spec. https://semver.org/spec/v2.0.0.html APKs released on github for debug build workflows and releases are now referred as `Github` releases as per termux/termux-app@7b10a35f and termux/termux-app@94e01d68, so APK filenames have been modified to include `github` in the filename. The APKs are still debuggable, so that tag remains too. For github workflows the apk filename format will be `termux-boot_+.github.debug_.apk`, like `termux-boot_v0.1.0+xxxxxxxx.github.debug_arm64-v8a.apk` and for github releases it will be `termux-boot_+github.debug_.apk`, like `termux-boot_v0.1.0+github.debug_arm64-v8a.apk`. The `last_commit_hash` will be the first `8` characters of the commit hash. The `.github.debug` will act as `buildmetadata` and will not affect versioning precedence. The dot `.` is used as tags separator instead of dash `-` for `github` release source and `debug` build type in the apk version tag to be consistent with semver build metadata tags. For example `github-debug` will now be `github.debug`. https://semver.org/#spec-item-10 For github workflows triggered by `push` and `pull_request` triggers, `+` will be used as new `versionName`, like `v0.1.0+xxxxxxxx`. This will make tracking which build a user is using easier and help in resolving issues as well. The `app/build.gradle` now also supports following `TERMUX_BOOT_APP_BUILD__` scoped environmental variables. - `TERMUX_BOOT_APP_BUILD__APP_VERSION_NAME` will be used as `versionName` if its set. - `TERMUX_BOOT_APP_BUILD__APK_VERSION_TAG` will be used as `termux-boot_.apk` if its set. --- .github/workflows/debug_build.yml | 23 ------- .github/workflows/github_action_build.yml | 77 +++++++++++++++++++++++ README.md | 2 +- app/build.gradle | 32 ++++++++-- 4 files changed, 105 insertions(+), 29 deletions(-) delete mode 100644 .github/workflows/debug_build.yml create mode 100644 .github/workflows/github_action_build.yml diff --git a/.github/workflows/debug_build.yml b/.github/workflows/debug_build.yml deleted file mode 100644 index 67b5a98..0000000 --- a/.github/workflows/debug_build.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Build - -on: push - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Clone repository - uses: actions/checkout@v4 - - name: Setup java 17 as required by gradle - uses: actions/setup-java@v4 - with: - distribution: 'temurin' - java-version: '17' - - name: Build - run: | - ./gradlew assembleDebug - - name: Store generated APK file - uses: actions/upload-artifact@v4 - with: - name: termux-boot - path: ./app/build/outputs/apk/debug/app-debug.apk diff --git a/.github/workflows/github_action_build.yml b/.github/workflows/github_action_build.yml new file mode 100644 index 0000000..ec8bdb7 --- /dev/null +++ b/.github/workflows/github_action_build.yml @@ -0,0 +1,77 @@ +name: GitHub Action Build + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Build + shell: bash {0} + run: | + exit_on_error() { echo "$1"; exit 1; } + + if [ -z "$JAVA_HOME_17_X64" ] || [ ! -f "$JAVA_HOME_17_X64/bin/javac" ] || [ ! -x "$JAVA_HOME_17_X64/bin/javac" ]; then + exit_on_error "jdk-17 binary not found at path '$JAVA_HOME_17_X64/bin/javac' or is not executable." + fi + + echo "Setting vars" + + if [ "$GITHUB_EVENT_NAME" == "pull_request" ]; then + GITHUB_SHA="${{ github.event.pull_request.head.sha }}" # Do not use last merge commit set in GITHUB_SHA + fi + + # Set RELEASE_VERSION_NAME to "+" + CURRENT_VERSION_NAME_REGEX='\s+versionName "([^"]+)"$' + CURRENT_VERSION_NAME="$(grep -m 1 -E "$CURRENT_VERSION_NAME_REGEX" ./app/build.gradle | sed -r "s/$CURRENT_VERSION_NAME_REGEX/\1/")" + RELEASE_VERSION_NAME="v$CURRENT_VERSION_NAME+${GITHUB_SHA:0:7}" # The "+" is necessary so that versioning precedence is not affected + if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then + exit_on_error "The release version '${RELEASE_VERSION_NAME/v/}' generated from current version '$CURRENT_VERSION_NAME' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html." + fi + + APK_DIR_PATH="./app/build/outputs/apk/debug" + APK_VERSION_TAG="$RELEASE_VERSION_NAME.github.debug" # Note the ".", GITHUB_SHA will already have "+" before it + APK_BASENAME_PREFIX="termux-boot_$APK_VERSION_TAG" + + # Used by upload step later + echo "APK_DIR_PATH=$APK_DIR_PATH" >> $GITHUB_ENV + echo "APK_VERSION_TAG=$APK_VERSION_TAG" >> $GITHUB_ENV + echo "APK_BASENAME_PREFIX=$APK_BASENAME_PREFIX" >> $GITHUB_ENV + + echo "Building APK file for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag" + export TERMUX_BOOT_APP_BUILD__APP_VERSION_NAME="${RELEASE_VERSION_NAME/v/}" # Used by app/build.gradle + export TERMUX_BOOT_APP_BUILD__APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle + export GRADLE_OPTS="-Dorg.gradle.java.home=$JAVA_HOME_17_X64" + if ! ./gradlew assembleDebug; then + exit_on_error "Build failed for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag." + fi + + echo "Validating APK file" + if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then + files_found="$(ls "$APK_DIR_PATH")" + exit_on_error "Failed to find built APK file at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found" + fi + + echo "Generating checksums-sha256.txt file" + if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > checksums-sha256.txt); then + exit_on_error "Generate checksums-sha256.txt file failed for '$RELEASE_VERSION_NAME' release." + fi + echo "checksums-sha256.txt:"$'\n```\n'"$(cat "$APK_DIR_PATH/checksums-sha256.txt")"$'\n```' + + - name: Upload files to action + uses: actions/upload-artifact@v4 + with: + name: ${{ env.APK_BASENAME_PREFIX }} + path: | + ${{ env.APK_DIR_PATH }}/${{ env.APK_BASENAME_PREFIX }}.apk + ${{ env.APK_DIR_PATH }}/checksums-sha256.txt + ${{ env.APK_DIR_PATH }}/output-metadata.json diff --git a/README.md b/README.md index 9963f97..1dbe461 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Termux:Boot application can be obtained from [F-Droid](https://f-droid.org/en/pa Additionally we provide per-commit debug builds for those who want to try out the latest features or test their pull request. This build can be obtained -from one of the workflow runs listed on [Github Actions](https://github.com/termux/termux-boot/actions) +from one of the workflow runs listed on [Github Actions](https://github.com/termux/termux-boot/actions/workflows/github_action_build.yml?query=branch%3Amaster+event%3Apush) page. Signature keys of all offered builds are different. Before you switch the diff --git a/app/build.gradle b/app/build.gradle index 3ef84f8..04d315f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -5,13 +5,18 @@ android { compileSdk project.properties.compileSdkVersion.toInteger() + def appVersionName = System.getenv("TERMUX_BOOT_APP_BUILD__APP_VERSION_NAME") ?: "" + def apkVersionTag = System.getenv("TERMUX_BOOT_APP_BUILD__APK_VERSION_TAG") ?: "" + defaultConfig { applicationId "com.termux.boot" minSdk project.properties.minSdkVersion.toInteger() targetSdk project.properties.targetSdkVersion.toInteger() versionCode 7 - versionName "0.7" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + versionName "0.7.0" + + if (appVersionName) versionName = appVersionName + validateVersionName(versionName) } signingConfigs { @@ -39,6 +44,16 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + + applicationVariants.all { variant -> + variant.outputs.all { output -> + if (variant.buildType.name == "debug") { + outputFileName = new File("termux-boot_" + (apkVersionTag ? apkVersionTag : "debug") + ".apk") + } else if (variant.buildType.name == "release") { + outputFileName = new File("termux-boot_" + (apkVersionTag ? apkVersionTag : "release") + ".apk") + } + } + } } dependencies { @@ -46,7 +61,14 @@ dependencies { } task versionName { - doLast { - print android.defaultConfig.versionName - } + doLast { + print android.defaultConfig.versionName + } +} + +def validateVersionName(String versionName) { + // https://semver.org/spec/v2.0.0.html#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + // ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ + if (!java.util.regex.Pattern.matches("^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?\$", versionName)) + throw new GradleException("The versionName '" + versionName + "' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html.") } From db207340032464cfbac77399a97208880bf25912 Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Wed, 17 Apr 2024 23:40:52 +0500 Subject: [PATCH 31/32] Added: Add `workflow_dispatch` and `cron` schedule for "00:15 on 1st of every 2nd month" to `github_action_build` workflow triggers - `workflow_dispatch` can be used to manually trigger a build, in case action run was deleted or artifacts get expired. - `cron` is scheduled to be run every 2nd month (`~60` days) because artifacts expire after `90` days by default, and there is no easy way to set `89` days from now/start of year or ideally last commit, and some months have 28 or 31 days, which would make it even harder. Additionally, workflow should get triggered based on `cron` schedule regardless of last push time, so multiple action runs may exist for every commit anyways, so using 2nd month shouldn't be an issue. - `cron` is scheduled to be run on the 15th minute to reduce chances of workflow getting dropped. If it does get dropped, then `workflow_dispatch` can be used. > The schedule event can be delayed during periods of high loads of GitHub Actions workflow runs. High load times include the start of every hour. If the load is sufficiently high enough, some queued jobs may be dropped. To decrease the chance of delay, schedule your workflow to run at a different time of the hour. - https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule The idea for using `cron` to trigger rebuild when artifacts were expected to expire was suggested by @twaik in #199, but it was meant to trigger every 3rd month instead of every 2nd month that is currently being used. Co-authored-by: @twaik Co-authored-by: @agnostic-apollo --- .github/workflows/github_action_build.yml | 3 + .github/workflows/github_release_build.yml | 69 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 .github/workflows/github_release_build.yml diff --git a/.github/workflows/github_action_build.yml b/.github/workflows/github_action_build.yml index ec8bdb7..f5c96d3 100644 --- a/.github/workflows/github_action_build.yml +++ b/.github/workflows/github_action_build.yml @@ -7,6 +7,9 @@ on: pull_request: branches: - master + schedule: + - cron: "15 0 1 */2 *" + workflow_dispatch: jobs: build: diff --git a/.github/workflows/github_release_build.yml b/.github/workflows/github_release_build.yml new file mode 100644 index 0000000..19fbbf5 --- /dev/null +++ b/.github/workflows/github_release_build.yml @@ -0,0 +1,69 @@ +name: GitHub Release Build + +on: + release: + types: + - published + +jobs: + build: + runs-on: ubuntu-latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + ref: ${{ env.GITHUB_REF }} + + - name: Build and upload files to release + shell: bash {0} + run: | + exit_on_error() { + echo "$1" + echo "Deleting '$RELEASE_VERSION_NAME' release and '$GITHUB_REF' tag" + hub release delete "$RELEASE_VERSION_NAME" + git push --delete origin "$GITHUB_REF" + exit 1 + } + + if [ -z "$JAVA_HOME_17_X64" ] || [ ! -f "$JAVA_HOME_17_X64/bin/javac" ] || [ ! -x "$JAVA_HOME_17_X64/bin/javac" ]; then + exit_on_error "jdk-17 binary not found at path '$JAVA_HOME_17_X64/bin/javac' or is not executable." + fi + + echo "Setting vars" + RELEASE_VERSION_NAME="${GITHUB_REF/refs\/tags\//}" + if ! printf "%s" "${RELEASE_VERSION_NAME/v/}" | grep -qP '^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'; then + exit_on_error "The release version '${RELEASE_VERSION_NAME/v/}' is not a valid version as per semantic version '2.0.0' spec in the format 'major.minor.patch(-prerelease)(+buildmetadata)'. https://semver.org/spec/v2.0.0.html." + fi + + APK_DIR_PATH="./app/build/outputs/apk/debug" + APK_VERSION_TAG="$RELEASE_VERSION_NAME+github.debug" + APK_BASENAME_PREFIX="termux-boot_$APK_VERSION_TAG" + + echo "Building APK file for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag" + export TERMUX_BOOT_APP_BUILD__APK_VERSION_TAG="$APK_VERSION_TAG" # Used by app/build.gradle + export GRADLE_OPTS="-Dorg.gradle.java.home=$JAVA_HOME_17_X64" + if ! ./gradlew assembleDebug; then + exit_on_error "Build failed for '$RELEASE_VERSION_NAME' release with '$APK_VERSION_TAG' tag." + fi + + echo "Validating APK file" + if ! test -f "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk"; then + files_found="$(ls "$APK_DIR_PATH")" + exit_on_error "Failed to find built APK file at '$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk'. Files found: "$'\n'"$files_found" + fi + + echo "Generating checksums-sha256.txt file" + if ! (cd "$APK_DIR_PATH"; sha256sum "${APK_BASENAME_PREFIX}.apk" > checksums-sha256.txt); then + exit_on_error "Generate checksums-sha256.txt file failed for '$RELEASE_VERSION_NAME' release." + fi + echo "checksums-sha256.txt:"$'\n```\n'"$(cat "$APK_DIR_PATH/checksums-sha256.txt")"$'\n```' + + echo "Uploading files to release" + if ! gh release upload "$RELEASE_VERSION_NAME" \ + "$APK_DIR_PATH/${APK_BASENAME_PREFIX}.apk" \ + "$APK_DIR_PATH/checksums-sha256.txt" \ + ; then + exit_on_error "Upload files to release failed for '$RELEASE_VERSION_NAME' release." + fi From ef1f272a4512102977b112eda8e3e0d8fa481cfc Mon Sep 17 00:00:00 2001 From: agnostic-apollo Date: Wed, 17 Apr 2024 23:50:37 +0500 Subject: [PATCH 32/32] Release: 0.8.0 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 04d315f..e98e735 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -12,8 +12,8 @@ android { applicationId "com.termux.boot" minSdk project.properties.minSdkVersion.toInteger() targetSdk project.properties.targetSdkVersion.toInteger() - versionCode 7 - versionName "0.7.0" + versionCode 8 + versionName "0.8.0" if (appVersionName) versionName = appVersionName validateVersionName(versionName)