From d3df6cb7124fb3f6786b0672e4ff3ea123e4491b Mon Sep 17 00:00:00 2001 From: Nathaniel van Diepen Date: Wed, 8 May 2024 13:30:15 -0600 Subject: [PATCH] Add support for limiting packages to OS versions (#759) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Port 3.11 and c-string fixes from toltecmk - Add rmallos2, rmallos3, rm1os2, rm1os3, rm2os2, and rm2os3 archs for limiting packages to only supporting those versions - Update documentation - Update known issues packages to only be for 2.x - Make toltec-base generate a package for each arch to make sure that the folders always get created - Added experimental toltec branch for testing purposes. You need to add the experimental tag to a PR, and it will start applying changes to the experimental branch. - Fix various issues with the install and reenable process - Update toltecctl output to use the same logging as bootstrap --------- Co-authored-by: Mattéo Delabre <1370040+matteodelabre@users.noreply.github.com> Co-authored-by: Mattéo Delabre --- .github/actions/setup/action.yml | 2 +- .github/actions/sync-repository/action.yml | 2 +- .github/workflows/pr.yml | 12 + docs/package.md | 16 +- package/Compatibility | 70 +++ package/ddvk-hacks/package | 112 ++-- package/fuse/package | 12 +- package/kernelctl/package | 6 +- package/signature-rm/package | 15 +- package/templatectl/package | 4 +- package/toltec-base/package | 54 +- package/toltec-bootstrap/package | 20 +- package/toltec-bootstrap/toltecctl | 581 ++++++++++++++++++++- package/toltec-completion/_toltecctl | 2 +- package/toltec-completion/package | 2 +- package/toltec-deletions/package | 28 + package/webinterface-onboot/package | 23 +- package/webinterface-upload-button/package | 15 +- package/wireguard/package | 4 +- requirements.txt | 38 +- scripts/bootstrap/bootstrap | 25 +- scripts/install-lib | 2 +- scripts/repo_build.py | 1 + scripts/toltec/bash.py | 43 +- scripts/toltec/builder.py | 7 +- scripts/toltec/repo.py | 16 +- 26 files changed, 896 insertions(+), 216 deletions(-) create mode 100644 package/Compatibility create mode 100644 package/toltec-deletions/package diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index f10600cf6..d139dbd2f 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -70,7 +70,7 @@ runs: - name: Setup Python uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version: '3.11' - name: Cache Python environment uses: actions/cache@v3 id: cache-python diff --git a/.github/actions/sync-repository/action.yml b/.github/actions/sync-repository/action.yml index 7a213bfe0..01b7aa50a 100644 --- a/.github/actions/sync-repository/action.yml +++ b/.github/actions/sync-repository/action.yml @@ -28,7 +28,7 @@ runs: echo '${{ inputs.ssh-key }}' > private/id_rsa echo '${{ inputs.ssh-known-hosts }}' > private/known_hosts chmod 600 private/* - rsync --archive --verbose --compress --delete \ + rsync --archive --verbose --compress --delete --hard-links \ -e "ssh -p ${{ inputs.ssh-port }} -i private/id_rsa -o UserKnownHostsFile=private/known_hosts" \ '${{ inputs.local-path }}' \ '${{ inputs.remote-path }}' diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7968bff0e..a0dbca99c 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -30,3 +30,15 @@ jobs: with: name: repo path: build/repo + - name: Build packages for experimental + if: ${{ contains(github.event.pull_request.labels.*.name, 'experimental') }} + run: make repo FLAGS='--remote-repo https://toltec-dev.org/${{ github.base_ref }}' + - name: Sync packages with the remote repository + if: ${{ contains(github.event.pull_request.labels.*.name, 'experimental') }} + uses: ./.github/actions/sync-repository + with: + local-path: build/repo/ + ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} + ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }} + ssh-port: ${{ secrets.SSH_PORT }} + remote-path: ${{ secrets.REMOTE_SSH }}:/srv/toltec/experimental diff --git a/docs/package.md b/docs/package.md index 72a9bdca8..bdaf7807a 100644 --- a/docs/package.md +++ b/docs/package.md @@ -38,11 +38,17 @@ You can also declare custom variables to reduce repetition but make sure to pref The list of devices that are compatible with this package. The following values are accepted: -Name | Meaning ---------|------------------------------------------------------------------------- -`rmall` | Packages which work on all reMarkable devices without modification. -`rm1` | Packages requiring reMarkable 1-specific resources or compilation flags. -`rm2` | Packages requiring reMarkable 2-specific resources or compilation flags. +Name | Meaning +------------|------------------------------------------------------------------------- +`rmall` | Packages which work on all reMarkable devices without modification. +`rm1` | Packages requiring reMarkable 1-specific resources or compilation flags. +`rm2` | Packages requiring reMarkable 2-specific resources or compilation flags. +`rmallos2` | Packages which work on all reMarkable devices without modification, but only on the 2.x series of operating system. +`rm1os2` | Packages requiring reMarkable 1-specific resources or compilation flags, but only on the 2.x series of operating system. +`rm2os2` | Packages requiring reMarkable 2-specific resources or compilation flags, but only on the 2.x series of operating system. +`rmallos3` | Packages which work on all reMarkable devices without modification, but only on the 3.x series of operating system. +`rm1os3` | Packages requiring reMarkable 1-specific resources or compilation flags, but only on the 3.x series of operating system. +`rm2os3` | Packages requiring reMarkable 2-specific resources or compilation flags, but only on the 3.x series of operating system. For example, use `archs=(rm1)` for a package that only works on reMarkable 1, or `archs=(rm1 rm2)` for a package that works both on reMarkable 1 and reMarkable 2 but needs different dependencies or compilation flags for each of those. diff --git a/package/Compatibility b/package/Compatibility new file mode 100644 index 000000000..cf3ac4c40 --- /dev/null +++ b/package/Compatibility @@ -0,0 +1,70 @@ +rm1=2.6.1.71 +rm1=2.6.2.75 +rm1=2.7.0.9 +rm1=2.7.0.30 +rm1=2.7.0.36 +rm1=2.7.0.44 +rm1=2.7.0.51 +rm1=2.8.0.81 +rm1=2.8.0.86 +rm1=2.8.0.98 +rm1=2.9.0.153 +rm1=2.9.0.204 +rm1=2.9.0.210 +rm1=2.9.1.217 +rm1=2.9.1.236 +rm1=2.10.2.356 +rm1=2.10.3.379 +rm1=2.11.0.442 +rm1=2.12.1.527 +rm1=2.12.2.573 +rm1=2.12.3.606 +rm1=2.13.0.758 +rm1=2.14.0.861 +rm1=2.14.1.866 +rm1=2.14.3.958 +rm1=2.14.3.977 +rm1=2.14.3.1005 +rm1=2.14.3.1047 +rm1=2.15.0.1067 +rm1=2.15.1.1189 +rm1=3.0.4.1305 +rm1=3.2.2.1581 +rm1=3.2.3.1595 +rm1=3.3.2.1666 + +rm2=2.6.1.71 +rm2=2.6.2.75 +rm2=2.7.0.9 +rm2=2.7.0.30 +rm2=2.7.0.36 +rm2=2.7.0.44 +rm2=2.7.0.51 +rm2=2.7.1.53 +rm2=2.8.0.81 +rm2=2.8.0.86 +rm2=2.8.0.98 +rm2=2.9.0.153 +rm2=2.9.0.204 +rm2=2.9.0.210 +rm2=2.9.1.217 +rm2=2.9.1.236 +rm2=2.10.2.356 +rm2=2.10.3.379 +rm2=2.11.0.442 +rm2=2.12.1.527 +rm2=2.12.2.573 +rm2=2.12.3.606 +rm2=2.13.0.758 +rm2=2.14.0.861 +rm2=2.14.1.866 +rm2=2.14.3.958 +rm2=2.14.3.977 +rm2=2.14.3.1005 +rm2=2.14.3.1047 +rm2=2.15.0.1067 +rm2=2.15.1.1189 +rm2=3.0.4.1305 +rm2=3.2.2.1581 +rm2=3.2.3.1595 +rm2=3.3.2.1666 diff --git a/package/ddvk-hacks/package b/package/ddvk-hacks/package index 70423edd9..edf8b1f12 100644 --- a/package/ddvk-hacks/package +++ b/package/ddvk-hacks/package @@ -2,11 +2,11 @@ # Copyright (c) 2021 The Toltec Contributors # SPDX-License-Identifier: MIT -archs=(rm1 rm2) +archs=(rm1os2 rm2os2) pkgnames=(ddvk-hacks) pkgdesc="Enhance Xochitl with additional features" url=https://github.com/ddvk/remarkable-hacks -pkgver=39.01-2 +pkgver=39.01-4 timestamp=2022-11-09T18:31:51Z section="readers" maintainer="Mattéo Delabre " @@ -20,55 +20,58 @@ sha256sums=(d3b1413bb9219804581afab598e7f5308233e7467d64e8084e67aae7346beaba) _patches_dir="/opt/share/ddvk-hacks" _xochitl_path="/usr/bin/xochitl" _work_dir="/home/root/.local/share/ddvk-hacks" +_info_path="$_work_dir/xochitl.info" _backup_path="$_work_dir/xochitl.backup" _old_backup_path="$_backup_path.old" _patched_path="$_work_dir/xochitl.patched" package() { - if [[ $arch = rm1 ]]; then - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/26171_rm1/patch_19.1.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/26275_rm1/patch_20.1.03 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/27051_rm1/patch_21.1.04 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/28098_rm1/patch_23.1.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/291236_rm1/patch_24.1.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2100324_rm1/patch_25.1.03 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2102356_rm1/patch_27.1.03 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2103379_rm1/patch_28.1.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2110442_rm1/patch_29.1.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2121527_rm1/patch_30.1.08 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2122573_rm1/patch_31.1.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2123606_rm1/patch_32.1.03 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2140861_rm1/patch_34.1.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2141866_rm1/patch_35.1.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2143977_rm1/patch_36.1.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/21431047_rm1/patch_37.1.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/21501067_rm1/patch_38.1.03 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/21511189_rm1/patch_39.1.01 - elif [[ $arch = rm2 ]]; then - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/26171_rm2/patch_19.2.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/26275_rm2/patch_20.2.03 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/27051_rm2/patch_21.2.05 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/27153_rm2/patch_22.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/28098_rm2/patch_23.2.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/291217_rm2/patch_24.2.04 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2100324_rm2/patch_25.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2101332_rm2/patch_26.2.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2102356_rm2/patch_27.2.05 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2103379_rm2/patch_28.2.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2110442_rm2/patch_29.2.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2121527_rm2/patch_30.2.07 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2122573_rm2/patch_31.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2123606_rm2/patch_32.2.02 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2130758_rm2/patch_33.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2140861_rm2/patch_34.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2141866_rm2/patch_35.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/2143977_rm2/patch_36.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/21431047_rm2/patch_37.2.01 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/21501067_rm2/patch_38.2.03 - install -D -m 644 -t "$pkgdir$_patches_dir" "$srcdir"/patches/21511189_rm2/patch_39.2.01 + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" + if [[ $arch = rm1os2 ]]; then + patches_dir="${pkgdir}${_patches_dir}" + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/26171_rm1/patch_19.1.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/26275_rm1/patch_20.1.03 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/27051_rm1/patch_21.1.04 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/28098_rm1/patch_23.1.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/291236_rm1/patch_24.1.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2100324_rm1/patch_25.1.03 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2102356_rm1/patch_27.1.03 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2103379_rm1/patch_28.1.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2110442_rm1/patch_29.1.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2121527_rm1/patch_30.1.08 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2122573_rm1/patch_31.1.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2123606_rm1/patch_32.1.03 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2140861_rm1/patch_34.1.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2141866_rm1/patch_35.1.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2143977_rm1/patch_36.1.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/21431047_rm1/patch_37.1.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/21501067_rm1/patch_38.1.03 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/21511189_rm1/patch_39.1.01 + elif [[ $arch = rm2os2 ]]; then + patches_dir="${pkgdir}${_patches_dir}" + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/26171_rm2/patch_19.2.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/26275_rm2/patch_20.2.03 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/27051_rm2/patch_21.2.05 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/27153_rm2/patch_22.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/28098_rm2/patch_23.2.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/291217_rm2/patch_24.2.04 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2100324_rm2/patch_25.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2101332_rm2/patch_26.2.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2102356_rm2/patch_27.2.05 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2103379_rm2/patch_28.2.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2110442_rm2/patch_29.2.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2121527_rm2/patch_30.2.07 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2122573_rm2/patch_31.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2123606_rm2/patch_32.2.02 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2130758_rm2/patch_33.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2140861_rm2/patch_34.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2141866_rm2/patch_35.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/2143977_rm2/patch_36.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/21431047_rm2/patch_37.2.01 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/21501067_rm2/patch_38.2.03 + install -D -m 644 -t "$patches_dir" "$srcdir"/patches/21511189_rm2/patch_39.2.01 fi - touch "$srcdir"/emptyfile - install -D -m 666 -t "$pkgdir"/usr/share/toltec/reenable.d/ddvk-hacks "$srcdir"/emptyfile } configure() { @@ -78,7 +81,7 @@ configure() { local device local original_hash local xochitl_version - if [[ $arch = rm1 ]]; then + if [[ $arch = rm1os2 ]]; then device="reMarkable 1" case "$build_date" in "20221026103859") @@ -179,7 +182,7 @@ configure() { exit 1 ;; esac - elif [[ $arch = rm2 ]]; then + elif [[ $arch = rm2os2 ]]; then device="reMarkable 2" case "$build_date" in "20221026104022") @@ -328,11 +331,25 @@ configure() { cp "$_patched_path" "$_xochitl_path" rm -rf /home/root/.cache/remarkable/xochitl/qmlcache/* + # shellcheck source=../toltec-bootstrap/toltecctl + source /home/root/.local/bin/toltecctl + get-release-version > "$_info_path" + echo "Please restart Xochitl to use the patches" echo } _restore() { + # shellcheck source=../toltec-bootstrap/toltecctl + source /home/root/.local/bin/toltecctl + + if ! [ -f "$_info_path" ] \ + || [[ "$(get-release-version)" != "$(cat "$_info_path")" ]] \ + || compare-versions "$(get-release-version)" "3.0"; then + echo "Skipping restore, as you are on a newer OS version" + return + fi + echo echo "Restoring the original Xochitl binary" @@ -342,6 +359,7 @@ _restore() { else cp "$_backup_path" "$_xochitl_path" rm -rf /home/root/.cache/remarkable/xochitl/qmlcache/* + rm "$_info_path" fi echo diff --git a/package/fuse/package b/package/fuse/package index 4c80b0bce..bb3c88a41 100755 --- a/package/fuse/package +++ b/package/fuse/package @@ -2,11 +2,11 @@ # Copyright (c) 2020 The Toltec Contributors # SPDX-License-Identifier: MIT -archs=(rm1 rm2) +archs=(rm1os2 rm2os2) pkgnames=(fuse) pkgdesc="FUSE (Filesystem in Userspace) Kernel Module" url=https://github.com/libfuse/libfuse -pkgver=1.0.0-4 +pkgver=1.0.0-5 timestamp=2021-04-06T22:16Z section=kernel maintainer="plan5 <30434574+plan5@users.noreply.github.com>" @@ -51,14 +51,14 @@ build() { } package() { - if [[ $arch = rm1 ]]; then + if [[ $arch = rm1os2 ]]; then mkdir -p "$pkgdir/lib/modules" cp -r "$srcdir/pkg"/* "$pkgdir/lib/modules" fi } configure() { - if [[ $arch = rm1 ]]; then + if [[ $arch = rm1os2 ]]; then # Regenerate /lib/modules/[ver]/modules.devname to request the # creation of /dev/fuse used for on-demand loading of fuse depmod -a @@ -72,7 +72,7 @@ configure() { } postremove() { - if [[ $arch = rm1 ]]; then + if [[ $arch = rm1os2 ]]; then echo 'Fuse (Kernel Module) has been removed.' echo 'The kernel module will remain loaded until you reboot, or you can attempt' echo 'to manually remove it by running "modprobe -r fuse".' @@ -81,7 +81,7 @@ postremove() { } postupgrade() { - if [[ $arch = rm1 ]]; then + if [[ $arch = rm1os2 ]]; then echo 'Fuse (Kernel Module) has been upgraded.' echo 'The old kernel module will remain loaded until you reboot, or you can' echo 'attempt to manually remove it by running "modprobe -r fuse".' diff --git a/package/kernelctl/package b/package/kernelctl/package index f4a4b36be..dcfcd5f7d 100644 --- a/package/kernelctl/package +++ b/package/kernelctl/package @@ -5,7 +5,7 @@ pkgnames=(kernelctl) pkgdesc="Manage aftermarket kernels" url=https://toltec-dev.org/ -pkgver=0.1-6 +pkgver=0.1-7 timestamp=2022-11-12T00:00Z section="utils" maintainer="Salvatore Stella " @@ -19,10 +19,10 @@ sha256sums=( ) package() { - touch "$srcdir"/emptyfile install -D -m 744 -t "$pkgdir"/opt/bin "$srcdir"/kernelctl install -d "$pkgdir"/opt/usr/share/kernelctl - install -D -m 666 -t "$pkgdir"/usr/share/toltec/reenable.d/kernelctl "$srcdir"/emptyfile + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" } configure() { diff --git a/package/signature-rm/package b/package/signature-rm/package index 7c24d8061..87154993a 100644 --- a/package/signature-rm/package +++ b/package/signature-rm/package @@ -2,17 +2,18 @@ # Copyright (c) 2021 The Toltec Contributors # SPDX-License-Identifier: MIT -_pkgname='signature-rm' -pkgnames=("$_pkgname") +archs=(rmallos2 rmallos3) +pkgnames=("signature-rm") pkgdesc="Remove the signature from the bottom of emails" url="https://github.com/rM-self-serve/signature-rM" -pkgver=1.0.2-1 +pkgver=1.0.2-2 timestamp=2023-12-06T11:43:00Z section="utils" maintainer="rM-self-serve <122753594+rM-self-serve@users.noreply.github.com>" license=MIT image=rust:v3.1 -conflicts=(ddvk-hacks webinterface-onboot) +conflicts=(webinterface-onboot) +conflicts_rmallos2=(ddvk-hacks) source=( "$url"/archive/b5561af4eb6a0f5aa6e98e1a1279066f0c4bd9b7.zip @@ -27,10 +28,10 @@ build() { package() { install -D -m 755 -t "$pkgdir"/opt/bin \ - "$srcdir/target/armv7-unknown-linux-gnueabihf/release/$_pkgname" + "$srcdir/target/armv7-unknown-linux-gnueabihf/release/$pkgname" - touch "$srcdir"/emptyfile - install -D -m 666 -t "$pkgdir"/usr/share/toltec/reenable.d/"$_pkgname" "$srcdir"/emptyfile + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" } configure() { diff --git a/package/templatectl/package b/package/templatectl/package index 7c7414550..b09b7fc7b 100644 --- a/package/templatectl/package +++ b/package/templatectl/package @@ -5,7 +5,7 @@ pkgnames=(templatectl) pkgdesc="Tool to add/remove templates for xochitl" url=https://github.com/PeterGrace/templatectl -pkgver=0.1.3-4 +pkgver=0.1.3-5 timestamp=2021-01-15T01:23Z section="templates" maintainer="Peter Grace " @@ -22,6 +22,8 @@ build() { package() { install -D -m 755 -t "$pkgdir"/opt/bin \ "$srcdir"/target/armv7-unknown-linux-gnueabihf/release/templatectl + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" } preinstall() { diff --git a/package/toltec-base/package b/package/toltec-base/package index 06d812667..c1fc5e010 100644 --- a/package/toltec-base/package +++ b/package/toltec-base/package @@ -2,25 +2,26 @@ # Copyright (c) 2023 The Toltec Contributors # SPDX-License-Identifier: MIT -archs=(rm1 rm2) +archs=(rmall rmallos2 rmallos3 rm1 rm1os2 rm1os3 rm2 rm2os2 rm2os3) pkgnames=(toltec-base) pkgdesc="Metapackage defining the base set of packages in a Toltec install" url=https://toltec-dev.org/ -pkgver=1.3-1 +pkgver=1.3-2 timestamp=2023-12-27T08:30Z section="utils" maintainer="Eeems " license=MIT -installdepends=(toltec-bootstrap toltec-completion) -installdepends_rm1=(open-remarkable-shutdown) -installdepends_rm2=(rm2-suspend-fix) +installdepends=(toltec-bootstrap toltec-deletions toltec-completion wget-ssl ca-certificates) +installdepends_rm1os2=(open-remarkable-shutdown) +installdepends_rm1os3=(open-remarkable-shutdown) +installdepends_rm2os2=(rm2-suspend-fix) +installdepends_rm2os3=(rm2-suspend-fix) source=() sha256sums=() package() { - touch "$srcdir"/emptyfile - install -D -m 666 -t "$pkgdir"/usr/share/toltec/reenable.d/toltec-base "$srcdir"/emptyfile + true } configure() { @@ -31,23 +32,28 @@ configure() { /opt/etc/profile echo "Disabling automatic update" disable-unit update-engine.service - if [[ "$arch" == "rm1" ]]; then - echo "Disabling usb1 network device to avoid long boots" - if ! is-masked sys-subsystem-net-devices-usb1.device; then - systemctl mask sys-subsystem-net-devices-usb1.device - fi - if ! is-masked busybox-ifplugd@usb1.service; then - systemctl mask busybox-ifplugd@usb1.service - fi - elif [[ "$arch" == "rm2" ]]; then - echo "Enabling usb1 network device to ensure usb SSH works" - if is-masked sys-subsystem-net-devices-usb1.device; then - systemctl unmask sys-subsystem-net-devices-usb1.device - fi - if is-masked busybox-ifplugd@usb1.service; then - systemctl unmask busybox-ifplugd@usb1.service - fi - fi + case "$arch" in + rmall | rmallos2 | rmallos3) + echo "Warning: rmall version of toltec-base should not be installed" + echo "Please run opkg install --force-reinstall toltec-base" + ;; + rm1 | rm1os2 | rm1os3) + if ! is-masked sys-subsystem-net-devices-usb1.device; then + systemctl mask sys-subsystem-net-devices-usb1.device + fi + if ! is-masked busybox-ifplugd@usb1.service; then + systemctl mask busybox-ifplugd@usb1.service + fi + ;; + rm2 | rm2os2 | rm2os3) + if is-masked sys-subsystem-net-devices-usb1.device; then + systemctl unmask sys-subsystem-net-devices-usb1.device + fi + if is-masked busybox-ifplugd@usb1.service; then + systemctl unmask busybox-ifplugd@usb1.service + fi + ;; + esac } postremove() { diff --git a/package/toltec-bootstrap/package b/package/toltec-bootstrap/package index 1b033cc4a..c1a3393ee 100644 --- a/package/toltec-bootstrap/package +++ b/package/toltec-bootstrap/package @@ -5,8 +5,8 @@ pkgnames=(toltec-bootstrap) pkgdesc="Manage your Toltec install" url=https://toltec-dev.org/ -pkgver=0.2.3-1 -timestamp=2023-09-17T17:35Z +pkgver=0.4.0-1 +timestamp=2023-11-27T00:34Z section="utils" maintainer="Eeems " license=MIT @@ -53,14 +53,14 @@ configure() { fi create-entware-conf - switch-branch "$branch" - echo "Your Opkg configuration has been migrated" + fi - if generate-opkg-conf; then - echo - echo "! The upgrade is not finished! Please run \`opkg update\`" - echo "! and \`opkg upgrade\` once more to complete it." - echo - fi + switch-branch "$(get-branch)" + echo "Your Opkg configuration has been upgraded" + if generate-opkg-conf; then + echo + echo "! The upgrade is not finished! Please run \`opkg update\`" + echo "! and \`opkg upgrade\` once more to complete it." + echo fi } diff --git a/package/toltec-bootstrap/toltecctl b/package/toltec-bootstrap/toltecctl index b9ea0bcb3..a3792f0ad 100644 --- a/package/toltec-bootstrap/toltecctl +++ b/package/toltec-bootstrap/toltecctl @@ -10,9 +10,16 @@ toltec_src=/home/root/.entware # Path where Toltec is mounted toltec_dest=/opt +# Path where toltec caches compatibility information +toltec_share=/home/root/.local/share/toltec +# Path to static opkg build +opkg_path=/home/root/.local/bin/opkg +# Path to opkg install status file +opkg_status="/opt/lib/opkg/status" + # Path to Opkg configuration -opkg_conf="$toltec_dest"/etc/opkg.conf -opkg_conf_dir="$toltec_dest"/etc/opkg.conf.d +opkg_conf="$toltec_src"/etc/opkg.conf +opkg_conf_dir="$toltec_src"/etc/opkg.conf.d # Path to the Xochitl configuration xochitl_conf=/home/root/.config/remarkable/xochitl.conf @@ -27,6 +34,50 @@ bashrc_start_marker="# Added by Toltec bootstrap (do not modify!)" bashrc_old_start_marker="# Path added by Toltec bootstrap" bashrc_end_marker="# End of Toltec bootstrap additions" +# Print a log message +# +# Arguments: +# +# [$1] - Log level: INFO, WARN or ERROR (default: INFO) +# $2... - Messages to print, each argument goes to a separate line +log() { + # Output stream where the messages will be sent + local log_type="INFO" + local fd=1 + local colored_prefix + + if [[ $# -ge 2 ]]; then + case "$1" in + INFO | WARN | ERROR) + log_type="$1" + shift + ;; + esac + fi + + case "$log_type" in + INFO) colored_prefix='\e[32mINFO:\e[0m ' ;; + WARN) + colored_prefix='\e[33mWARN:\e[0m ' + fd=2 + ;; + ERROR) + colored_prefix='\e[31mERROR:\e[0m ' + fd=2 + ;; + esac + + echo -e "${colored_prefix}$1" >&$fd + + # Extra lines to print indented + shift + local line + + for line in "$@"; do + echo -e " $line" >&$fd + done +} + # Identify which reMarkable model we’re currently running on # # Output: One of the following strings @@ -51,6 +102,68 @@ identify-model() { esac } +# Find the current OS release version +# +# Output: Current version in the X.Y.Z.P format +get-release-version() { + awk -F= '/RELEASE_VERSION/{print $2}' /usr/share/remarkable/update.conf +} + +# Check to see if the version is supported and error if it isn't supported +# +# Arguments: +# +# $1 - Branch for which to check support +# +# Exit code: +# +# 0 - if the current version is supported +# 1 - if unsupported +# 2 - if version compatibility information could not be retrieved +# 3 - unable to install standalone wget +check-version() { + local wget + if [[ "$(install-state)" != "yes" ]] || [[ "$(command -v wget)" != "/opt/bin/wget" ]]; then + if ! install-standalone-wget; then + return 2 + fi + wget="${toltec_share}/wget" + else + wget="wget" + fi + local check_branch + local current_model + local current_version + local cwd + check_branch="$1" + current_model="$(identify-model)" + current_version="$(get-release-version)" + + cwd="$(pwd)" + mkdir -p "$toltec_share" + cd "$toltec_share" + if ! "$wget" "$toltec_srv_root"/"$check_branch"/Compatibility \ + --timestamping \ + --no-verbose \ + --ignore-length 2> /dev/null; then + log ERROR "Unable to fetch updated version compatibility information, make sure you have a stable Wi-Fi connection" + if ! [ -f Compatibility ]; then + cd "$cwd" + return 2 + fi + log WARN "Using outdated cached version compatibility information" + fi + cd "$cwd" + + if ! grep -q "${current_model}=${current_version}" "${toltec_share}/Compatibility"; then + LOG ERROR "You’re running an unsupported OS version: $current_version" + LOG ERROR "Please monitor Toltec releases for upcoming support" + return 1 + fi + + return 0 +} + # Get the password used to login to the SSH prompt # # Output: SSH password @@ -122,21 +235,214 @@ remove-bind-mount() { if [[ ! -e $unit_path ]]; then echo "No existing bind mount for '$1'" - return 1 + return fi echo "Removing mount over '$1'" systemctl disable "$unit_name" - umount -l "$1" + systemctl stop "$unit_name" + if mountpoint -q "$1"; then + umount -l "$1" + fi rm "$unit_path" systemctl daemon-reload } +# Escape a string for use in a sed search +# +# Arguments +# +# $1 - String to escape +# +# Output: +# +# Escaped string +escape-for-sed() { + # shellcheck disable=SC1003 + sed -e 's/[^^]/[&]/g; s/\^/\\^/g; $!a\'$'\n''\\n' <<< "$1" | tr -d '\n' +} + +# Escape a string for use in a sed replacement +# +# Arguments +# +# $1 - String to escape +# +# Output: +# +# Escaped string +escape-for-sed-replace() { + IFS= read -d '' -r < <(sed -e ':a' -e '$!{N;ba' -e '}' -e 's/[&/\]/\\&/g; s/\n/\\&/g' <<< "$1") + printf %s "${REPLY%$'\n'}" +} + +# Replace multiline string content in stdin +# +# Arguments: +# +# $1 - String to replace +# $2 - string to replace with +# stdin - Text to perform replacement on +# +# Output: +# +# Contents of stdin with the string replaced +replace-string() { + sed \ + -e ':a' \ + -e '$!{N;ba' -e '}' \ + -e "s/$(escape-for-sed "$1")/$(escape-for-sed-replace "$2")/" +} + +# Get the opkg status for a package +# +# Arguments: +# +# $1 - Package name +# +# Output: Opkg status information for the package +# +# Exit Code: +# +# 0 - Status found +# 1 - Status not found +get-package-status() { + local status + status="$(opkg status "$1" | grep -v "has no valid architecture, ignoring" || true)" + if [ -n "$status" ]; then + echo "$status" + return 0 + fi + local index + local index2 + local count + # Don't use --line-number so this works on the built in grep + index="$(grep -n "Package: ${1}" "$opkg_status" | cut -d':' -f1 || echo "-1")" + if [ "$index" -eq -1 ]; then + return 1 + fi + # Don't use --line-number so this works on the built in grep + count="$(tail -n +$((index + 1)) "$opkg_status" | grep -n "Package: " | head -n1 | cut -d':' -f1 || echo "-1")" + if [ "$count" -eq -1 ]; then + return 1 + fi + index2=$((index + count - 1)) + status="$(sed -n "${index},${index2}p;$((index2 + 1))q" "$opkg_status")" + if [ -z "$status" ]; then + return 1 + fi + echo "$status" + return 0 +} + +# Check if a string appears in a set of strings +# +# Arguments: +# +# $1 - String to look for +# $2... - Elements to compare to $1 +# +# Example: +# +# > has-element "needle" "${haystack[@]}" +# Will return 0 if "needle" is found in the "haystack" array. +# +# Exit code: 0 if the element is found, 1 otherwise. +has-element() { + local needle="$1" + shift + + for element; do + if [[ $needle == "$element" ]]; then + return 0 + fi + done + + return 1 +} + +# Update the opkg status for a package with the correct architecture for the device +# +# Arguments: +# +# $1 - Package name +# +# Exit Codes: +# +# 0 - Package status was updated +# 1 - Package status was not modified +# 2 - Package status was not found +# 3 - Package status has no architecture +update-package-arch() { + if ! grep -q "Package: ${1}" "$opkg_status"; then + return 1 + fi + local arch + local model + local new_status + local version + local status + local rc=0 + status="$(get-package-status "$1" || true)" + if [ -z "$status" ]; then + log WARN "Unable to get status for package: ${1}" + return 2 + fi + arch="$(echo "$status" | grep "Architecture:" | awk '{print $2}')" + if [ -z "$arch" ]; then + return 3 + fi + case "$arch" in + rmallos2 | rmallos3) + version="$(identify-support-version)" + new_status="$(echo "$status" | replace-string "Architecture: ${arch}" "Architecture: rmall${version}")" + ;; + rm1os2 | rm1os3 | rm2os2 | rm2os3) + model="$(identify-model)" + version="$(identify-support-version)" + new_status="$(echo "$status" | replace-string "Architecture: ${arch}" "Architecture: ${model}${version}")" + ;; + *) + new_status="$status" + ;; + esac + if [[ "$status" == "$new_status" ]]; then + return 1 + fi + echo "Updating package architecture for package: ${1}" + sed -i \ + -e ':a' \ + -e '$!{N;ba' -e '}' \ + -e "s/$(escape-for-sed "$status")/$(escape-for-sed-replace "$new_status")/" \ + "$opkg_status" + return 0 +} + +# Reinstall toltec-base and toltec-deletions +reinstall-base() { + local packages=() + while read -r pkg; do + if update-package-arch "$pkg"; then + packages+=("$pkg") + fi + done < <(opkg list-installed | grep -v "has no valid architecture, ignoring" | cut -d' ' -f1 || true) + while read -r pkg; do + if update-package-arch "$pkg"; then + packages+=("$pkg") + fi + done < <(opkg list-installed | grep "has no valid architecture, ignoring" | cut -d' ' -f2 || true) + if ! has-element "toltec-base" "${packages[@]}"; then + packages+=(toltec-base) + fi + if ! has-element "toltec-deletions" "${packages[@]}"; then + packages+=(toltec-deletions) + fi + opkg install --force-reinstall "${packages[@]}" || true +} + # Reinstall all Toltec packages that had files installed outside of # $toltec_src, e.g. systemd configuration files reinstall-root() { - opkg update - # Get the list of installed packages with files on root local pkgname declare -A on_root_packages @@ -161,7 +467,7 @@ reinstall-root() { # temporarily set +u if [[ ${#reinstall_packages[@]} -ne 0 ]]; then - opkg install --force-reinstall --force-remove "${!reinstall_packages[@]}" + opkg install --force-reinstall --force-remove "${!reinstall_packages[@]}" || true else echo "No package needs to be reinstalled" fi @@ -195,7 +501,7 @@ SHELL new_path="$(bash -l -c "echo \$PATH")" if [[ $old_path != "$new_path" ]]; then - echo "Please restart your SSH session or run 'exec bash --login' to use Toltec" + log WARN "Please restart your SSH session or run 'exec bash --login' to use Toltec" fi } @@ -267,6 +573,61 @@ src/gz entware https://bin.entware.net/armv7sf-k3.2 CONF } +# Get the current Toltec branch of this installation +# +# Output: Current branch name +get-branch() { + if ! [ -f "$opkg_conf_dir/15-toltec.conf" ]; then + return + fi + local srv_prefix_len=${#toltec_srv_root} + local srv_prefix="${toltec_srv_root//\//\\/}" + local awk_get_branch=" + match(\$0, /$srv_prefix\/(.+)\/rmall/) { + print substr( \ + \$0, \ + RSTART+$srv_prefix_len+1, \ + RLENGTH-$srv_prefix_len-1-6 \ + ) + } + " + awk "$awk_get_branch" "$opkg_conf_dir/15-toltec.conf" | head -n1 || true +} + +# Compare two version numbers +# +# Arguments: +# +# $1 - Version number to compare +# $2 - Version number to compare +# +# Output: True if the first number is larger than the second +compare-versions() { + [ "$(echo -e "${1}\n${2}" | sort | head -n1)" != "$1" ] +} + +# Identify which toltec version this should be limited to +# +# Output: One of the following strings +# +# os2 - 2.x OS version +# os3 - 3.x OS version +# unknown +identify-support-version() { + local current_version + current_version="$(get-release-version)" + + if compare-versions "2.0" "$current_version"; then + echo "unknown" + elif compare-versions "3.0" "$current_version"; then + echo "os2" + elif compare-versions "4.0" "$current_version"; then + echo "os3" + else + echo "unknown" + fi +} + # Set the Toltec branch for this installation # (generate-opkg-conf must be run afterwards to rebuild the main config file) # @@ -276,10 +637,16 @@ CONF switch-branch() { local branch="${1:-stable}" local model + local version model="$(identify-model)" + version="$(identify-support-version)" if [[ $model = "unknown" ]]; then - echo "You’re running an unsupported or unrecognised device" + log ERROR "You’re running an unsupported or unrecognised device" + exit 1 + fi + if [[ $version = "unknown" ]]; then + log ERROR "You're running an unsupported or unrecognised OS version" exit 1 fi @@ -292,16 +659,43 @@ switch-branch() { # switch to a different Toltec branch arch rmall 200 -src/gz toltec-rmall $toltec_srv_root/$branch/rmall -arch $model 250 -src/gz toltec-$model $toltec_srv_root/$branch/$model +src/gz toltec-rmall ${toltec_srv_root}/${branch}/rmall +arch ${model} 250 +src/gz toltec-${model} ${toltec_srv_root}/${branch}/${model} +arch rmall${version} 260 +src/gz toltec-rmall$version ${toltec_srv_root}/${branch}/rmall${version} +arch ${model}os2 270 +arch ${model}os3 270 +src/gz toltec-${model}${version} ${toltec_srv_root}/${branch}/${model}${version} CONF } # Re-enable Toltec install after system update reenable() { + log INFO "Mounting /opt" add-bind-mount "$toltec_src" "$toltec_dest" + switch-branch "$(get-branch)" + log INFO "Generating /opt/etc/opkg.conf" + generate-opkg-conf || true + log INFO "Opkg update" + opkg update + log INFO "Reinsalling base packages" + reinstall-base + log INFO "Reinstalling packages with files on the root partition" reinstall-root + if [ -d /opt/share/toltec/reenable.d ]; then + find /opt/share/toltec/reenable.d -maxdepth 1 -mindepth 1 -print0 \ + | xargs -0rn1 basename \ + | while read -r pkg; do + local script + script="/opt/lib/opkg/info/${pkg}.postinst" + if [ -f "$script" ]; then + log INFO "Reconfiguring ${pkg}" + "$script" configure || true + fi + done + fi + log INFO "Configuring bashrc" set-path } @@ -323,18 +717,68 @@ list-installed-ordered() { # tsort reports errors if there are dependency cycles, we ignore them } -# Remove Toltec completely -uninstall() { - # Fetch standalone opkg used to uninstall packages - local opkg_path=/home/root/.local/bin/opkg +# Install standalone opkg binary +install-standalone-opkg() { + local wget + if [[ "$(install-state)" != "yes" ]] || [[ "$(command -v wget)" != "/opt/bin/wget" ]]; then + if ! install-standalone-wget; then + return 2 + fi + wget="${toltec_share}/wget" + else + wget="wget" + fi local opkg_remote=https://bin.entware.net/armv7sf-k3.2/installer/opkg - if ! wget --no-verbose "$opkg_remote" --output-document "$opkg_path"; then - echo "Unable to fetch standalone opkg, make sure you have a stable Wi-Fi connection" + if ! "$wget" --no-verbose "$opkg_remote" --output-document "$opkg_path"; then + log ERROR "Unable to fetch standalone opkg, make sure you have a stable Wi-Fi connection" return 1 fi chmod u+x "$opkg_path" + if [[ $(command -v opkg) != "$opkg_path" ]]; then + export PATH + PATH="$(dirname "$opkg_path"):$PATH)" + fi +} + +# Install a local wget binary which supports TLS (the original one +# installed on the reMarkable does not) in the PATH +install-standalone-wget() { + local wget_path="${toltec_share}/wget" + local wget_remote=http://toltec-dev.org/thirdparty/bin/wget-v1.21.1 + local wget_checksum=8798fcdabbe560722a02f95b30385926e4452e2c98c15c2c217583eaa0db30fc + + if [ -f "$wget_path" ] && ! [[ -e $wget_path ]] || ! sha256sum -c <(echo "$wget_checksum $wget_path") > /dev/null 2>&1; then + rm "$wget_path" + fi + + if ! [ -f "$wget_path" ]; then + log INFO "Fetching secure wget" + + # Download and compare to hash + mkdir -p "$(dirname "$wget_path")" + + if ! wget -q "$wget_remote" --output-document "$wget_path"; then + log ERROR "Could not fetch wget, make sure you have a stable Wi-Fi connection" + exit 1 + fi + + if ! sha256sum -c <(echo "$wget_checksum $wget_path") > /dev/null 2>&1; then + log ERROR "Invalid checksum for the local wget binary" + exit 1 + fi + + chmod 755 "$wget_path" + fi +} + +# Remove Toltec completely +uninstall() { + # Fetch standalone opkg used to uninstall packages + if ! install-standalone-opkg; then + return 1 + fi # Remove installed packages in reverse dependency order list-installed-ordered | while read -r pkgname; do @@ -358,6 +802,71 @@ uninstall() { systemctl enable xochitl } +# The current toltec install state +# +# Output: +# +# yes - opt.mount is enabled and active +# partial - opt.mount is active but not enabled +# no - opt.mount is not enabled, or does not exist +install-state() { + local unit_name + local enabled + unit_name="$(systemd-escape --path "$toltec_dest").mount" + if ! systemctl --quiet is-enabled "$unit_name" 2> /dev/null; then + echo "no" + elif systemctl --quiet is-active "$unit_name"2 > /dev/null; then + echo "partial" + else + echo "yes" + fi +} + +# Output toltec installation status +status() { + echo -ne "Enabled: \033[1m" + local enabled=false + case "$(install-state)" in + yes) + enabled=true + echo -ne "\e[32mYes" + ;; + no) + echo -ne "\e[31mNo" + ;; + partial) + echo -ne "\e[33mPartial" + ;; + *) + echo -ne "\e[31mUnknown" + ;; + esac + echo -e "\e[0m" + echo -ne "Supported: \033[1m" + local rc + rc=0 + check-version "$(get-branch)" &> /dev/null || rc=$? + if [ $rc -eq 0 ]; then + echo -ne "\e[32mYes" + elif [ $rc -eq 2 ] || [ $rc -eq 3 ]; then + echo -ne "\e[33mUnknown" + else + echo -ne "\e[31mNo" + fi + echo -e "\e[0m" + echo -n "Branch: " + if [ -f "$opkg_conf" ]; then + # shellcheck disable=SC2005 + echo "$(get-branch)" + else + echo -e "\033[1m\e[33mUnknown\e[0m" + fi + echo -n "Model: " + identify-model + echo -n "OS: " + get-release-version +} + help() { echo "Usage: $(basename "$0") COMMAND Manage your Toltec install. Available commands: @@ -387,7 +896,7 @@ if [[ $0 = "${BASH_SOURCE[0]}" ]]; then echo if [[ $REPLY =~ ^[Nn]$ ]]; then - echo "Not reloading. Use 'opkg update' to do it manually." + log WARN "Not reloading. Use 'opkg update' to do it manually." else opkg update fi @@ -416,7 +925,13 @@ MSG echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Canceled" + log WARN "Canceled" + exit 1 + fi + fi + + if ! check-version "$target_branch"; then + if [[ -z $force ]]; then exit 1 fi fi @@ -433,7 +948,7 @@ MSG echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Canceled" + log WARN "Canceled" exit 1 fi fi @@ -446,7 +961,7 @@ MSG echo if [[ $REPLY =~ ^[Nn]$ ]]; then - echo "Not reloading. Use 'opkg update' to do it manually." + log WARN "Not reloading. Use 'opkg update' to do it manually." exit fi fi @@ -456,6 +971,14 @@ MSG ;; reenable) + force=$({ (($# > 0)) && [[ $1 = "--force" || $1 = "-f" ]] && echo 1; } || true) + + if ! check-version "$(get-branch)"; then + if [[ -z $force ]]; then + exit 1 + fi + fi + reenable ;; @@ -467,7 +990,7 @@ MSG echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then - echo "Canceled" + log WARN "Canceled" exit 1 fi fi @@ -479,25 +1002,29 @@ MSG echo if [[ $REPLY =~ ^[Nn]$ ]]; then - echo "Please reboot your device manually to complete the uninstall process" + log WARN "Please reboot your device manually to complete the uninstall process" exit fi fi if [[ ! -f $ssh_key_file ]]; then - echo "In case something goes wrong, your SSH password is: $(get-ssh-password)" + log WARN "In case something goes wrong, your SSH password is: $(get-ssh-password)" fi - echo "Rebooting" + log INFO "Rebooting" reboot ;; + status) + status + ;; + help | -h | --help) help ;; *) - echo -e "Error: Invalid command '$action'\n" + log ERROR "Invalid command '$action'\n" help exit 1 ;; diff --git a/package/toltec-completion/_toltecctl b/package/toltec-completion/_toltecctl index e1d3b765b..5a8d7e01c 100755 --- a/package/toltec-completion/_toltecctl +++ b/package/toltec-completion/_toltecctl @@ -8,7 +8,7 @@ _toltecctl() { _init_completion -s || return if [[ $cword -eq 1 ]]; then - COMPREPLY=($(compgen -W 'help generate-opkg-conf switch-branch reenable uninstall' -- "$cur")) + COMPREPLY=($(compgen -W 'help generate-opkg-conf switch-branch reenable uninstall status' -- "$cur")) return fi diff --git a/package/toltec-completion/package b/package/toltec-completion/package index cc465a569..39a87f0e3 100644 --- a/package/toltec-completion/package +++ b/package/toltec-completion/package @@ -5,7 +5,7 @@ pkgnames=(toltec-completion) pkgdesc="Expands bash-completion with functions for toltec-specific commands" url=https://github.com/toltec-dev/toltec -pkgver=0.3.1-1 +pkgver=0.3.2-1 timestamp=2022-01-23T23:29Z section="utils" maintainer="Linus K. " diff --git a/package/toltec-deletions/package b/package/toltec-deletions/package new file mode 100644 index 000000000..74764e261 --- /dev/null +++ b/package/toltec-deletions/package @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +archs=(rmallos2 rmallos3) +pkgnames=(toltec-deletions) +pkgdesc="Metapackage to handle package deletions between OS versions" +url=https://toltec-dev.org/ +pkgver=0.1-1 +timestamp=2023-12-03T04:51:58Z +section="utils" +maintainer="Eeems " +license=MIT +installdepends=(toltec-bootstrap) +conflicts_rmallos2=() +replaces_rmallos2=() +conflicts_rmallos3=(ddvk-hacks fuse wireguard) +replaces_rmallos3=(ddvk-hacks fuse wireguard) + +source=() +sha256sums=() + +package() { + # This should be fully reinstalled on reenable + # So add a file to root + mkdir -p "$pkgdir"/usr/share/toltec/reenable.d + touch "$pkgdir"/usr/share/toltec/reenable.d/toltec-deletions +} diff --git a/package/webinterface-onboot/package b/package/webinterface-onboot/package index fc12319fe..0040ffc06 100644 --- a/package/webinterface-onboot/package +++ b/package/webinterface-onboot/package @@ -2,21 +2,22 @@ # Copyright (c) 2021 The Toltec Contributors # SPDX-License-Identifier: MIT -_pkgname='webinterface-onboot' -pkgnames=("$_pkgname") +archs=(rmallos2 rmallos3) +pkgnames=("webinterface-onboot") pkgdesc="Start the web interface without the cable, on boot." -url="https://github.com/rM-self-serve/$_pkgname" -pkgver=1.2.3-1 +url="https://github.com/rM-self-serve/webinterface-onboot" +pkgver=1.2.3-2 timestamp=2023-12-31T11:43:00Z section="utils" maintainer="rM-self-serve <122753594+rM-self-serve@users.noreply.github.com>" license=MIT -conflicts=(ddvk-hacks signature-rm) +conflicts=(signature-rm) +conflicts_rmallos2=(ddvk-hacks) installdepends=(libbfd) source=( "$url"/archive/e184b6a37ccba0ebeacd34faf63c8f4cdfa5c448.zip - "$_pkgname-toltec.service" + "webinterface-onboot-toltec.service" ) sha256sums=( 2e3666b1875f874ef09da2bbd163295b89e9e241f1e59e77349b0e2db716b8ff @@ -24,12 +25,12 @@ sha256sums=( ) package() { - install -D -m 755 -t "$pkgdir/opt/bin" "$srcdir/$_pkgname" - install -D -m 644 "$srcdir/$_pkgname-toltec.service" \ - "$pkgdir/lib/systemd/system/$_pkgname.service" + install -D -m 755 -t "$pkgdir/opt/bin" "$srcdir/$pkgname" + install -D -m 644 "$srcdir/$pkgname-toltec.service" \ + "$pkgdir/lib/systemd/system/$pkgname.service" - touch "$srcdir"/emptyfile - install -D -m 666 -t "$pkgdir"/usr/share/toltec/reenable.d/"$_pkgname" "$srcdir"/emptyfile + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" } configure() { diff --git a/package/webinterface-upload-button/package b/package/webinterface-upload-button/package index 201285a15..62227cae5 100644 --- a/package/webinterface-upload-button/package +++ b/package/webinterface-upload-button/package @@ -2,11 +2,10 @@ # Copyright (c) 2021 The Toltec Contributors # SPDX-License-Identifier: MIT -_pkgname='webinterface-upload-button' -pkgnames=("$_pkgname") +pkgnames=("webinterface-upload-button") pkgdesc="A simple upload button for the web interface" -url="https://github.com/rM-self-serve/$_pkgname" -pkgver=1.1.1-1 +url="https://github.com/rM-self-serve/webinterface-upload-button" +pkgver=1.1.1-2 timestamp=2023-12-16T15:35:49Z section="utils" maintainer="rM-self-serve <122753594+rM-self-serve@users.noreply.github.com>" @@ -20,11 +19,11 @@ sha256sums=( ) package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir/$_pkgname" - install -D -m 644 -t "$pkgdir"/usr/share/remarkable/webui/ "$srcdir/$_pkgname.js" + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir/$pkgname" + install -D -m 644 -t "$pkgdir"/usr/share/remarkable/webui/ "$srcdir/$pkgname.js" - touch "$srcdir"/emptyfile - install -D -m 666 -t "$pkgdir"/usr/share/toltec/reenable.d/"$_pkgname" "$srcdir"/emptyfile + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" } configure() { diff --git a/package/wireguard/package b/package/wireguard/package index 23665bb19..9a46b62c6 100755 --- a/package/wireguard/package +++ b/package/wireguard/package @@ -1,11 +1,11 @@ #!/usr/bin/env bash # Copyright (c) 2021 The Toltec Contributors # SPDX-License-Identifier: MIT - +archs=(rm1os2 rm2os2) pkgnames=(wireguard) pkgdesc="Fast, modern, secure VPN tunnel" url=https://www.wireguard.com -pkgver=1.0.20210219-4 +pkgver=1.0.20210219-5 timestamp=2021-02-19T14:08Z section=kernel maintainer="Jonah Weissman " diff --git a/requirements.txt b/requirements.txt index a36680a62..1302931a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,27 +1,11 @@ -appdirs==1.4.4 -astroid==2.15.4 -black==23.3.0 -certifi==2020.12.5 -chardet==4.0.0 -click==8.1.3 -docker==4.4.1 -idna==2.10 -isort==5.7.0 -Jinja2==2.11.2 -lazy-object-proxy==1.4.3 -MarkupSafe==1.1.1 -mccabe==0.6.1 -mypy==0.790 -mypy-extensions==0.4.3 -pathspec==0.11.1 -pyelftools==0.27 -pylint==2.17.4 -python-dateutil==2.8.1 -regex==2020.11.13 -requests==2.25.1 -six==1.15.0 -toml==0.10.2 -typing-extensions==4.5.0 -urllib3==1.26.2 -websocket-client==0.57.0 -wrapt==1.12.1 +docker==6.1.3 +python-dateutil==2.8.2 +pyelftools==0.29 +black==23.7.0 +pylint==2.17.5 +mypy==1.5.1 +mypy-extensions==1.0.0 +Jinja2==3.1.2 +types-python-dateutil==2.8.19.14 +types-requests==2.31.0.2 +typing-extensions==4.7.1 diff --git a/scripts/bootstrap/bootstrap b/scripts/bootstrap/bootstrap index f72fff16d..997a2e270 100755 --- a/scripts/bootstrap/bootstrap +++ b/scripts/bootstrap/bootstrap @@ -89,7 +89,7 @@ wget-bootstrap() { exit 1 fi - log "Fetching secure wget" + log INFO "Fetching secure wget" # Download and compare to hash mkdir -p "$(dirname "$wget_path")" @@ -174,6 +174,12 @@ main() { # Clean up the partial install if an uncaught error happens trap error-cleanup ERR + if ! check-version "$toltec_branch"; then + if [ $# -eq 0 ] || [[ "$1" != "--force" ]]; then + exit 1 + fi + fi + log "Installing Toltec and Entware" # Create bind mount from user directory to /opt @@ -224,23 +230,12 @@ main() { ln -sf /etc/localtime /opt/etc/localtime fi - # Install base Toltec packages - local additional_packages=(toltec-base) - - [[ ! -d /opt/etc/ssl/certs ]] && additional_packages+=(ca-certificates) - [[ ! -f /opt/bin/wget ]] && additional_packages+=(wget-ssl) - - if [[ ${#additional_packages[@]} -gt 0 ]]; then - opkg install "${additional_packages[@]}" - fi + opkg install toltec-base - if [[ $# -gt 0 ]]; then - opkg install "$@" + if [[ $# -gt 0 ]] && ! /opt/bin/opkg install "$@"; then + log ERROR "The install was still successful, but the requested packages failed to install" fi - # Reinstall toltec-bootstrap to mark its files as managed, - # to install its dependencies, and to set the user’s PATH - opkg install toltec-bootstrap log "After each system upgrade, run 'toltecctl reenable' to re-enable Toltec" } diff --git a/scripts/install-lib b/scripts/install-lib index e5e9f22a4..ae6cb5066 100644 --- a/scripts/install-lib +++ b/scripts/install-lib @@ -189,7 +189,7 @@ remove-bind-mount() { # # $1 - Full name of the systemd unit, e.g. "draft.service" unit-exists() { - [ "$(systemctl --quiet list-unit-files "${1}" | grep -c "${1}")" -eq 1 ] + [ "$(systemctl --quiet list-unit-files "${1}" | /bin/grep -c "${1}" 2> /dev/null || echo "0")" -eq 1 ] } # Stops and disabled a unit diff --git a/scripts/repo_build.py b/scripts/repo_build.py index 4e7d8c69f..9a9b5f1b4 100755 --- a/scripts/repo_build.py +++ b/scripts/repo_build.py @@ -72,3 +72,4 @@ repo.make_index() repo.make_listing() +repo.make_compatibility() diff --git a/scripts/toltec/bash.py b/scripts/toltec/bash.py index b763dd18c..bf74d17bb 100644 --- a/scripts/toltec/bash.py +++ b/scripts/toltec/bash.py @@ -38,6 +38,7 @@ class ScriptError(Exception): "BASH_SUBSHELL", "BASH_VERSINFO", "BASH_VERSION", + "BASH_LOADABLES_PATH", "COLUMNS", "COMP_WORDBREAKS", "DIRSTACK", @@ -132,10 +133,10 @@ def get_declarations(src: str) -> Tuple[Variables, Functions]: while True: token = lexer.get_token() - if token == lexer.eof: + if token == lexer.eof or token is None: break - next_token = lexer.get_token() + next_token = lexer.get_token() or "" if token == "declare" and next_token[0] == "-": lexer.push_token(next_token) @@ -144,8 +145,16 @@ def get_declarations(src: str) -> Tuple[Variables, Functions]: if name not in default_variables: variables[name] = value else: - assert next_token == "(" - assert lexer.get_token() == ")" + if next_token != "(": + raise ScriptError( + f"Unexpected token '{next_token}' on line {lexer.lineno}. Expecting '('." + ) + + _token = lexer.get_token() + if _token != ")": + raise ScriptError( + f"Unexpected token '{_token}' on line {lexer.lineno}. Expecting ')'." + ) start, end = _parse_func(lexer) functions[token] = declarations[start:end] @@ -217,10 +226,13 @@ def _parse_indexed(lexer: shlex.shlex) -> IndexedArray: break assert token == "[" - index = int(lexer.get_token()) + index = int(lexer.get_token() or "") assert lexer.get_token() == "]" assert lexer.get_token() == "=" - value = _parse_string(lexer.get_token()) + string_token = lexer.get_token() or "" + if string_token == "$": + string_token = lexer.get_token() or "" + value = _parse_string(string_token) # Grow the result array so that the index exists if index >= len(result): @@ -247,7 +259,7 @@ def _generate_indexed(array: IndexedArray) -> str: def _parse_assoc(lexer: shlex.shlex) -> AssociativeArray: """Parse an associative Bash array.""" assert lexer.get_token() == "(" - result = {} + result: AssociativeArray = {} while True: token = lexer.get_token() @@ -258,9 +270,13 @@ def _parse_assoc(lexer: shlex.shlex) -> AssociativeArray: assert token == "[" key = lexer.get_token() + assert key is not None assert lexer.get_token() == "]" assert lexer.get_token() == "=" - value = _parse_string(lexer.get_token()) + string_token = lexer.get_token() or "" + if string_token == "$": + string_token = lexer.get_token() or "" + value = _parse_string(string_token) result[key] = value @@ -283,14 +299,14 @@ def _parse_var(lexer: shlex.shlex) -> Tuple[str, Optional[Any]]: """Parse a variable declaration.""" flags_token = lexer.get_token() - if flags_token != "--": + if flags_token != "--" and flags_token is not None: var_flags = set(flags_token[1:]) else: var_flags = set() - var_name = lexer.get_token() + var_name: str = lexer.get_token() or "" var_value: Optional[Any] = None - lookahead = lexer.get_token() + lookahead = lexer.get_token() or "" if lookahead == "=": if "a" in var_flags: @@ -298,7 +314,10 @@ def _parse_var(lexer: shlex.shlex) -> Tuple[str, Optional[Any]]: elif "A" in var_flags: var_value = _parse_assoc(lexer) else: - var_value = _parse_string(lexer.get_token()) + string_token = lexer.get_token() or "" + if string_token == "$": + string_token = lexer.get_token() or "" + var_value = _parse_string(string_token) else: lexer.push_token(lookahead) diff --git a/scripts/toltec/builder.py b/scripts/toltec/builder.py index ee14b0e29..249162793 100644 --- a/scripts/toltec/builder.py +++ b/scripts/toltec/builder.py @@ -48,10 +48,13 @@ class BuildContextAdapter(logging.LoggerAdapter): def process( self, msg: str, kwargs: MutableMapping[str, Any] ) -> Tuple[str, MutableMapping[str, Any]]: + if self.extra is None: + return msg, kwargs + prefix = "" if "recipe" in self.extra: - prefix += self.extra["recipe"] + prefix += str(self.extra["recipe"]) if "arch" in self.extra: prefix += f" [{self.extra['arch']}]" @@ -657,7 +660,7 @@ def _archive(self, package: Package, pkg_dir: str) -> None: def _print_logs( self, logs: bash.LogGenerator, - function_name: str = None, + function_name: Optional[str] = None, max_lines_on_fail: int = 50, ) -> None: """ diff --git a/scripts/toltec/repo.py b/scripts/toltec/repo.py index af9c1ad28..62f9b3273 100644 --- a/scripts/toltec/repo.py +++ b/scripts/toltec/repo.py @@ -9,6 +9,7 @@ from enum import Enum, auto import logging import os +import shutil import textwrap from typing import Dict, Iterable, List, Optional, Set import requests @@ -55,10 +56,10 @@ def __init__(self, recipe_dir: str, repo_dir: str) -> None: self.repo_dir = repo_dir self.generic_recipes = {} - for name in os.listdir(self.recipe_dir): - if name[0] != ".": - self.generic_recipes[name] = GenericRecipe.from_file( - os.path.join(self.recipe_dir, name) + for entry in os.scandir(self.recipe_dir): + if entry.is_dir(): + self.generic_recipes[entry.name] = GenericRecipe.from_file( + entry.path ) def fetch_packages(self, remote: Optional[str]) -> GroupedPackages: @@ -266,3 +267,10 @@ def make_listing(self) -> None: # pylint: disable-next=unspecified-encoding with open(listing_path, "w") as listing_file: listing_file.write(template.render(sections=sections)) + + def make_compatibility(self) -> None: + """Generate the OS compatibility information file.""" + logger.info("Generating compatibility info") + compat_source = os.path.join(self.recipe_dir, "Compatibility") + compat_dest = self.repo_dir + shutil.copy2(compat_source, compat_dest)