diff --git a/.github/ISSUE_TEMPLATE/documentation-issue.md b/.github/ISSUE_TEMPLATE/documentation-issue.md new file mode 100644 index 000000000..90a044823 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation-issue.md @@ -0,0 +1,20 @@ +--- +name: Documentation Issue +about: Report an issue with the documentation +title: '' +labels: bug, documentation +assignees: '' + +--- + +**Describe the issue** +A clear and concise description of what the issue with the documentation is. + +**Potential resolution** +A clear and concise description of what you expected to happen. + +**Links** +If applicable, add links to the documentation in question. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/documentation-request.md b/.github/ISSUE_TEMPLATE/documentation-request.md new file mode 100644 index 000000000..93afde795 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation-request.md @@ -0,0 +1,20 @@ +--- +name: Documentation request +about: Request changes to the documentation +title: '' +labels: documentation +assignees: '' + +--- + +**Is your documentation request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/installation-issue.md b/.github/ISSUE_TEMPLATE/installation-issue.md new file mode 100644 index 000000000..9ac89311b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/installation-issue.md @@ -0,0 +1,31 @@ +--- +name: Installation issue +about: Report an issue with the installation process +title: '' +labels: bug, install +assignees: '' + +--- + +**Describe the issue** +A clear and concise description of what the issue is. + +**To Reproduce** +Steps to reproduce the behaviour: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behaviour** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Device information (please complete the following information):** + - Device: [e.g. reMarkable 2] + - OS version: [e.g. 2.15] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/package-issue.md b/.github/ISSUE_TEMPLATE/package-issue.md new file mode 100644 index 000000000..eae009fe4 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/package-issue.md @@ -0,0 +1,35 @@ +--- +name: Package Issue +about: Create a report to help us improve +title: '' +labels: bug, packages +assignees: '' + +--- + +**Describe the issue** +A clear and concise description of what the issue is. + +**To Reproduce** +Steps to reproduce the behaviour: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behaviour** +A clear and concise description of what you expected to happen. + +**Upstream issue** +If applicable, add the link to the upstream issue here. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Device/Package information (please complete the following information):** + - Device: [e.g. reMarkable 2] + - OS version: [e.g. 2.15] + - Package: [e.g. toltec-base 0.0.1-1] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/package-request.md b/.github/ISSUE_TEMPLATE/package-request.md new file mode 100644 index 000000000..9c00eae55 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/package-request.md @@ -0,0 +1,14 @@ +--- +name: Package request +about: Request a package be added to toltec +title: Add [package] to toltec +labels: packages +assignees: '' + +--- + +**Package information** +Add the name of the package, and a link to where the source can be found. + +**Reason for addition** +Provide some basic information about why you'd need this package, and what it provides that existing packages don't. diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 66c961ee6..3e34d796a 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -8,7 +8,7 @@ runs: sudo apt-get update -yq echo "aptVersion=libarchive-tools-$(apt-cache policy libarchive-tools | grep -oP '(?<=Candidate:\s)(.+)')" >> $GITHUB_ENV - name: Cache Apt packages - uses: actions/cache@v2 + uses: actions/cache@v4 id: cache-apt with: path: ~/.aptcache @@ -26,7 +26,7 @@ runs: sudo cp --verbose --force --recursive ~/.aptcache/* / fi - name: Cache shfmt - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: /usr/local/bin/shfmt key: 43439b996942b53dfafa9b6ff084f394555d049c98fb7ec37978f7668b43e1be @@ -44,7 +44,7 @@ runs: sudo chmod a+x "$install_dir"/shfmt fi - name: Cache Shellcheck - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: /usr/local/bin/shellcheck key: 64f17152d96d7ec261ad3086ed42d18232fcb65148b44571b564d688269d36c8 @@ -67,18 +67,21 @@ runs: sudo chown root:root shellcheck sudo mv shellcheck "$install_dir" fi + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: '3.12' - name: Cache Python environment - uses: actions/cache@v2 + uses: actions/cache@v4 id: cache-python with: - path: ${{ env.pythonLocation }} - key: ${{ env.pythonLocation }}-${{ hashFiles('requirements.txt') }} + path: .venv + key: .venv-${{ hashFiles('requirements.txt') }} - name: Install Python dependencies shell: bash env: CACHE_HIT: ${{ steps.cache-python.outputs.cache-hit }} run: | if [[ "$CACHE_HIT" != 'true' ]]; then - python -m pip install --upgrade pip - pip install -r requirements.txt + make .venv/bin/activate fi 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-labels.yml b/.github/workflows/pr-labels.yml index 67daf3ba2..166d3e256 100644 --- a/.github/workflows/pr-labels.yml +++ b/.github/workflows/pr-labels.yml @@ -5,7 +5,7 @@ on: jobs: check-labels: name: Check that PRs against the stable branch are labelled correctly - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Check labels run: | diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c2612f004..c6b30ff9b 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -4,14 +4,10 @@ on: jobs: lint: name: Check that it conforms to the style guide - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout the Git repository - uses: actions/checkout@v2 - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.8' + uses: actions/checkout@v4 - name: Setup Toltec dependencies uses: ./.github/actions/setup - name: Check formatting @@ -20,21 +16,29 @@ jobs: run: make lint pr: name: Check that it builds without error - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 needs: lint steps: - name: Checkout the Git repository - uses: actions/checkout@v2 - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.8' + uses: actions/checkout@v4 - name: Setup Toltec dependencies uses: ./.github/actions/setup - name: Build packages - run: make repo-new FLAGS='--remote-repo https://toltec-dev.org/${{ github.base_ref }}' + run: FLAGS='--remote-repo https://toltec-dev.org/${{ github.base_ref }}' make repo-new - name: Save the build output - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 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/.github/workflows/stable.yml b/.github/workflows/stable.yml index f610e8588..2ad14c7bf 100644 --- a/.github/workflows/stable.yml +++ b/.github/workflows/stable.yml @@ -6,14 +6,10 @@ on: jobs: stable: name: Build and publish the stable channel - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout the Git repository - uses: actions/checkout@v2 - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.8' + uses: actions/checkout@v4 - name: Setup Toltec dependencies uses: ./.github/actions/setup - name: Build packages @@ -33,9 +29,13 @@ jobs: GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} - name: Create Github Release continue-on-error: true - run: hub release create -t ${{ github.sha }} -m "${{ github.event.commits[0].message }}" $(date +%G-W%V-%u) + run: | + sudo apt-get update && sudo apt-get install -y hub + hub release create -t $SHA -m $MESSAGE $(date +%G-W%V-%u) env: + SHA: ${{ github.sha }} GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} + MESSAGE: ${{ github.event.commits[0].message }} - name: Send notification to Discord continue-on-error: true uses: ./.github/actions/discord-send diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index d391430ed..24446c870 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -6,14 +6,10 @@ on: jobs: testing: name: Build and publish the testing channel - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Checkout the Git repository - uses: actions/checkout@v2 - - name: Setup Python - uses: actions/setup-python@v2 - with: - python-version: '3.8' + uses: actions/checkout@v4 - name: Setup Toltec dependencies uses: ./.github/actions/setup - name: Build packages diff --git a/.gitignore b/.gitignore index 15b7bc855..fd35141df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ private -build +build/ +!scripts/build/ __pycache__ -.venv +.venv/ +repo/ diff --git a/Makefile b/Makefile index 8a6fe60f1..0ec4607ca 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,10 @@ RECIPES=$(shell ls package/) RECIPES_PUSH=$(foreach app, $(RECIPES), $(app)-push) RECIPES_CLEAN=$(foreach app, $(RECIPES), $(app)-clean) +ifeq ($(RUNNER_DEBUG), 1) +FLAGS+= --verbose +endif + define USAGE Building packages: @@ -44,19 +48,30 @@ export USAGE help: @echo "$$USAGE" -repo: +.venv/bin/activate: requirements.txt + @echo "Setting up development virtual env in .venv" + python -m venv .venv; \ + . .venv/bin/activate; \ + python -m pip install -r requirements.txt + +repo: .venv/bin/activate + . .venv/bin/activate; \ ./scripts/repo_build.py $(FLAGS) -repo-local: +repo-local: .venv/bin/activate + . .venv/bin/activate; \ ./scripts/repo_build.py --local $(FLAGS) -repo-new: +repo-new: .venv/bin/activate + . .venv/bin/activate; \ ./scripts/repo_build.py --diff $(FLAGS) -repo-check: +repo-check: .venv/bin/activate + . .venv/bin/activate; \ ./scripts/repo-check build/repo -$(RECIPES): %: +$(RECIPES): %: .venv/bin/activate + . .venv/bin/activate; \ ./scripts/package_build.py $(FLAGS) "$(@)" push: %: @@ -81,24 +96,28 @@ $(RECIPES_PUSH): %: "Make sure rsync is installed on your reMarkable."; \ fi -format: +format: .venv/bin/activate @echo "==> Checking Bash formatting" shfmt -d . @echo "==> Checking Python formatting" + . .venv/bin/activate; \ black --line-length 80 --check --diff scripts -format-fix: +format-fix: .venv/bin/activate @echo "==> Fixing Bash formatting" shfmt -l -w . @echo "==> Fixing Python formatting" + . .venv/bin/activate; \ black --line-length 80 scripts -lint: +lint: .venv/bin/activate @echo "==> Linting Bash scripts" - shellcheck $$(shfmt -f .) -P SCRIPTDIR +# shellcheck $$(shfmt -f .) -P SCRIPTDIR @echo "==> Typechecking Python files" + . .venv/bin/activate; \ MYPYPATH=scripts mypy --disallow-untyped-defs scripts @echo "==> Linting Python files" + . .venv/bin/activate; \ PYTHONPATH=: pylint scripts $(RECIPES_CLEAN): %: diff --git a/docs/building.md b/docs/building.md index 38d95e91b..b6cb816b4 100644 --- a/docs/building.md +++ b/docs/building.md @@ -1,7 +1,7 @@ ## Building the Repository from Source The Toltec repository is automatically built for each commit on the `stable` and `testing` branches. -You may want to build the repository locally when working with a new package recipe or to make sure that nobody tampered with the automated build system. +You may want to build the repository locally when working with a new package recipe or to make sure that nobody tampered with the automated build system. [Toltecmk](https://github.com/toltec-dev/build) could also be used instead, if you just need to compile a single standalone package. To proceed, create a local clone of the Git repository. @@ -18,7 +18,7 @@ Before running the build, make sure you have all the required dependencies: * Docker * bsdtar -* Python ⩾ 3.8 +* Python 3.10 You’ll also need all the Python modules listed in [requirements.txt](../requirements.txt) (install them by running `pip install --user -r requirements.txt` or using a [virtual environment](https://docs.python.org/3/tutorial/venv.html)). diff --git a/docs/package.md b/docs/package.md index fcd9690a4..072da60b5 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. @@ -328,7 +334,9 @@ math | Apps to assist the user in performing mathematical tasks. readers | Apps for reading and annotating documents (PDF, EPUB, …). screensharing | Apps for streaming the display between the PC and tablet. templates | Templates for xochitl notebooks. +splashscreens | Splashscreens for device startup, poweroff, suspend, etc. utils | System tools and various apps. +writing | Apps for writing text. If the package does not fit into one of the existing sections, you are free to create a new one and document it here. @@ -404,6 +412,21 @@ A list of packages that the current package replaces. Setting this field allows the current package to overwrite and take ownership of files from other packages. Note that the replaced packages will not be automatically uninstalled unless you also declare a conflict with them using the [`conflicts` field](#conflicts-field). +#### `provides` field + + + + + + + + + +
Required?No, defaults to () +
TypeArray of strings
+ +A list of virtual packages that the current package provides. + #### `package()` function The `package()` function populates the `$pkgdir` directory with the files and directories that need to be installed using artifacts from the `$srcdir` directory. @@ -439,3 +462,12 @@ When upgrading a package from version A to B, the following happens: * `postupgrade B`, if it exists, is called from version A * New package files are unpacked and installed * `configure`, if it exists, is called from version B + + +### reload-oxide-apps hook + +If a package contains one or more files in `/opt/etc/draft` or `/opt/usr/share/applications` the `reload-oxide-apps` method in `install-lib` will be appended to the following: + +* `configure` +* `postupgrade` +* `postremove` diff --git a/package/7zip/package b/package/7zip/package new file mode 100644 index 000000000..28a2e3275 --- /dev/null +++ b/package/7zip/package @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 The Toltec Contributors +# SPDX-License-Identifier: MIT +pkgnames=(7zip) +pkgdesc="Metapackage for 7-zip" +url="https://www.7-zip.org/" +section="utils" +pkgver=23.01-2 +timestamp=2023-06-20T00:00:00Z +maintainer="Eeems " +license=LGPL-2.1-or-later +installdepends=(7-zip) + +package() { + true +} 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/appmarkable/package b/package/appmarkable/package index 136491f19..d2c31f358 100644 --- a/package/appmarkable/package +++ b/package/appmarkable/package @@ -5,17 +5,17 @@ pkgnames=(appmarkable) pkgdesc="Front-end for apps that do not have a graphical user interface" url="https://github.com/LinusCDE/appmarkable" -pkgver=0.0.0-11 -timestamp=2021-03-10T18:36Z +pkgver=0.1.3-1 +timestamp=2024-06-01T21:00Z section="devel" maintainer="Linus K. " license=MIT installdepends=(display) flags=(patch_rm2fb) -image=rust:v2.1 -source=(https://github.com/LinusCDE/appmarkable/archive/c44ee87ea2b1f1e41c9592476c076150c9a1acf4.zip) -sha256sums=(76e151aeae0f18b206dd3c6258bf74bcb5256ee2f803e1ed2073278831158f60) +image=rust:v3.1 +source=(https://github.com/LinusCDE/appmarkable/archive/0463ffc5bdaf29ff0a0e92fb15a90b06e310c417.zip) +sha256sums=(bb45ed03a360f1a58e58e5a8e3176008e8e63053fc46925d20be92b532a02822) build() { # Fall back to system-wide config diff --git a/package/bandwhich/package b/package/bandwhich/package new file mode 100644 index 000000000..c9c1243a7 --- /dev/null +++ b/package/bandwhich/package @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(bandwhich) +pkgdesc="CLI network utilization tool" +url=https://github.com/imsnif/bandwhich +pkgver=0.22.2-1 +timestamp=2024-01-27T19:33Z +section="utils" +maintainer="gbyl " +license=MIT + +image=rust:v3.1 +source=("https://github.com/imsnif/bandwhich/archive/refs/tags/v${pkgver%-*}.zip") +sha256sums=(5d1eaa1796ec3c16f349cb6b00bd9dba6d425e9323d63af648a41cd68c5d456b) + +build() { + cargo build --release +} + +package() { + install -D -m 755 "$srcdir"/target/armv7-unknown-linux-gnueabihf/release/bandwhich "$pkgdir"/opt/bin/bandwhich +} diff --git a/package/calculator/package b/package/calculator/package index 072063a15..092ef00d6 100644 --- a/package/calculator/package +++ b/package/calculator/package @@ -5,7 +5,7 @@ pkgnames=(calculator) pkgdesc="Touch-based calculator" url=https://github.com/reHackable/Calculator -pkgver=0.0.0-15 +pkgver=0.0.0-16 timestamp=2020-08-20T12:28Z section="math" maintainer="Mattéo Delabre " diff --git a/package/changescrn/package b/package/changescrn/package new file mode 100644 index 000000000..f45f98023 --- /dev/null +++ b/package/changescrn/package @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Copyright (c) 2020 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(changescrn) +pkgdesc="Change sleep/suspend/poweroff/reboot screens" +url=https://github.com/pr0fsmith/rMscreens/ +pkgver=1.0.0-2 +timestamp=2022-03-15T01:28:33Z +section="utils" +maintainer="pr0fsmith " +license=GPL-3.0 + +source=(https://github.com/pr0fsmith/rMscreens/archive/6d04e97b3997873f0f8b1bd50283ae7ed9be7abd.zip) +sha256sums=(3c2e8b0952d848d7326c0a4ce45da625dd7fd0fbc6b564a2d40c3b97015138e3) + +package() { + install -Dm755 "$srcdir"/changescrn "$pkgdir/opt/bin/changescrn" +} + +configure() { + if [ ! -d /opt/usr/share/backupscrns ] || [ -z "$(ls -A /opt/usr/share/backupscrns)" ]; then + changescrn -b + fi +} + +preremove() { + changescrn -r all +} diff --git a/package/chessmarkable/package b/package/chessmarkable/package index f8a4b50bd..6258ab355 100644 --- a/package/chessmarkable/package +++ b/package/chessmarkable/package @@ -5,7 +5,7 @@ pkgnames=(chessmarkable) pkgdesc="Chess game" url=https://github.com/LinusCDE/chessmarkable -pkgver=0.8.0-1 +pkgver=0.8.0-2 timestamp=2021-07-22T12:04Z section="games" maintainer="Linus K. " diff --git a/package/ddvk-hacks/package b/package/ddvk-hacks/package index 61c8c76ea..edf8b1f12 100644 --- a/package/ddvk-hacks/package +++ b/package/ddvk-hacks/package @@ -2,61 +2,75 @@ # 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=35.01-1 -timestamp=2022-07-09T00:05:57+0200 +pkgver=39.01-4 +timestamp=2022-11-09T18:31:51Z section="readers" maintainer="Mattéo Delabre " license=MIT flags=(nostrip) +conflicts=(webinterface-onboot signature-rm) -source=(https://github.com/ddvk/remarkable-hacks/archive/5e5aabf1dfe02b802a3ce8ce1046bd05fe29ffd2.zip) -sha256sums=(cb47f0291f8712a8df563bb6a5793fd2b699074fe055d56c40efe987eb5f7571) +source=(https://github.com/ddvk/remarkable-hacks/archive/90e7e3e7ffc269373de191085453be50c9f8da0c.zip) +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 - 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 + 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 } @@ -67,12 +81,32 @@ 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") + patch_version="39.1.01" + original_hash="1c01bae469a2e29846c68758e2cae4a2b8b5055d" + xochitl_version="2.15.1.1189" + ;; + "20221003074737") + patch_version="38.1.03" + original_hash="a3ce408c8a717d48746e361336532924f5ff40f2" + xochitl_version="2.15.0.1067" + ;; + "20220921102803") + patch_version="37.1.01" + original_hash="011742f027b70f37a0da293132daafcfc82b537d" + xochitl_version="2.14.3.1047" + ;; + "20220825122914") + patch_version="36.1.01" + original_hash="a88faec812ae20960bfbab38be0aa49aafec902a" + xochitl_version="2.14.3.977" + ;; "20220617142418") patch_version="35.1.01" - original_hash="d172016ac8a97ca5df3c551648e0b3314f17f72a" + original_hash="a052dfbe587851d17146e586e4be65819f1360e3" xochitl_version="2.14.1.866" ;; "20220615075543") @@ -148,9 +182,29 @@ configure() { exit 1 ;; esac - elif [[ $arch = rm2 ]]; then + elif [[ $arch = rm2os2 ]]; then device="reMarkable 2" case "$build_date" in + "20221026104022") + patch_version="39.2.01" + original_hash="64e3cb3d05aec4a40624ebfc730e480358e1b184" + xochitl_version="2.15.1.1189" + ;; + "20221003075633") + patch_version="38.2.03" + original_hash="fcd3c84215c5457d455419831760304736f3b694" + xochitl_version="2.15.0.1067" + ;; + "20220921101206") + patch_version="37.2.01" + original_hash="47c3ad26651f604be5de901881a8a44f9124a79c" + xochitl_version="2.14.3.1047" + ;; + "20220825124750") + patch_version="36.2.01" + original_hash="470e88f8d5fb62f64939fe4ea3b89c515113f7e5" + xochitl_version="2.14.3.977" + ;; "20220617143306") patch_version="35.2.01" original_hash="1d7f6f049e5a6b192caaf07cbf67ba7c2555e5f0" @@ -277,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" @@ -291,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/display/package b/package/display/package index f5d7b307e..633b4e9f5 100644 --- a/package/display/package +++ b/package/display/package @@ -4,11 +4,11 @@ archs=(rm1 rm2) pkgnames=(display rm2fb-client) -timestamp=2022-06-22T13:16:48Z +timestamp=2023-08-27T02:39:10Z maintainer="raisjn " license=MIT url="https://github.com/ddvk/remarkable2-framebuffer" -pkgver=1:0.0.20-1 +pkgver=1:0.0.33-3 _release="${pkgver%-*}" _release="v${_release#*:}" _libver=1.0.1 @@ -23,7 +23,7 @@ source=( rm2fb-preload.env ) sha256sums=( - 02acb6c77e4b9b973151ba6eb4e6093a0f7733d9aeca513ecbc36f6008acda89 + dd57f1ba31f08a28d801989e9a705bd93cc637cd8f4dffa160412119e69329ff SKIP SKIP SKIP @@ -64,21 +64,26 @@ display() { configure() { if [[ $arch = rm2 ]]; then systemctl daemon-reload - systemctl enable rm2fb --now - # Restart xochitl if it's running - if systemctl --quiet is-active xochitl; then - # Reset the crash count so we don't trigger remarkable-fail - echo "0" > /tmp/crashnum - systemctl restart xochitl + if systemctl enable rm2fb --now; then + # Restart xochitl if it's running + if is-active xochitl; then + # Reset the crash count so we don't trigger remarkable-fail + echo "0" > /tmp/crashnum + systemctl restart xochitl + fi + else + disable-unit rm2fb.service + echo "Failed to start rm2fb. Keeping it disabled for now." + echo "Please check the logs and open an issue:" + echo " https://github.com/toltec-dev/toltec/issues/new" + exit 1 fi fi } preremove() { if [[ $arch = rm2 ]]; then - if systemctl list-units --full -all | grep -Fq 'rm2fb.service'; then - systemctl disable rm2fb --now - fi + disable-unit rm2fb.service echo -n "make sure " if ! is-enabled xochitl.service; then echo "to re-enable xochitl with 'systemctl enable xochitl --now'" @@ -97,14 +102,16 @@ rm2fb-client() { replaces=(rm2fb) package() { - libname="librm2fb_client.so.$_libver" - install -D -m 644 -t "$pkgdir"/opt/lib "$srcdir"/src/client/"$libname" + libname="librm2fb_client.so" + libnamever="$libname.$_libver" + install -D -m 644 -t "$pkgdir"/opt/lib "$srcdir"/src/client/"$libnamever" install -d "$pkgdir"/usr/lib - ln -s /opt/lib/"$libname" "$pkgdir"/usr/lib/"$libname" + ln -s /opt/lib/"$libnamever" "$pkgdir"/usr/lib/"$libnamever" + ln -s /opt/lib/"$libnamever" "$pkgdir"/opt/lib/"$libname" for dest in opt/lib usr/lib; do - ln -s "$libname" "$pkgdir/$dest/${libname%.*.*}" - ln -s "$libname" "$pkgdir/$dest/${libname%.*}" + ln -s "$libnamever" "$pkgdir/$dest/${libnamever%.*.*}" + ln -s "$libnamever" "$pkgdir/$dest/${libnamever%.*}" done install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/rm2fb-client diff --git a/package/display/rm2fb-preload.env b/package/display/rm2fb-preload.env index 910b04299..99ec3959c 100644 --- a/package/display/rm2fb-preload.env +++ b/package/display/rm2fb-preload.env @@ -3,7 +3,7 @@ # Please do not modify files shipped by Toltec, or they risk being # overwritten with updates. Instead create your own files in this directory. if [[ -f /dev/shm/swtfb.01 ]]; then - export LD_PRELOAD=/opt/lib/librm2fb_client.so.1 + export LD_PRELOAD="$LD_PRELOAD:/opt/lib/librm2fb_client.so.1" else echo "rm2fb server is not running: starting without rm2fb client" fi diff --git a/package/doomarkable/package b/package/doomarkable/package index 14863079f..3e5ae8735 100644 --- a/package/doomarkable/package +++ b/package/doomarkable/package @@ -5,7 +5,7 @@ pkgnames=(doomarkable) pkgdesc="DOOM game" url=https://github.com/LinusCDE/doomarkable -pkgver=0.4.1-1 +pkgver=0.4.1-2 timestamp=2021-10-31T16:15Z section="games" maintainer="Linus K. " diff --git a/package/draft/launcherctl-draft b/package/draft/launcherctl-draft new file mode 100644 index 000000000..a3c0b9db2 --- /dev/null +++ b/package/draft/launcherctl-draft @@ -0,0 +1,93 @@ +#!/bin/bash +set -e +draft_pid() { + systemctl show --no-pager --property MainPID draft.service | sed 's|MainPID=||' +} +kill_pid() { + pid="$1" + if [[ "$(awk '{print $3}' "/proc/${pid}/stat")" == "T" ]]; then + kill -CONT "$pid" + fi + kill -TERM "$pid" + # Wait 5s for process to exit + start="$(date +'%s')" + while kill -0 "$pid" 2> /dev/null; do + sleep 0.5 + if [ "$(date +'%s')" -gt $((start + 5)) ]; then + break + fi + done + if kill -0 "$pid" 2> /dev/null; then + # If process is still running, force kill it + kill -KILL "$pid" + fi +} +case "$1" in + is-active) + systemctl is-active --quiet draft.service + ;; + is-enabled) + systemctl is-enabled --quiet draft.service + ;; + logs) + if [ $# -eq 2 ] && [[ "$2" == "-f" ]] || [[ "$2" == "--follow" ]]; then + journalctl --follow --all --unit draft.service + else + journalctl --no-pager --all --unit draft.service + fi + ;; + start) + systemctl start draft.service + ;; + stop) + systemctl stop draft.service + ;; + enable) + systemctl enable draft.service + ;; + disable) + systemctl disable draft.service + ;; + apps) + find {/opt,}/etc/draft -maxdepth 1 -type f | while read -r file; do + grep 'name=' "$file" | sed 's|^name=||' + done + ;; + close) + find {/opt,}/etc/draft -maxdepth 1 -type f | while read -r file; do + if [[ "$(grep 'name=' "$file" | sed 's|^name=||')" == "$2" ]]; then + term="$(grep 'term=' "$file" | sed 's|^term=||')" + if [ -z "$term" ]; then + echo "No term= configuration specified for ${2}" + exit 1 + fi + $term + call="$(grep 'call=' "$file" | sed 's|^call=||')" + name="$(grep 'name=' "$file" | sed 's|^name=||')" + /opt/libexec/ps-procps-ng --ppid "$(draft_pid)" -o pid | tail -n +2 | while read -r pid; do + if [[ "$(tr -d '\0' < "/proc/${pid}/cmdline")" == "$call" ]]; then + kill_pid "$pid" + break + fi + done + fi + done + ;; + running) + pid=$(draft_pid) + find {/opt,}/etc/draft -maxdepth 1 -type f | while read -r file; do + call="$(grep 'call=' "$file" | sed 's|^call=||')" + name="$(grep 'name=' "$file" | sed 's|^name=||')" + /opt/libexec/ps-procps-ng --ppid "$(draft_pid)" -o pid | tail -n +2 | while read -r pid; do + if [[ "$(tr -d '\0' < "/proc/${pid}/cmdline")" == "$call" ]]; then + echo "$name" + break + fi + done + done + ;; + *) + echo "Draft does not support this method" + exit 1 + ;; +esac diff --git a/package/draft/package b/package/draft/package index 2234c85f0..81610e407 100644 --- a/package/draft/package +++ b/package/draft/package @@ -5,22 +5,24 @@ pkgnames=(draft) pkgdesc="Launcher which wraps around the standard interface" url=https://github.com/dixonary/draft-reMarkable -pkgver=0.2.0-21 +pkgver=0.2.0-25 timestamp=2020-07-20T10:23Z section="launchers" maintainer="Mattéo Delabre " license=Apache-2.0 -installdepends=(xochitl display) +installdepends=(xochitl display procps-ng-ps) flags=(patch_rm2fb) image=qt:v2.1 source=( https://github.com/dixonary/draft-reMarkable/archive/5bd660a2fd07eba166c6110d2b48cfc58ee67e58.zip draft.service + launcherctl-draft ) sha256sums=( c41d7a4fd537c54d787018fd764421dbf7dd64306ca800875283e05eef99173e SKIP + SKIP ) build() { @@ -46,23 +48,24 @@ package() { mv "$pkgdir"/opt/etc/draft/{99-,}shutdown install -D -m 644 -t "$pkgdir"/lib/systemd/system "$srcdir"/draft.service + install -D -T -m 755 "$srcdir"/launcherctl-draft "$pkgdir"/opt/share/launcherctl/"$pkgname" } configure() { systemctl daemon-reload - if ! is-enabled "$pkgname.service"; then + if ! launcherctl is-current-launcher "$pkgname"; then echo "" echo "Run the following command(s) to use $pkgname as your launcher" - how-to-enable "$pkgname.service" + echo "launcherctl switch-launcher --start $pkgname" echo "" fi } preremove() { - if systemctl list-units --full -all | grep -Fq "$pkgname.service"; then - echo "Disabling $pkgname" - systemctl disable --now "$pkgname" + # Just in case more than one launcher is active, do individual checks + if launcherctl is-active-launcher "$pkgname" || launcherctl is-enabled-launcher "$pkgname"; then + launcherctl switch-launcher --start xochitl fi } diff --git a/package/entware-rc/entware-rc@.service b/package/entware-rc/entware-rc@.service new file mode 100644 index 000000000..f76fb3466 --- /dev/null +++ b/package/entware-rc/entware-rc@.service @@ -0,0 +1,13 @@ +[Unit] +Description=Entware %I service +After=opt.mount + +[Service] +ExecStart=/opt/etc/init.d/%I start +ExecStop=/opt/etc/init.d/%I stop +Type=forking +GuessMainPID=true +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/package/entware-rc/package b/package/entware-rc/package new file mode 100644 index 000000000..40b8432f4 --- /dev/null +++ b/package/entware-rc/package @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 The Toltec Contributors +# SPDX-License-Identifier: MIT + +archs=(rmall) +pkgnames=(entware-rc) +pkgdesc="Manage entware installed services" +url=https://toltec-dev.org/ +pkgver=0.1-1 +timestamp=2024-05-22T22:59:03Z +section="utils" +maintainer="Eeems " +license=MIT +installdepends=() + +source=( + entware-rc@.service + rcctl +) +sha256sums=( + SKIP + SKIP +) + +package() { + install -D -m 666 -t "$pkgdir"/lib/systemd/system/ "$srcdir"/entware-rc@.service + install -D -m 755 -t "$pkgdir"/opt/bin/ "$srcdir"/rcctl +} + +configure() { + systemctl daemon-reload + echo "" + echo "You can use rcctl to manage services installed by entware" +} + +preremove() { + rcctl list | xargs -I {} systemctl disable --now entware-rc@{} +} diff --git a/package/entware-rc/rcctl b/package/entware-rc/rcctl new file mode 100755 index 000000000..899ae7862 --- /dev/null +++ b/package/entware-rc/rcctl @@ -0,0 +1,62 @@ +#!/bin/bash +help() { + echo "Usage: rcctl " + echo " commands:" + echo " help: Display this message and exit" + echo " start : Start a service" + echo " stop : Stop a service" + echo " restart : Restart a service" + echo " enable : Enable service startup on boot" + echo " disable : Disable service startup on boot" + echo " status []: View the current status of services" + echo " logs [-f|--follow] : View logs for a service" + echo " list: List available services" +} +if [[ $1 == "help" ]] || [[ $1 == "--help" ]]; then + help +elif [[ $1 == "start" ]] \ + || [[ $1 == "stop" ]] \ + || [[ $1 == "restart" ]] \ + || [[ $1 == "enable" ]] \ + || [[ $1 == "disable" ]]; then + if [ $# -ge 3 ]; then + echo "Too many arguments" + exit 1 + elif [ $# -lt 2 ]; then + echo "Too few arguments" + exit 1 + fi + systemctl "$1" "entware-rc@$2.service" +elif [[ $1 == "status" ]]; then + if [ $# -ge 3 ]; then + echo "Too many arguments" + exit 1 + elif [ $# -eq 1 ]; then + "$0" list | xargs -rn1 "$0" status + else + s="entware-rc@${2}.service" + echo "${2}" "$(systemctl is-active "${s}")" "$(systemctl is-enabled "${s}")" \ + | grep --color=always '\(disabled\|inactive\|$\)' + fi +elif [[ $1 == "logs" ]]; then + if [ $# -ge 4 ]; then + echo "Too many arguments" + exit 1 + elif [ $# -lt 2 ]; then + echo "Too few arguments" + exit 1 + elif [ $# -eq 3 ] && [[ "$2" != "-f" ]] && [[ "$2" != "--follow" ]]; then + echo "Invalid arguments" + exit 1 + fi + if [ $# -eq 3 ]; then + journalctl --no-pager -all --follow --unit "entware-rc@${3}.service" + else + journalctl --no-pager -all --unit "entware-rc@${2}.service" + fi +elif [[ $1 == "list" ]]; then + /opt/bin/find /opt/etc/init.d/ -perm '-u+x' -name 'S*' | xargs -rn1 basename +else + help + exit 1 +fi diff --git a/package/fbink/package b/package/fbink/package index 8f5caf974..504bca3f3 100644 --- a/package/fbink/package +++ b/package/fbink/package @@ -4,8 +4,8 @@ pkgnames=(fbink fbdepth fbink-doom) url=https://github.com/NiLuJe/FBInk -pkgver=1.24.0-1 -timestamp=2021-03-25T23:41:13Z +pkgver=1.25.0-1 +timestamp=2022-12-05T02:50:38Z maintainer="Mattéo Delabre " license=GPL-3.0 installdepends=(display) diff --git a/package/fingerterm/package b/package/fingerterm/package index 03dc4956e..80a8ea8e7 100644 --- a/package/fingerterm/package +++ b/package/fingerterm/package @@ -5,7 +5,7 @@ pkgnames=(fingerterm) pkgdesc="Terminal emulator with an on-screen touch keyboard" url=https://github.com/dixonary/fingerterm-reMarkable -pkgver=1.3.5-14 +pkgver=1.3.5-15 timestamp=2020-10-27T12:02Z section="admin" maintainer="Mattéo Delabre " diff --git a/package/folly/package b/package/folly/package index 2682d2c7d..80a788d08 100644 --- a/package/folly/package +++ b/package/folly/package @@ -5,13 +5,13 @@ pkgnames=(folly) pkgdesc="Z-machine interpreter for interactive fiction" url="https://github.com/bkirwi/folly" -pkgver=0.0.1-3 +pkgver=0.0.1-4 timestamp=2022-04-18T17:50:16Z section=games maintainer="Ben Kirwin " license=MIT installdepends=(display) -makedepends=(build:librust-clang-sys-dev build:libclang-dev build:libc6 build:libc6-dev build:clang) +makedepends=(build:libclang-14-dev build:clang-14 build:llvm-14-dev) image=rust:v2.3 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/gocryptfs/package b/package/gocryptfs/package index 2c7965ae1..c6b4dd8e9 100644 --- a/package/gocryptfs/package +++ b/package/gocryptfs/package @@ -2,11 +2,12 @@ # Copyright (c) 2020 The Toltec Contributors # SPDX-License-Identifier: MIT +archs=(rmallos2) pkgnames=(gocryptfs) pkgdesc="An encrypted overlay filesystem written in Go." url="https://nuetzlich.net/gocryptfs/" _srcver=2.0-beta2 -pkgver="$_srcver"-2 +pkgver="$_srcver"-3 timestamp=2021-03-22 section=utils maintainer="plan5 <30434574+plan5@users.noreply.github.com>" diff --git a/package/innernet/package b/package/innernet/package index 61f08ff16..b34064f7a 100644 --- a/package/innernet/package +++ b/package/innernet/package @@ -1,25 +1,26 @@ #!/usr/bin/env bash -# Copyright (c) 2021 The Toltec Contributors +# Copyright (c) 2024 The Toltec Contributors # SPDX-License-Identifier: MIT +archs=(rmallos2) pkgnames=(innernet-client) pkgdesc="A private network system that uses WireGuard under the hood." url="https://github.com/tonarino/innernet" -pkgver=1.5.3-2 -timestamp=2022-01-31T20:08:43Z +pkgver=1.6.1-1 +timestamp=2024-01-19T14:24:40Z section="utils" maintainer="plan5 <30434574+plan5@users.noreply.github.com>" license=MIT installdepends=(wireguard) makedepends=(build:librust-clang-sys-dev build:libclang-dev build:libc6 build:libc6-dev build:clang) -image=rust:v2.2.2 +image=rust:v3.1 _srcver="v${pkgver%-*}" source=( "https://github.com/tonarino/innernet/archive/refs/tags/$_srcver.zip" ) sha256sums=( - 2f7ca1d802d898b1c4fd090cba9e0562a1e80d617b55f23ba596e81c99441a1c + fd9ec6eb75dcc46c818696e7fcb87eb772dc024e0c326360f0f8c473c937c37c ) prepare() { @@ -42,9 +43,6 @@ package() { install -D -m 700 -t "$pkgdir"/opt/bin "$srcdir"/target/armv7-unknown-linux-gnueabihf/release/innernet install -D -m 644 -t "$pkgdir"/lib/systemd/system "$srcdir/client/innernet@.service" install -D -m 644 -t "$pkgdir"/lib/systemd/system "$srcdir/client/innernet.target" - - # Link /opt/bin/innernet to /opt/bin/inn - ln -s /opt/bin/innernet "$pkgdir"/opt/bin/inn } configure() { @@ -52,3 +50,12 @@ configure() { mkdir -p /opt/var/lib/innernet fi } + +preremove() { + disable-unit innernet.target + disable-unit innernet@.service +} + +postremove() { + systemctl daemon-reload +} diff --git a/package/kernelctl/kernelctl b/package/kernelctl/kernelctl new file mode 100644 index 000000000..5ad691d85 --- /dev/null +++ b/package/kernelctl/kernelctl @@ -0,0 +1,247 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 The Toltec Contributors +# SPDX-License-Identifier: MIT + +# kernel staging dir +kernelctl_dir=/opt/usr/share/kernelctl + +# Formatting +bf="\033[1m" # bold +sf="\033[0m" # standard +gr="\033[1;32m" # green +bl="\033[1;34m" # blue + +# change our working directory to / to ease filesystem operations +cd / + +# find current os version +os_version=$(awk -F= '/RELEASE_VERSION/{print $2}' /usr/share/remarkable/update.conf) + +help() { + read -r -d '' msg <<- EOM + Usage: $(basename "$0") COMMAND + Manage your booting kernel. + + ${gr}Available commands:${sf} + ${bf} backup ${sf}Backup current kernel and name it . This is guaranteed to work only with vanilla (i.e. upstream) kernels. + ${bf} help ${sf}Show this help message. + ${bf} list ${sf}List available kernels. + ${bf} show ${sf}Show the current configured kernel. + ${bf} delete ${sf}Delete kernel from the staging dir. WARNING this is irreversible. + ${bf} prune ${sf}Delete all backups of vanilla kernels older than the one that shipped with the current software version. WARNING this is irreversible. + ${bf} set ${sf}Change booting kernel. + + ${bf} ${sf}Kernel name or number (from 'list' command) or "default" to revert to the upstram kernel. + EOM + echo -e "$msg" +} + +# backup current kernel +backup() { + if [[ "$1" = "vanilla" ]]; then + kernel_name="vanilla-$os_version" + else + kernel_name=$1 + fi + + kernel_file="$kernelctl_dir"/"$kernel_name".tar.bz2 + + if [[ -e "$kernel_file" ]]; then + read -r -d "" msg <<- EOM + It looks like there is already copy of $kernel_name in the staging area. + If you really want to back it up again please run + + $(basename "$0") delete $kernel_name + $(basename "$0") backup $kernel_name + EOM + echo -e "$msg" + exit 1 + else + tar cpjf "$kernel_file" lib/modules/* boot/zImage* boot/*.dtb + rm -f "$kernelctl_dir"/current.tar.bz2 + ln "$kernel_file" "$kernelctl_dir"/current.tar.bz2 + fi +} + +# get available kernels +get_kernel_names() { + mapfile -t kernel_names < <(find "$kernelctl_dir" -path "*.tar.bz2" ! -name current.tar.bz2 -print0 | xargs -0 -I"{}" basename {} .tar.bz2) +} + +# get current kernel +get_current_kernel_name() { + if [[ -e "$kernelctl_dir"/current.tar.bz2 ]]; then + current_kernel_name=$(find "$kernelctl_dir" -samefile "$kernelctl_dir"/current.tar.bz2 ! -name current.tar.bz2 -print0 | xargs -0 -I"{}" basename {} .tar.bz2) + else + current_kernel_name='' + fi +} + +# translate input into a kernel name +to_kernel_name() { + local ker + get_kernel_names + if [[ "$1" =~ ^[0-9]+$ ]] && ((0 < $1 && $1 <= ${#kernel_names[@]})); then + echo "${kernel_names[$(($1 - 1))]}" + return + elif [[ "$1" = "default" ]]; then + ker="vanilla-$os_version" + else + ker="$1" + fi + if [[ $(echo "${kernel_names[@]}" | grep -ow "$ker" | wc -w) -gt 0 ]]; then + echo "$ker" + else + echo "Can't find $ker in the staging area." + exit 1 + fi +} + +# list available kernels +list() { + get_kernel_names + get_current_kernel_name + echo -e "${gr}Available kernels:${sf}" + for i in "${!kernel_names[@]}"; do + if [[ "$current_kernel_name" = "${kernel_names[$i]}" ]]; then cur=" ${bl}*${sf}"; else cur=""; fi + echo -e " ${bf}[$((i + 1))]${sf}\t${kernel_names[$i]}$cur" + done +} + +# show the current configured kernel +show() { + get_current_kernel_name + if [[ "$current_kernel_name" = "" ]]; then + echo -e "${bf}There is no link to the current running kernel in the staging area.${sf}" + else + echo -e "${gr}Current kernel:${sf}" + echo -e " ${bf}${current_kernel_name}${sf}" + fi +} + +# actually switch kernels +switch() { + tar tjf "$1" | sort -r | xargs -r -I {} bash -c 'if [[ -d "{}" ]]; then rmdir "{}"; else rm "{}"; fi' + tar xpjf "$2" +} + +# change the kernel that will boot next time +set() { + new_kernel_name=$(to_kernel_name "$1") + new_kernel_file="${kernelctl_dir}/${new_kernel_name}.tar.bz2" + current_kernel_file="${kernelctl_dir}/current.tar.bz2" + if [[ ! -e "$current_kernel_file" ]]; then + read -r -d '' msg <<- EOM + ${bf}There is no link to the current running kernel in the staging + area, you might have accidentally deleted it!${sf} + Try making a backup first. + EOM + echo -e "$msg" + exit 1 + fi + if switch "$current_kernel_file" "$new_kernel_file"; then + rm -f "$current_kernel_file" + ln "$new_kernel_file" "$current_kernel_file" + /bin/sync + echo "Reboot system to use your newly installed kernel." + else + read -r -d '' msg <<- EOM + ${bf}WARNING: failed to extract the new kernel!${sf} + This may be due to a lack of space in the root partition. + Attempting to revert to the current running kernel. + EOM + echo -e "$msg" + if switch "$new_kernel_file" "$current_kernel_file"; then + /bin/sync + read -r -d '' msg <<- EOM + Successfully reverted to the current running kernel. + Please check that everything is in order before rebooting. + EOM + echo -e "$msg" + else + read -r -d '' msg <<- EOM + Unable to revert to a working configuration. + If you do not know how to proceed, please do not reboot your device, + do not let the battery die, and seek assistance + in the reMarkable's community Discord server: https://discord.gg/ATqQGfu + EOM + echo -e "$msg" + exit 1 + fi + fi +} + +# delete kernel from staging dir +delete() { + kernel_name=$(to_kernel_name "$1") + echo "Deleting $kernel_name from the staging area is irreversible." + echo "If the kernel was installed as a toltec package this may confuse the package manager" + echo -n "Do you want to proceed? [N/y]: " + read -r ans + if [[ "$ans" = "y" || "$ans" = "Y" ]]; then + rm "${kernelctl_dir}/${kernel_name}.tar.bz2" + fi +} + +prune() { + echo "Deleting backups of old vanilla kernel(s) from the staging area is irreversible." + echo -n "Do you want to proceed? [N/y]: " + read -r ans + if [[ "$ans" = "y" || "$ans" = "Y" ]]; then + mapfile -t filenames < <(find "$kernelctl_dir" -path "*vanilla-*.tar.bz2" ! -name vanilla-"$os_version".tar.bz2) + for filename in "${filenames[@]}"; do + rm "$filename" + done + fi +} + +if [[ $0 = "${BASH_SOURCE[0]}" ]]; then + if [[ $# -eq 0 ]]; then + help + exit 1 + fi + + action="$1" + shift + + case $action in + help | -h | --help) + help + ;; + list) + list + ;; + show) + show + ;; + backup) + if [[ $# -ne 1 ]]; then + help + exit 1 + fi + backup "$1" + ;; + set) + if [[ $# -ne 1 ]]; then + help + exit 1 + fi + set "$1" + ;; + delete) + if [[ $# -ne 1 ]]; then + help + exit 1 + fi + delete "$1" + ;; + prune) + prune + ;; + *) + echo -e "Error: Invalid command '$action'\n" + help + exit 1 + ;; + esac +fi diff --git a/package/kernelctl/package b/package/kernelctl/package new file mode 100644 index 000000000..31acac595 --- /dev/null +++ b/package/kernelctl/package @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(kernelctl) +pkgdesc="Manage aftermarket kernels" +url=https://toltec-dev.org/ +pkgver=0.2-1 +timestamp=2022-11-12T00:00Z +section="utils" +maintainer="Salvatore Stella " +license=MIT + +source=( + kernelctl +) +sha256sums=( + SKIP +) + +package() { + install -D -m 744 -t "$pkgdir"/opt/bin "$srcdir"/kernelctl + install -d "$pkgdir"/opt/usr/share/kernelctl + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" +} + +configure() { + os_version=$(awk -F= '/RELEASE_VERSION/{print $2}' /usr/share/remarkable/update.conf) + if [[ "$(kernelctl list | tail -n +2 | awk '{print $2}' | grep "vanilla-$os_version")" == "" ]]; then + echo "Creating a backup of the currently running kernel." + kernelctl backup vanilla + fi +} + +preremove() { + os_version=$(awk -F= '/RELEASE_VERSION/{print $2}' /usr/share/remarkable/update.conf) + if [[ "$(kernelctl show | tail -n 1 | grep "vanilla-$os_version")" == "" ]]; then + if [[ "$(kernelctl list | tail -n +2 | awk '{print $2}' | grep "vanilla-$os_version")" == "" ]]; then + echo "Unable to restore default kernel." + echo "To force removal, you can run the following:" + echo " opkg remove --force-remove kernelctl" + echo "Warning: This will not leave you in a stock state" + exit 1 + else + echo "Restoring default kernel" + kernelctl set default + fi + fi +} diff --git a/package/keywriter/package b/package/keywriter/package index 542a6359d..32ab6d891 100644 --- a/package/keywriter/package +++ b/package/keywriter/package @@ -5,7 +5,7 @@ pkgnames=(keywriter) pkgdesc="Markdown-enabled free writing app" url=https://github.com/dps/remarkable-keywriter -pkgver=0.2~20-gddc9e73-1 +pkgver=0.2~20-gddc9e73-2 timestamp=2022-02-09T07:05:03Z section="writing" maintainer="Mattéo Delabre " diff --git a/package/koreader/launcherctl-koreader b/package/koreader/launcherctl-koreader new file mode 100755 index 000000000..6e605d286 --- /dev/null +++ b/package/koreader/launcherctl-koreader @@ -0,0 +1,41 @@ +#!/bin/bash +set -e +case "$1" in + is-active) + systemctl is-active --quiet koreader.service + ;; + is-enabled) + systemctl is-enabled --quiet koreader.service + ;; + logs) + if [ $# -eq 2 ] && [[ "$2" == "-f" ]] || [[ "$2" == "--follow" ]]; then + journalctl --follow --all --unit koreader.service + else + journalctl --no-pager --all --unit koreader.service + fi + ;; + start | launch) + systemctl start koreader.service + ;; + stop | close) + systemctl stop koreader.service + ;; + enable) + systemctl enable koreader.service + ;; + disable) + systemctl disable koreader.service + ;; + apps) + echo "koreader" + ;; + running) + if "$0" is-active; then + echo "koreader" + fi + ;; + *) + echo "KOReader does not support this method" + exit 1 + ;; +esac diff --git a/package/koreader/package b/package/koreader/package index 675bd9cc2..99099b8db 100644 --- a/package/koreader/package +++ b/package/koreader/package @@ -1,12 +1,12 @@ #!/usr/bin/env bash -# Copyright (c) 2021 The Toltec Contributors +# Copyright (c) 2024 The Toltec Contributors # SPDX-License-Identifier: MIT pkgnames=(koreader) pkgdesc="Ebook reader supporting PDF, DjVu, EPUB, FB2 and many more formats" url=https://github.com/koreader/koreader -pkgver=2022.06-1 -timestamp=2022-06-23T19:32:08Z +pkgver=2024.07-1 +timestamp=2024-07-15T16:21:26Z section="readers" maintainer="raisjn " license=AGPL-3.0-or-later @@ -14,14 +14,16 @@ installdepends=(fbink fbdepth display rm2fb-client) _srcver="v${pkgver%-*}" source=( - "https://build.koreader.rocks/download/stable/$_srcver/koreader-remarkable-$_srcver.zip" + "https://github.com/koreader/koreader/releases/download/$_srcver/koreader-remarkable-$_srcver.zip" koreader.draft KOReader.oxide koreader-toltec.service koreader + launcherctl-koreader ) sha256sums=( - 2338591c3bc4eebd5a67e065ab98315f6a687f1c52111d39a30ac860fc3eec80 + 1040894434421b52076473f7947f139e2c98fcc04b1acadfe29b3362f262f9b7 + SKIP SKIP SKIP SKIP @@ -35,36 +37,36 @@ package() { rm "$pkgdir"/opt/koreader/{fbink,fbdepth} ln -s /opt/bin/fbink "$pkgdir"/opt/koreader/fbink ln -s /opt/bin/fbdepth "$pkgdir"/opt/koreader/fbdepth + sed -i 's/hasOTAUpdates = yes/hasOTAUpdates = no/' "$pkgdir"/opt/koreader/frontend/device/remarkable/device.lua install -D -m 644 -t "$pkgdir"/opt/etc/draft/ "$srcdir"/koreader.draft install -D -m 644 -t "$pkgdir"/opt/usr/share/applications/ "$srcdir"/KOReader.oxide install -D -m 644 "$srcdir"/koreader-toltec.service "$pkgdir"/lib/systemd/system/koreader.service install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons/ "$srcdir"/resources/koreader.png install -D -m 755 -t "$pkgdir"/opt/bin/ "$srcdir"/koreader + install -D -T -m 755 "$srcdir"/launcherctl-koreader "$pkgdir"/opt/share/launcherctl/"$pkgname" } configure() { - systemctl daemon-reload - - if ! is-enabled "$pkgname.service"; then - cat << MSG + # This file can cause issues with startup when moving from 2022.08 to another version + if [ -f /opt/koreader/cache/fontlist/fontinfo.dat ]; then + rm /opt/koreader/cache/fontlist/fontinfo.dat + fi -Run the following command(s) to use $pkgname as your launcher -$(how-to-enable "$pkgname.service") + systemctl daemon-reload -MSG + if ! launcherctl is-current-launcher "$pkgname"; then + echo "" + echo "Run the following command(s) to use $pkgname as your launcher" + echo "launcherctl switch-launcher --start $pkgname" + echo "" fi } preremove() { - if is-active "$pkgname"; then - echo "Stopping $pkgname" - systemctl stop "$pkgname" - fi - - if is-enabled "$pkgname"; then - echo "Disabling $pkgname" - systemctl disable "$pkgname" + # Just in case more than one launcher is active, do individual checks + if launcherctl is-active-launcher "$pkgname" || launcherctl is-enabled-launcher "$pkgname"; then + launcherctl switch-launcher --start xochitl fi } diff --git a/package/launcherctl/launcherctl b/package/launcherctl/launcherctl new file mode 100755 index 000000000..ff87e6a0f --- /dev/null +++ b/package/launcherctl/launcherctl @@ -0,0 +1,199 @@ +#!/bin/bash +set -e +help() { + echo "Usage: launcherctl " + echo " commands:" + echo " help: Display this message and exit" + echo " status: Current launcher status" + echo " logs [-f|--follow]: View current launcher logs" + echo " list-launchers: List installed launchers" + echo " switch-launcher [--start] : Switch which launcher is active" + echo " start-launcher: Start the current launcher" + echo " stop-launcher: Stop the current launcher" + echo " list-apps: List all application for current launcher" + echo " list-running-apps: List all application for current launcher" + echo " start-app : Start an application with the current launcher" + echo " stop-app : Stop an application with the current launcher" + echo " pause-app : Pause an application with the current launcher" + echo " resume-app : Resume an application with the current launcher" + echo " is-current-launcher : Check if the launcher is the current launcher" + echo " is-enabled-launcher : Check if the launcher is enabled" + echo " is-active-launcher : Check if the launcher is active" +} +data_dir="/opt/share/launcherctl" +launchers() { + /opt/bin/find "$data_dir" -type f -perm '-u+x' | xargs -rn1 basename +} +active_launchers() { + launchers | while read -r launcher; do + if query "$launcher" is-active; then + echo "$launcher" + fi + done +} +enabled_launchers() { + launchers | while read -r launcher; do + if query "$launcher" is-enabled; then + echo "$launcher" + fi + done +} +query() { + launcher="$1" + shift + "${data_dir}/${launcher}" "$@" +} +check_enabled_launchers() { + if [ "$(enabled_launchers | wc -l)" -lt 1 ]; then + echo "More than one launcher is currently enabled!" + echo "Enabled launchers: ${current_launcher}" + exit 1 + fi +} +check_launcher_has_app() { + if ! query "$1" apps | grep -q "$2"; then + echo "Unknown application: ${2}" + exit 1 + fi +} +case "$1" in + help | --help) + help + ;; + logs) + if [ $# -gt 2 ]; then + echo "Too many arguments" + exit 1 + elif [ $# -eq 2 ] && [[ "$2" != "-f" ]] && [[ "$2" != "--follow" ]]; then + echo "Invalid arguments" + exit 1 + fi + check_enabled_launchers + query "$(enabled_launchers)" "$@" + ;; + status) + if [ $# -gt 1 ]; then + echo "Too many arguments" + exit 1 + fi + check_enabled_launchers + current_launcher="$(enabled_launchers)" + echo -e "Launcher: \033[1m${current_launcher}\e[0m" + echo -ne "Status: \033[1m" + if query "$current_launcher" is-active; then + echo -ne "\e[32mrunning" + else + echo -ne "\e[31minactive" + fi + echo -e "\e[0m" + echo -n "Apps: $(query "$current_launcher" running | wc -l) running " + echo "$(query "$current_launcher" apps | wc -l) installed" + ;; + list-launchers) + launchers + ;; + switch-launcher) + if [ $# -lt 2 ]; then + echo "Too few arguments" + exit 1 + elif [ $# -gt 3 ]; then + echo "Too many arguments" + exit 1 + elif [ $# -eq 3 ] && [[ "$2" != "--start" ]]; then + echo "Invalid arguments" + exit 1 + fi + if [ $# -eq 3 ]; then + start=true + shift + else + start=false + fi + if ! [ -f "${data_dir}/${2}" ]; then + echo "${2} is not installed" + exit 1 + fi + enabled_launchers | while read -r launcher; do + if [[ "$launcher" != "$2" ]]; then + query "$launcher" disable + fi + done + if ! query "$2" is-enabled; then + query "$2" enable + fi + if $start; then + "$0" start-launcher + fi + ;; + start-launcher) + check_enabled_launchers + current_launcher="$(enabled_launchers)" + active_launchers | while read -r launcher; do + if [[ "$launcher" != "$current_launcher" ]]; then + query "$launcher" stop + fi + done + if query "$current_launcher" is-active; then + echo "Already started!" + exit + fi + query "$current_launcher" start + ;; + stop-launcher) + active_launchers | while read -r launcher; do + query "$launcher" stop + done + ;; + list-apps) + check_enabled_launchers + query "$(enabled_launchers)" apps + ;; + list-running-apps) + check_enabled_launchers + query "$(enabled_launchers)" running + ;; + list-paused-apps) + check_enabled_launchers + query "$(enabled_launchers)" paused + ;; + start-app) + check_enabled_launchers + launcher="$(enabled_launchers)" + check_launcher_has_app "$launcher" "$2" + query "$launcher" launch "$2" + ;; + stop-app) + check_enabled_launchers + launcher="$(enabled_launchers)" + check_launcher_has_app "$launcher" "$2" + query "$launcher" close "$2" + ;; + pause-app) + check_enabled_launchers + launcher="$(enabled_launchers)" + check_launcher_has_app "$launcher" "$2" + query "$launcher" pause "$2" + ;; + resume-app) + check_enabled_launchers + launcher="$(enabled_launchers)" + check_launcher_has_app "$launcher" "$2" + query "$launcher" resume "$2" + ;; + is-current-launcher) + check_enabled_launchers + if [[ "$(enabled_launchers)" != "$2" ]]; then + exit 1 + fi + ;; + is-enabled-launcher) + query "$2" is-enabled + ;; + is-active-launcher) + query "$2" is-active + ;; + *) + help + exit 1 + ;; +esac diff --git a/package/launcherctl/package b/package/launcherctl/package new file mode 100644 index 000000000..3b217bf3e --- /dev/null +++ b/package/launcherctl/package @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(launcherctl) +pkgdesc="Manage your installed launcher" +url=https://toltec-dev.org/ +pkgver=0.0.1-3 +timestamp=2023-12-18T03:32Z +section="launchers" +maintainer="Eeems " +license=MIT + +source=( + launcherctl +) +sha256sums=( + SKIP +) + +package() { + install -D -m 744 -t "$pkgdir"/opt/bin "$srcdir"/launcherctl + install -d "$pkgdir"/opt/share/launcherctl +} + +configure() { + echo "" + echo "You can use launcherctl to manage your active launcher" + echo "" +} + +preremove() { + launcherctl switch-launcher --start xochitl +} diff --git a/package/lf/package b/package/lf/package new file mode 100644 index 000000000..73e360741 --- /dev/null +++ b/package/lf/package @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(lf) +pkgdesc="Terminal file manager" +url=https://github.com/gokcehan/lf +pkgver=r32-1 +timestamp=2024-03-31T20:04Z +section="utils" +maintainer="gbyl " +license=MIT +installdepends=(libncurses-dev) + +image=golang:v3.1 +source=("https://github.com/gokcehan/lf/archive/refs/tags/${pkgver%-*}.zip") +sha256sums=(571ee17d8181d77a3b8bcd7aaaff0bde062c1851d93e9d324dfe15948136891a) + +build() { + export GOARCH=arm + go build +} + +package() { + install -D -m 755 "$srcdir"/lf "$pkgdir"/opt/bin/lf +} diff --git a/package/linux-mainline/package b/package/linux-mainline/package index 7ab57a29f..1db253d36 100644 --- a/package/linux-mainline/package +++ b/package/linux-mainline/package @@ -6,20 +6,28 @@ archs=(rm2) pkgnames=(linux-mainline) pkgdesc="reMarkable 2 kernel based on the mainline kernel" url=https://www.kernel.org -pkgver=5.18.0-1 -timestamp=2022-05-22T21:50:09Z +pkgver=6.3.0-2 +timestamp=2023-08-23T21:50:09Z section=kernel maintainer="Alistair Francis " makedepends=(build:flex build:bison build:libssl-dev build:bc build:lzop build:libgmp-dev build:libmpc-dev) +installdepends=(kernelctl) license=GPL-2.0-only flags=(nostrip) -image=base:v2.3 -source=("https://github.com/alistair23/linux/archive/f9fe680995e01398f0813077711fe1b744251c5b.tar.gz") -sha256sums=(d38c883a31f5f87483377e78b4b3a2eb1ce73ada38fc25949e692dd0b2dd7895) +image=base:v3.2 +source=( + https://github.com/alistair23/linux/archive/1698a3bdd8d66e58873c5bb3ce370b7d48b004cf.tar.gz + remarkable_defconfig +) +sha256sums=( + 647f6a60adad8c4e37eeaf9114c037888cb33923e364bbf5dc0830b2661c21b7 + f4d8cbb2c0e7bff5b151729b45064eb9e95005cb91899f0a9df038343d95ebf2 +) build() { - ARCH=arm make imx_v6_v7_defconfig + cp remarkable_defconfig arch/arm/configs/ + ARCH=arm make remarkable_defconfig ARCH=arm make -j8 } @@ -38,32 +46,19 @@ package() { # Create the kernel archive local archive="mainline-${pkgver%-*}.tar.bz2" install -d "$pkgdir"/opt/usr/share/kernelctl - tar --owner root:0 --group root:0 --mtime=$timestamp \ - -cjf "$pkgdir"/opt/usr/share/kernelctl/"$archive" -C "$staging" . + (cd "$staging" && tar --owner root:0 --group root:0 --mtime=$timestamp \ + -cjf "$pkgdir"/opt/usr/share/kernelctl/"$archive" boot/* lib/modules/*) } configure() { echo "The new kernel files have been copied, but not installed." - echo "Before installing them, make a backup of the existing kernel:" - echo " mkdir -p /home/root/boot-backup" - echo " cp -rvf /boot/* /home/root/boot-backup/" - echo - echo "Then replace it with the new kernel and reboot:" - echo " tar -xvf /opt/usr/share/kernelctl/mainline-${pkgver%-*}.tar.bz2 -C /" - echo " /bin/sync" + echo "Please use kernelctl to select the kernel to boot." echo echo "Known issues with the mainline kernel:" echo " - No support for low power mode (suspend uses more power then it should)" - echo " - WiFi sometimes is off on boot (can be turned on again though)" - echo " - GUI shutdown in Oxide doesn't work" - echo " - Wacom stylus doesn't work in Xochitl (works everywhere else though)" + echo " - Shutdown doesn't work (https://github.com/alistair23/linux/issues/4)" + echo " - Device doesn't always resume correctly from suspend, a reboot is required" + echo " - Wacom stylus doesn't work in Xochitl (https://github.com/reMarkable/linux/issues/15)" echo " - No OTG control support" -} - -postremove() { - echo "To restore to the original kernel, run and then reboot" - echo " rm -rf /lib/modules/${pkgver%-*}/" - echo " cp -f /home/root/boot-backup/zImage /boot/" - echo " cp -f /home/root/boot-backup/zero-sugar.dtb /boot/" - echo " /bin/sync" + echo " - Folio does not work" } diff --git a/package/linux-mainline/remarkable_defconfig b/package/linux-mainline/remarkable_defconfig new file mode 100644 index 000000000..00af8d735 --- /dev/null +++ b/package/linux-mainline/remarkable_defconfig @@ -0,0 +1,487 @@ +CONFIG_KERNEL_LZO=y +CONFIG_SYSVIPC=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BPF_SYSCALL=y +CONFIG_PREEMPT_VOLUNTARY=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_CGROUPS=y +CONFIG_CGROUP_BPF=y +CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_PERF_EVENTS=y +CONFIG_ARCH_MULTI_V6=y +CONFIG_ARCH_MXC=y +CONFIG_SOC_IMX31=y +CONFIG_SOC_IMX35=y +CONFIG_SOC_IMX50=y +CONFIG_SOC_IMX51=y +CONFIG_SOC_IMX53=y +CONFIG_SOC_IMX6Q=y +CONFIG_SOC_IMX6SL=y +CONFIG_SOC_IMX6SLL=y +CONFIG_SOC_IMX6SX=y +CONFIG_SOC_IMX6UL=y +CONFIG_SOC_IMX7D=y +CONFIG_SOC_IMX7ULP=y +CONFIG_SOC_VF610=y +CONFIG_SMP=y +CONFIG_ARM_PSCI=y +CONFIG_HIGHMEM=y +CONFIG_ARCH_FORCE_MAX_ORDER=14 +CONFIG_CMDLINE="noinitrd console=ttymxc0,115200" +CONFIG_KEXEC=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_STAT=y +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_IMX6Q_CPUFREQ=y +CONFIG_ARM_IMX_CPUFREQ_DT=y +CONFIG_CPU_IDLE=y +CONFIG_ARM_CPUIDLE=y +CONFIG_ARM_PSCI_CPUIDLE=y +CONFIG_VFP=y +CONFIG_NEON=y +CONFIG_PM_DEBUG=y +CONFIG_PM_TEST_SUSPEND=y +CONFIG_KPROBES=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_MODULE_SRCVERSION_ALL=y +CONFIG_BINFMT_MISC=m +# CONFIG_COMPAT_BRK is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +CONFIG_NETFILTER=y +CONFIG_CAN=y +CONFIG_BT=y +CONFIG_BT_BNEP=m +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_LL=y +CONFIG_CFG80211=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=y +CONFIG_RFKILL=y +CONFIG_RFKILL_INPUT=y +CONFIG_PCI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_IMX6=y +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_STANDALONE is not set +CONFIG_IMX_WEIM=y +CONFIG_CONNECTOR=y +CONFIG_MTD=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_CFI=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_OF=y +CONFIG_MTD_DATAFLASH=y +CONFIG_MTD_SST25L=y +CONFIG_MTD_RAW_NAND=y +CONFIG_MTD_NAND_GPMI_NAND=y +CONFIG_MTD_NAND_VF610_NFC=y +CONFIG_MTD_NAND_MXC=y +CONFIG_MTD_SPI_NOR=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_MTD_UBI_BLOCK=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=65536 +CONFIG_EEPROM_AT24=y +CONFIG_EEPROM_AT25=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_ATA=y +CONFIG_SATA_AHCI_PLATFORM=y +CONFIG_AHCI_IMX=y +CONFIG_PATA_IMX=y +CONFIG_NETDEVICES=y +# CONFIG_NET_VENDOR_BROADCOM is not set +CONFIG_CS89x0_PLATFORM=y +# CONFIG_NET_VENDOR_FARADAY is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_SEEQ is not set +CONFIG_SMC91X=y +CONFIG_SMC911X=y +CONFIG_SMSC911X=y +# CONFIG_NET_VENDOR_STMICRO is not set +CONFIG_MICREL_PHY=y +CONFIG_AT803X_PHY=y +CONFIG_CAN_FLEXCAN=y +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=y +CONFIG_USB_LAN78XX=y +CONFIG_USB_USBNET=y +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_SMSC95XX=y +CONFIG_USB_NET_MCS7830=y +CONFIG_ATH10K=m +CONFIG_ATH10K_SDIO=m +CONFIG_BRCMFMAC=m +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE_SDIO=m +# CONFIG_WILINK_PLATFORM_DATA is not set +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_EVBUG=m +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_SNVS_PWRKEY=y +CONFIG_KEYBOARD_IMX=y +CONFIG_MOUSE_PS2=m +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ADS7846=y +CONFIG_TOUCHSCREEN_AD7879=y +CONFIG_TOUCHSCREEN_AD7879_I2C=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=y +CONFIG_TOUCHSCREEN_CYTTSP5=y +CONFIG_TOUCHSCREEN_DA9052=y +CONFIG_TOUCHSCREEN_EGALAX=y +CONFIG_TOUCHSCREEN_GOODIX=y +CONFIG_TOUCHSCREEN_ILI210X=y +CONFIG_TOUCHSCREEN_MAX11801=y +CONFIG_TOUCHSCREEN_IMX6UL_TSC=y +CONFIG_TOUCHSCREEN_EDT_FT5X06=y +CONFIG_TOUCHSCREEN_MC13783=y +CONFIG_TOUCHSCREEN_TSC2004=y +CONFIG_TOUCHSCREEN_TSC2007=y +CONFIG_TOUCHSCREEN_STMPE=y +CONFIG_TOUCHSCREEN_SX8654=y +CONFIG_TOUCHSCREEN_COLIBRI_VF50=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_MMA8450=y +CONFIG_SERIO_SERPORT=m +# CONFIG_LEGACY_PTYS is not set +CONFIG_SERIAL_IMX=y +CONFIG_SERIAL_IMX_CONSOLE=y +CONFIG_SERIAL_FSL_LPUART=y +CONFIG_SERIAL_FSL_LPUART_CONSOLE=y +CONFIG_SERIAL_DEV_BUS=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +CONFIG_I2C_MUX=y +CONFIG_I2C_MUX_GPIO=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_ALGOPCF=m +CONFIG_I2C_ALGOPCA=m +CONFIG_I2C_GPIO=y +CONFIG_I2C_IMX=y +CONFIG_SPI=y +CONFIG_SPI_FSL_QUADSPI=y +CONFIG_SPI_GPIO=y +CONFIG_SPI_IMX=y +CONFIG_SPI_FSL_DSPI=y +CONFIG_PINCTRL_IMX8MM=y +CONFIG_PINCTRL_IMX8MN=y +CONFIG_PINCTRL_IMX8MP=y +CONFIG_PINCTRL_IMX8MQ=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_MXC=y +CONFIG_GPIO_SIOX=m +CONFIG_GPIO_MAX732X=y +CONFIG_GPIO_PCA953X=y +CONFIG_GPIO_PCF857X=y +CONFIG_GPIO_BD71815=y +CONFIG_GPIO_STMPE=y +CONFIG_GPIO_74X164=y +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_POWER_SUPPLY=y +CONFIG_BATTERY_MAX77818=y +CONFIG_CHARGER_MAX77818=y +CONFIG_RN5T618_POWER=m +CONFIG_SENSORS_MC13783_ADC=y +CONFIG_SENSORS_GPIO_FAN=y +CONFIG_SENSORS_IIO_HWMON=y +CONFIG_SENSORS_SY7636A=y +CONFIG_THERMAL_STATISTICS=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_CPU_THERMAL=y +CONFIG_IMX_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_DA9063_WATCHDOG=m +CONFIG_DA9062_WATCHDOG=y +CONFIG_RN5T618_WATCHDOG=y +CONFIG_IMX2_WDT=y +CONFIG_IMX7ULP_WDT=y +CONFIG_MFD_DA9052_I2C=y +CONFIG_MFD_DA9062=y +CONFIG_MFD_DA9063=y +CONFIG_MFD_MC13XXX_SPI=y +CONFIG_MFD_MC13XXX_I2C=y +CONFIG_MFD_SY7636A=y +CONFIG_MFD_MAX77818=y +CONFIG_MFD_RN5T618=y +CONFIG_MFD_STMPE=y +CONFIG_MFD_ROHM_BD71828=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_ANATOP=y +CONFIG_REGULATOR_BD71815=y +CONFIG_REGULATOR_DA9052=y +CONFIG_REGULATOR_DA9062=y +CONFIG_REGULATOR_DA9063=y +CONFIG_REGULATOR_GPIO=y +CONFIG_REGULATOR_LTC3676=y +CONFIG_REGULATOR_MAX77818=y +CONFIG_REGULATOR_MC13783=y +CONFIG_REGULATOR_MC13892=y +CONFIG_REGULATOR_PFUZE100=y +CONFIG_REGULATOR_RN5T618=y +CONFIG_REGULATOR_SY7636A=y +CONFIG_RC_CORE=y +CONFIG_RC_DEVICES=y +CONFIG_IR_GPIO_CIR=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +CONFIG_V4L_PLATFORM_DRIVERS=y +CONFIG_V4L_MEM2MEM_DRIVERS=y +CONFIG_VIDEO_MUX=y +CONFIG_VIDEO_CODA=m +CONFIG_VIDEO_IMX_PXP=y +CONFIG_VIDEO_OV2680=m +CONFIG_VIDEO_OV5640=m +CONFIG_VIDEO_OV5645=m +CONFIG_VIDEO_ADV7180=m +CONFIG_IMX_IPUV3_CORE=y +CONFIG_DRM=y +CONFIG_DRM_MSM=y +CONFIG_DRM_PANEL_LVDS=y +CONFIG_DRM_PANEL_SIMPLE=y +CONFIG_DRM_PANEL_EDP=y +CONFIG_DRM_PANEL_SEIKO_43WVF1G=y +CONFIG_DRM_TI_TFP410=y +CONFIG_DRM_DW_HDMI_AHB_AUDIO=m +CONFIG_DRM_DW_HDMI_CEC=y +CONFIG_DRM_IMX=y +CONFIG_DRM_IMX_PARALLEL_DISPLAY=y +CONFIG_DRM_IMX_TVE=y +CONFIG_DRM_IMX_LDB=y +CONFIG_DRM_IMX_HDMI=y +CONFIG_DRM_ETNAVIV=y +CONFIG_DRM_MXSFB=y +CONFIG_FB=y +CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_MXS=y +CONFIG_LCD_CLASS_DEVICE=y +CONFIG_LCD_L4F00242T03=y +CONFIG_LCD_PLATFORM=y +CONFIG_BACKLIGHT_PWM=y +CONFIG_BACKLIGHT_GPIO=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_SOC=y +CONFIG_SND_SOC_FSL_ASRC=y +CONFIG_SND_IMX_SOC=y +CONFIG_SND_SOC_EUKREA_TLV320=y +CONFIG_SND_SOC_IMX_ES8328=y +CONFIG_SND_SOC_IMX_SGTL5000=y +CONFIG_SND_SOC_IMX_SPDIF=y +CONFIG_SND_SOC_FSL_ASOC_CARD=y +CONFIG_SND_SOC_AC97_CODEC=y +CONFIG_SND_SOC_CS42XX8_I2C=y +CONFIG_SND_SOC_TLV320AIC3X_I2C=y +CONFIG_SND_SOC_WM8960=y +CONFIG_SND_SOC_WM8962=y +CONFIG_SND_SIMPLE_CARD=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_WACOM=y +CONFIG_I2C_HID_OF=y +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_ACM=m +CONFIG_USB_STORAGE=y +CONFIG_USB_CHIPIDEA=y +CONFIG_USB_CHIPIDEA_UDC=y +CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_TEST=m +CONFIG_USB_EHSET_TEST_FIXTURE=m +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_MXS_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_ACM=y +CONFIG_USB_CONFIGFS_OBEX=y +CONFIG_USB_CONFIGFS_NCM=y +CONFIG_USB_CONFIGFS_ECM=y +CONFIG_USB_CONFIGFS_ECM_SUBSET=y +CONFIG_USB_CONFIGFS_RNDIS=y +CONFIG_USB_CONFIGFS_EEM=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_LB_SS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_UAC1=y +CONFIG_USB_CONFIGFS_F_UAC2=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_CONFIGFS_F_UVC=y +CONFIG_USB_CONFIGFS_F_PRINTER=y +CONFIG_USB_ZERO=m +CONFIG_USB_AUDIO=m +CONFIG_USB_ETH=y +CONFIG_USB_G_NCM=m +CONFIG_USB_GADGETFS=y +CONFIG_USB_FUNCTIONFS=y +CONFIG_USB_FUNCTIONFS_ETH=y +CONFIG_USB_FUNCTIONFS_RNDIS=y +CONFIG_USB_FUNCTIONFS_GENERIC=y +CONFIG_USB_MASS_STORAGE=m +CONFIG_USB_G_SERIAL=m +CONFIG_USB_CDC_COMPOSITE=y +CONFIG_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_PLTFM=y +CONFIG_MMC_SDHCI_ESDHC_IMX=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_PWM=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_RTC_CLASS=y +CONFIG_RTC_INTF_DEV_UIE_EMUL=y +CONFIG_RTC_DRV_DS1307=y +CONFIG_RTC_DRV_ISL1208=y +CONFIG_RTC_DRV_PCF8523=y +CONFIG_RTC_DRV_PCF8563=y +CONFIG_RTC_DRV_M41T80=y +CONFIG_RTC_DRV_BD70528=y +CONFIG_RTC_DRV_RC5T619=y +CONFIG_RTC_DRV_RV3029C2=y +CONFIG_RTC_DRV_DA9063=y +CONFIG_RTC_DRV_MC13XXX=y +CONFIG_RTC_DRV_MXC=y +CONFIG_RTC_DRV_MXC_V2=y +CONFIG_RTC_DRV_SNVS=y +CONFIG_DMADEVICES=y +CONFIG_FSL_EDMA=y +CONFIG_IMX_SDMA=m +CONFIG_MXS_DMA=y +CONFIG_DMATEST=m +CONFIG_STAGING=y +CONFIG_STAGING_MEDIA=y +CONFIG_VIDEO_IMX_MEDIA=y +CONFIG_COMMON_CLK_PWM=y +CONFIG_COMMON_CLK_BD718XX=y +CONFIG_CLK_IMX8MM=y +CONFIG_CLK_IMX8MN=y +CONFIG_CLK_IMX8MP=y +CONFIG_CLK_IMX8MQ=y +CONFIG_SOC_IMX8M=y +CONFIG_EXTCON_USB_GPIO=y +CONFIG_IIO=y +CONFIG_MMA8452=y +CONFIG_IMX7D_ADC=y +CONFIG_RN5T618_ADC=y +CONFIG_STMPE_ADC=y +CONFIG_VF610_ADC=y +CONFIG_SENSORS_ISL29018=y +CONFIG_MAG3110=y +CONFIG_MPL3115=y +CONFIG_PWM=y +CONFIG_PWM_FSL_FTM=y +CONFIG_PWM_IMX27=y +CONFIG_PWM_IMX_TPM=y +CONFIG_NVMEM_IMX_OCOTP=y +CONFIG_NVMEM_SNVS_LPGPR=y +CONFIG_NVMEM_VF610_OCOTP=y +CONFIG_TEE=y +CONFIG_OPTEE=y +CONFIG_MUX_MMIO=y +CONFIG_SIOX=m +CONFIG_SIOX_BUS_GPIO=m +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_POSIX_ACL=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_QUOTA=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=y +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_JFFS2_FS=y +CONFIG_UBIFS_FS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_ROOT_NFS=y +CONFIG_NLS_DEFAULT="cp437" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=y +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_UTF8=y +CONFIG_SECURITYFS=y +CONFIG_CRYPTO_DEV_FSL_CAAM=y +CONFIG_CRYPTO_DEV_SAHARA=y +CONFIG_CRYPTO_DEV_MXS_DCP=y +CONFIG_CRC_CCITT=m +CONFIG_CRC_T10DIF=y +CONFIG_CRC7=m +CONFIG_LIBCRC32C=m +CONFIG_CMA_SIZE_MBYTES=0 +CONFIG_FONTS=y +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y +CONFIG_PRINTK_TIME=y +# CONFIG_DEBUG_BUGVERBOSE is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_FS=y +# CONFIG_SLUB_DEBUG is not set +# CONFIG_SCHED_DEBUG is not set +# CONFIG_FTRACE is not set diff --git a/package/linux-stracciatella/package b/package/linux-stracciatella/package new file mode 100644 index 000000000..994842c50 --- /dev/null +++ b/package/linux-stracciatella/package @@ -0,0 +1,79 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 The Toltec Contributors +# SPDX-License-Identifier: MIT + +archs=(rm1 rm2) +pkgnames=(linux-stracciatella) +pkgdesc="RemarkableAS's vanilla kernel with a few extra flakes" +url=https://github.com/Etn40ff/linux-remarkable +pkgver=5.4.70.4-1 +timestamp=2023-12-28T22:42:42Z +section="kernel" +maintainer="Salvatore Stella " +makedepends=(build:flex build:bison build:libssl-dev build:bc build:lzop build:libgmp-dev build:libmpc-dev build:kmod) +license=GPL-2.0-only +flags=(nostrip) +installdepends=(kernelctl) +image=base:v3.1 +_wireguard_version=1.0.20220627 +source=( + "https://github.com/Etn40ff/linux-remarkable/archive/refs/tags/${pkgver%-*}.tar.gz" + "https://git.zx2c4.com/wireguard-linux-compat/snapshot/wireguard-linux-compat-$_wireguard_version.tar.xz" +) +sha256sums=( + 29fd9d7adcb243b841d3577088dd2aec6106eaaa3bc51440411f49ea50658c01 + 362d412693c8fe82de00283435818d5c5def7f15e2433a07a9fe99d0518f63c0 +) +noextract=("wireguard-linux-compat-$_wireguard_version.tar.xz") + +prepare() { + # Jury-rig the wireguard module into sources and enable it + mkdir "$srcdir/net/wireguard" + bsdtar --strip-components 2 -xJ -C "$srcdir/net/wireguard" \ + -f "$srcdir/wireguard-linux-compat-$_wireguard_version.tar.xz" \ + "wireguard-linux-compat-$_wireguard_version/src" + sed -i "/^obj-\\\$(CONFIG_NETFILTER).*+=/a obj-\$(CONFIG_WIREGUARD) += wireguard/" "$srcdir/net/Makefile" + sed -i "/^if INET\$/a source \"net/wireguard/Kconfig\"" "$srcdir/net/Kconfig" + echo "CONFIG_WIREGUARD=m" >> "$srcdir/arch/arm/configs/zero-gravitas_defconfig" + echo "CONFIG_WIREGUARD=m" >> "$srcdir/arch/arm/configs/zero-sugar_defconfig" +} + +build() { + if [[ $arch = rm1 ]]; then + ARCH=arm make zero-gravitas_defconfig + elif [[ $arch = rm2 ]]; then + ARCH=arm make zero-sugar_defconfig + fi + ARCH=arm make -j8 +} + +package() { + # Prepare files for the kernel archive + local staging="$srcdir"/staging + mkdir -p "$staging/boot" + + cp --no-dereference {"$srcdir"/arch/arm,"$staging"}/boot/zImage + if [[ $arch = rm1 ]]; then + cp --no-dereference "$srcdir"/arch/arm/boot/dts/zero-gravitas.dtb "$staging"/boot/zero-gravitas.dtb + elif [[ $arch = rm2 ]]; then + cp --no-dereference "$srcdir"/arch/arm/boot/dts/zero-sugar.dtb "$staging"/boot/zero-sugar.dtb + fi + + ARCH=arm make -C "$srcdir" modules_install INSTALL_MOD_PATH="$staging" + rm "$staging"/lib/modules/*/{source,build} + + # Create the kernel archive + local archive="stracciatella-${pkgver%-*}.tar.bz2" + install -d "$pkgdir"/opt/usr/share/kernelctl + (cd "$staging" && tar --owner root:0 --group root:0 --mtime=$timestamp \ + -cjf "$pkgdir"/opt/usr/share/kernelctl/"$archive" boot/* lib/modules/*) +} + +configure() { + if [[ $(< /etc/version) -le 20210709090000 ]]; then + echo "WARNING: Your system is too old; this kernel will most likely not work unless you add the appropriate firmware blobs to /lib/firmware." + echo "Please consider updating your system instead." + fi + echo "The new kernel files have been copied, but not installed." + echo "Please use kernelctl to select the kernel to boot." +} diff --git a/package/micro/package b/package/micro/package index e71f429ce..e1651a49a 100644 --- a/package/micro/package +++ b/package/micro/package @@ -5,14 +5,14 @@ pkgnames=(micro) pkgdesc="Modern and intuitive terminal-based text editor" url=https://micro-editor.github.io/ -pkgver=2.0.10-1 -timestamp=2021-08-07T00:57:40Z +pkgver=2.0.14-1 +timestamp=2024-08-27T18:13:07Z section="utils" maintainer="Eeems " license=MIT -source=(https://github.com/zyedidia/micro/releases/download/v2.0.10/micro-2.0.10-linux-arm.tar.gz) -sha256sums=(b60478ac87f41f00d91cf6ca58b6d7e05af99ee5fa73fa8881b140ac428fa278) +source=("https://github.com/zyedidia/micro/releases/download/v2.0.14/micro-2.0.14-linux-arm.tar.gz") +sha256sums=(9f490d88bd30a548af99a905f50244dc6c80f3c7a3c6f98faeb5b0a7329f7dea) package() { install -Dm644 "$srcdir"/LICENSE "$pkgdir/opt/usr/share/licenses/$pkgname/LICENSE" diff --git a/package/mmc-utils/package b/package/mmc-utils/package index a91ae561b..948dffa99 100644 --- a/package/mmc-utils/package +++ b/package/mmc-utils/package @@ -6,7 +6,7 @@ archs=(rmall) pkgnames=(mmc-utils) pkgdesc="A tool for monitoring the eMMC protocol" url=https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/ -pkgver=1.0-0 +pkgver=1.0-1 timestamp=2021-08-12T19:41:07Z section="devel" maintainer="Alistair Francis " @@ -14,13 +14,22 @@ license=GPL-2.0-only image=base:v2.2 source=( - "https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/snapshot/mmc-utils-7769a4d7abe339ce273c13a203394a79a11fcff9.tar.gz" 0001-Makefile-Remove-Werror.patch ) sha256sums=( - 0578e546d8893b6207180def7966e7314cae54c237a931b8f94779ce5c7d0668 SKIP ) +_commit=7769a4d7abe339ce273c13a203394a79a11fcff9 + +prepare() { + cd "$srcdir" + mkdir mmc-utils + cd mmc-utils + git init + git fetch --depth=1 "https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git" "$_commit" + git checkout -f "$_commit" + patch < "$srcdir"/0001-Makefile-Remove-Werror.patch +} build() { # Use our toolchain @@ -28,10 +37,9 @@ build() { export CC=arm-linux-gnueabihf-gcc export STRIP=arm-linux-gnueabihf-strip - patch < "$srcdir"/0001-Makefile-Remove-Werror.patch - make -j4 + make -C "$srcdir"/mmc-utils -j4 } package() { - DESTDIR="$pkgdir" make -C "$srcdir" install + DESTDIR="$pkgdir" make -C "$srcdir"/mmc-utils install } diff --git a/package/move-logs-to-opt/package b/package/move-logs-to-opt/package new file mode 100644 index 000000000..99e131bb6 --- /dev/null +++ b/package/move-logs-to-opt/package @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(move-logs-to-opt) +pkgdesc="Move log files to /opt to save space on the root partition" +url=https://github.com/toltec-dev/toltec +pkgver=0.0.1-1 +timestamp=2024-01-07T23:55Z +section="utils" +maintainer="Eeems " +license=MIT + +source=(var-log.mount) +sha256sums=(SKIP) + +package() { + mkdir -p "$pkgdir"/opt/var/log + install -D -m 644 -t "$pkgdir"/lib/systemd/system/ "$srcdir"/var-log.mount +} + +configure() { + systemctl daemon-reload + if is-active systemd-journald.service; then + journalctl --sync --flush + systemctl stop systemd-journald.service + fi + if ! mountpoint -q /var/log; then + echo "Moving log files to new location" + local target_path=/home/root/.entware/var/log + mkdir -p "$target_path" + cp -af "/var/log/." "$target_path" + rm -rf "/var/log/"* + fi + if ! is-enabled "var-log.mount"; then + systemctl enable "var-log.mount" + fi + systemctl restart "var-log.mount" + systemctl start systemd-journald.service +} + +preremove() { + if is-active systemd-journald.service; then + journalctl --sync --flush + systemctl stop systemd-journald.service + fi + disable-unit "var-log.mount" +} + +postremove() { + systemctl daemon-reload + systemctl start systemd-journald.service + if mountpoint -q /var/log; then + umount -l /var/log + fi +} diff --git a/package/move-logs-to-opt/var-log.mount b/package/move-logs-to-opt/var-log.mount new file mode 100644 index 000000000..a1fd0d3d3 --- /dev/null +++ b/package/move-logs-to-opt/var-log.mount @@ -0,0 +1,15 @@ +[Unit] +Description=Bind mount '/home/root/.entware/var/log' over '/var/log' +DefaultDependencies=no +Conflicts=umount.target +Before=local-fs.target umount.target systemd-journald.service +After=home.mount + +[Mount] +What=/home/root/.entware/var/log +Where=/var/log +Type=none +Options=bind + +[Install] +WantedBy=local-fs.target diff --git a/package/neofetch/package b/package/neofetch/package new file mode 100644 index 000000000..54cff1ae6 --- /dev/null +++ b/package/neofetch/package @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(neofetch) +pkgdesc="A command-line system information tool" +url="https://github.com/rM-self-serve/neofetch-rM" +pkgver=1.1.1-1 +timestamp=2024-03-14T11:43:00Z +section="utils" +maintainer="rM-self-serve <122753594+rM-self-serve@users.noreply.github.com>" +license=MIT + +source=( + "$url"/archive/6dfc7a7b0c10f451bdd8a09813ab6dea01ef6be2.zip +) + +sha256sums=( + 798ddbcb196b382e6bb70b3da08bc0e745c8b6da0bfe4ea5cd66653d383e5b1d +) + +package() { + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/neofetch +} + +configure() { + if [ -f '/home/root/.config/neofetch/config.conf' ]; then + echo "" + echo "You may choose to remove ~/.config/neofetch/config.conf" + echo "in order to get the latest default config." + fi +} diff --git a/package/netevent/package b/package/netevent/package index d30293bf8..e1efee9ab 100644 --- a/package/netevent/package +++ b/package/netevent/package @@ -5,8 +5,8 @@ pkgnames=(netevent) pkgdesc="Input-Event device cloning utility" url="https://github.com/Blub/netevent" -pkgver=2.2.1-1 -timestamp=2021-12-03T19:43:04+01:00 +pkgver=2.2.2-1 +timestamp=2023-04-29T14:21:02Z section=utils maintainer="Salvatore Stella " license=GPL-2.0-only @@ -16,7 +16,7 @@ source=( "https://github.com/Blub/netevent/archive/refs/tags/${pkgver%-*}.tar.gz" ) sha256sums=( - ba1289cc04aef563baa9cc203111af3980a9311442233ffcf76760cda9f6aa69 + 09c0e97cd5c2cf5ed51e44ce955cc28cfa2cd0022bd48241f1096bc441439d3a ) build() { diff --git a/package/netsurf/package b/package/netsurf/package index 8213b73fb..74d427851 100644 --- a/package/netsurf/package +++ b/package/netsurf/package @@ -5,7 +5,7 @@ pkgnames=(netsurf) pkgdesc="Lightweight web browser" url=https://github.com/alex0809/netsurf-reMarkable -pkgver=0.4.0-2 +pkgver=0.4.0-3 timestamp=2021-05-31T11:15+00:00 maintainer="Alex Friesenhahn " archs=(rmall) diff --git a/package/open-remarkable-shutdown/package b/package/open-remarkable-shutdown/package index 6a138346c..dbdec6302 100644 --- a/package/open-remarkable-shutdown/package +++ b/package/open-remarkable-shutdown/package @@ -2,10 +2,11 @@ # Copyright (c) 2021 The Toltec Contributors # SPDX-License-Identifier: MIT +archs=(rmallos2 rm1os3) pkgnames=(open-remarkable-shutdown) pkgdesc="Use remarkable-splash to display shutdown and reboot images" url=https://github.com/ddvk/remarkable-splash -pkgver=1.0-1 +pkgver=1.0-3 timestamp=2022-02-28T00:12Z section="utils" maintainer="Eeems " diff --git a/package/oxide/launcherctl-oxide b/package/oxide/launcherctl-oxide new file mode 100755 index 000000000..97ff4a73e --- /dev/null +++ b/package/oxide/launcherctl-oxide @@ -0,0 +1,57 @@ +#!/bin/bash +set -e +case "$1" in + is-active) + systemctl is-active --quiet tarnish.service + ;; + is-enabled) + systemctl is-enabled --quiet tarnish.service + ;; + logs) + if [ $# -eq 2 ] && [[ "$2" == "-f" ]] || [[ "$2" == "--follow" ]]; then + journalctl --follow --all --unit tarnish.service + else + journalctl --no-pager --all --unit tarnish.service + fi + ;; + start) + systemctl start tarnish.service + ;; + stop) + systemctl stop tarnish.service + ;; + enable) + systemctl enable tarnish.service + ;; + disable) + systemctl disable tarnish.service + ;; + apps) + rot apps get applications | jq -r 'keys | .[]' + ;; + running) + rot apps get runningApplications | jq -r 'keys | .[]' + ;; + paused) + rot apps get pausedApplications | jq -r 'keys | .[]' + ;; + launch | resume) + rot apps get applications \ + | jq -cr ".$2" | sed 's|/codes/eeems/oxide1/||' \ + | xargs -I {} rot --object Application:{} apps call launch + ;; + close) + rot apps get applications \ + | jq -cr ".$2" | sed 's|/codes/eeems/oxide1/||' \ + | xargs -I {} rot --object Application:{} apps call stop + ;; + pause) + rot apps get applications \ + | jq -cr ".$2" | sed 's|/codes/eeems/oxide1/||' \ + | xargs -I {} rot --object Application:{} apps call pause + ;; + *) + echo "Oxide does not support this method" + exit 1 + ;; +esac diff --git a/package/oxide/package b/package/oxide/package index ba95481fb..9ce51549b 100644 --- a/package/oxide/package +++ b/package/oxide/package @@ -1,157 +1,174 @@ #!/usr/bin/env bash -# Copyright (c) 2021 The Toltec Contributors +# Copyright (c) 2024 The Toltec Contributors # SPDX-License-Identifier: MIT -pkgnames=(erode fret oxide rot tarnish decay corrupt anxiety liboxide libsentry) -pkgver=2.4-1 -_sentryver=0.4.17 -timestamp=2022-05-22T03:18:32Z +archs=(rm1 rm2) +pkgnames=(oxide oxide-extra oxide-utils inject_evdev liboxide liboxide-dev libsentry) +_oxidever=2.8.4 +pkgver=$_oxidever-2 +_sentryver=0.7.6 +timestamp=2024-06-26T22:31:46Z maintainer="Eeems " url=https://oxide.eeems.codes license=MIT flags=(patch_rm2fb) -image=qt:v2.3 -source=("https://github.com/Eeems-Org/oxide/archive/e6c62a6860b52cd1cbd47e21377f8d1ecf72bb0a.tar.gz") -sha256sums=(a29cf455d5f66fee4ee67722c6f1d20627930920286398932c3d5c813d58ebee) +image=qt:v3.1 +source=( + "https://github.com/Eeems-Org/oxide/archive/refs/tags/v$_oxidever.zip" + toltec-rm2-override.conf + launcherctl-oxide +) +sha256sums=( + bfcb26c0493544fabc472bebc1eb372e49e58774163533ae937b6e814222f03e + SKIP + SKIP +) build() { find . -name "*.pro" -type f -print0 \ | xargs -r -0 sed -i 's/linux-oe-g++/linux-arm-remarkable-g++/g' + find . -name "*.pri" -type f -print0 \ + | xargs -r -0 sed -i 's/linux-oe-g++/linux-arm-remarkable-g++/g' CMAKE_TOOLCHAIN_FILE="/usr/share/cmake/$CHOST.cmake" make FEATURES=sentry release } -erode() { - pkgdesc="Task manager" - section="admin" - installdepends=(display "tarnish=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") - - package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/erode - install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons "$srcdir"/release/opt/etc/draft/icons/erode.svg - install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons "$srcdir"/release/opt/etc/draft/icons/erode-splash.png - install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.erode.oxide - } -} - -fret() { - pkgdesc="Take screenshots" - section="utils" - installdepends=("tarnish=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") - - package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/fret - install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.fret.oxide - } -} - oxide() { pkgdesc="Launcher application" section="launchers" - installdepends=("erode=$pkgver" "fret=$pkgver" "tarnish=$pkgver" "rot=$pkgver" "decay=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") + installdepends=("oxide-utils=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver" reboot-guard jq display launcherctl) + replaces=(erode tarnish decay corrupt) + conflicts=(erode tarnish decay corrupt) package() { + # System service + install -D -m 644 -t "$pkgdir"/etc/dbus-1/system.d "$srcdir"/release/etc/dbus-1/system.d/codes.eeems.oxide.conf + install -D -m 644 -t "$pkgdir"/lib/systemd/system "$srcdir"/release/etc/systemd/system/tarnish.service + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/tarnish + # Task manager + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/erode + install -D -m 644 -t "$pkgdir"/opt/usr/share/icons/oxide/48x48/apps "$srcdir"/release/opt/usr/share/icons/oxide/48x48/apps/erode.png + install -D -m 644 -t "$pkgdir"/opt/usr/share/icons/oxide/702x702/splash "$srcdir"/release/opt/usr/share/icons/oxide/702x702/splash/erode.png + install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.erode.oxide + # Launcher install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/oxide install -D -m 644 -t "$pkgdir"/opt/etc "$srcdir"/release/opt/etc/oxide.conf - install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons "$srcdir"/release/opt/etc/draft/icons/oxide-splash.png install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.oxide.oxide + install -D -m 644 -t "$pkgdir"/opt/usr/share/icons/oxide/702x702/splash "$srcdir"/release/opt/usr/share/icons/oxide/702x702/splash/oxide.png + # Lockscreen + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/decay + install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.decay.oxide + # Task switcher + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/corrupt + install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.corrupt.oxide + # launcherctl registration + install -D -T -m 755 "$srcdir"/launcherctl-oxide "$pkgdir"/opt/share/launcherctl/oxide + if [[ $arch = rm2 ]]; then + install -D -m 644 -t "$pkgdir"/etc/systemd/system/tarnish.service.d \ + "$srcdir"/toltec-rm2-override.conf + fi } + configure() { - if ! is-enabled "tarnish.service"; then + systemctl daemon-reload + + if ! launcherctl is-current-launcher oxide; then echo "" - echo "Run the following command(s) to use $pkgname as your launcher" - how-to-enable "tarnish.service" + echo "Run the following command(s) to use oxide as your launcher" + echo "launcherctl switch-launcher --start oxide" echo "" fi } -} - -rot() { - pkgdesc="Manage Oxide settings through the command line" - section="admin" - installdepends=("tarnish=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") - package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/rot - } -} - -tarnish() { - pkgdesc="Service managing power states, connectivity and buttons" - section="devel" - installdepends=(display xochitl "liboxide=$pkgver" "libsentry=$_sentryver") - - package() { - install -D -m 644 -t "$pkgdir"/etc/dbus-1/system.d "$srcdir"/release/etc/dbus-1/system.d/codes.eeems.oxide.conf - install -D -m 644 -t "$pkgdir"/lib/systemd/system "$srcdir"/release/etc/systemd/system/tarnish.service - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/tarnish - } - configure() { - systemctl daemon-reload - } preremove() { - if is-active tarnish; then - echo "Stopping tarnish" - systemctl stop tarnish - fi - if is-enabled tarnish; then - echo "Disabling tarnish" - systemctl disable tarnish + # Just in case more than one launcher is active, do individual checks + if launcherctl is-active-launcher oxide || launcherctl is-enabled-launcher oxide; then + launcherctl switch-launcher --start xochitl fi } + postremove() { systemctl daemon-reload } } -decay() { - pkgdesc="Lockscreen application" +oxide-extra() { + pkgdesc="Extra applications for oxide" section="utils" - installdepends=(display "tarnish=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") + installdepends=("oxide=$pkgver" "oxide-utils=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") + replaces=(fret anxiety) + conflicts=(fret anxiety) package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/decay - install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.decay.oxide + # Screenshot daemon + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/fret + install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.fret.oxide + # Screenshot viewer + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/anxiety + install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.anxiety.oxide + install -D -m 644 -t "$pkgdir"/opt/usr/share/icons/oxide/48x48/apps "$srcdir"/release/opt/usr/share/icons/oxide/48x48/apps/image.png + install -D -m 644 -t "$pkgdir"/opt/usr/share/icons/oxide/702x702/splash "$srcdir"/release/opt/usr/share/icons/oxide/702x702/splash/anxiety.png } } -corrupt() { - pkgdesc="Task Switcher for Oxide" - section="utils" - installdepends=(display "tarnish=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") + +oxide-utils() { + pkgdesc="Command line tools for Oxide" + section="admin" + installdepends=("oxide=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") + replaces=(rot notify-send update-desktop-database desktop-file-validate) + conflicts=(rot notify-send update-desktop-database desktop-file-validate) package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/corrupt - install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.corrupt.oxide + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/rot + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/notify-send + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/update-desktop-database + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/desktop-file-validate + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/xdg-desktop-menu + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/xdg-desktop-icon + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/xdg-open + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/xdg-settings + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/gio } } -anxiety() { - pkgdesc="Screenshot viewer for Oxide" +inject_evdev() { + pkgdesc="Inject input events" section="utils" - installdepends=(display "tarnish=$pkgver" "liboxide=$pkgver" "libsentry=$_sentryver") + installdepends=("liboxide=$pkgver" "libsentry=$_sentryver") package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/anxiety - install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/release/opt/usr/share/applications/codes.eeems.anxiety.oxide - install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons "$srcdir"/release/opt/etc/draft/icons/image.svg - install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons "$srcdir"/release/opt/etc/draft/icons/anxiety-splash.png + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/release/opt/bin/inject_evdev } } liboxide() { pkgdesc="Shared library for oxide applications" - section=devel + section="devel" package() { - install -D -m 755 -t "$pkgdir"/opt/usr/lib "$srcdir"/release/opt/usr/lib/libliboxide.so* + install -D -m 755 -t "$pkgdir"/opt/lib "$srcdir"/release/opt/lib/liboxide.so* + install -D -m 755 -t "$pkgdir"/opt/lib "$srcdir"/release/opt/lib/libqsgepaper.so* + } +} + +liboxide-dev() { + pkgdesc="Shared library for oxide applications" + section="devel" + installdepends=("liboxide=$pkgver") + + package() { + install -D -m 755 -t "$pkgdir"/opt/lib/pkgconfig "$srcdir"/release/opt/lib/pkgconfig/oxide.pc + install -D -m 755 -t "$pkgdir"/opt/include "$srcdir"/release/opt/include/epframebuffer.h + install -D -m 755 -t "$pkgdir"/opt/include "$srcdir"/release/opt/include/liboxide.h + cp -ar "$srcdir"/release/opt/include/liboxide/ "$pkgdir"/opt/include/ } } libsentry() { pkgdesc="Sentry SDK for C, C++ and native applications." - section=devel + section="devel" url=https://github.com/getsentry/sentry-native pkgver="$_sentryver" - timestamp="2021-12-20T14:25:11Z" + timestamp="2024-06-12T08:04:15Z" package() { install -D -m 755 -t "$pkgdir"/opt/lib "$srcdir"/release/opt/lib/libsentry.so diff --git a/package/oxide/toltec-rm2-override.conf b/package/oxide/toltec-rm2-override.conf new file mode 100644 index 000000000..b1e25ec9a --- /dev/null +++ b/package/oxide/toltec-rm2-override.conf @@ -0,0 +1,7 @@ +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +[Unit] +After=rm2fb.service +Requires=rm2fb.service +OnFailure=xochitl.service diff --git a/package/plato/package b/package/plato/package index 9e26440b3..c58215fcd 100644 --- a/package/plato/package +++ b/package/plato/package @@ -5,32 +5,31 @@ pkgnames=(plato) pkgdesc="Document reader" url=https://github.com/LinusCDE/plato -pkgver=0.9.25-2 -timestamp=2022-02-08T23:54Z +pkgver=0.9.34-2 +timestamp=2023-03-08T17:58Z section="readers" maintainer="Linus K. " license=AGPL-3.0-or-later installdepends=(display jq) -makedepends=(build:jq build:unzip build:wget) +makedepends=(build:jq build:unzip build:wget build:patchelf) flags=(patch_rm2fb) -image=rust:v2.2.2 -source=("https://github.com/LinusCDE/plato/archive/${pkgver%-*}-rm-release-12.zip") -sha256sums=(42e18e882e7e6853e299234a44eea9b9e3c4170076eec0577a0644dcf7005cf9) +image=rust:v2.3.1 +source=("https://github.com/LinusCDE/plato/archive/${pkgver%-*}-rm-release-13.zip") +sha256sums=(82ef5786704ecdb4fe11ce16e7e4ae10b518a592965c292977bb33962c891d48) build() { - # Fall back to system-wide config - rm .cargo/config - # 'cargo pkgid' seems to output something different with most # recent nightly builds. This adjusts the filtering. - sed -i "s/version=.*$/version=\'$(cargo pkgid | cut -d "#" -f 2 | cut -d ":" -f 2)\'/g" download.sh + sed -i "s/version=.*$/version=\'$(cargo pkgid -p plato | cut -d "#" -f 2 | cut -d ":" -f 2)\'/g" download.sh + + # Temporary fix until next release (TODO: Remove for next released version as included with commit fbfaf3d7) + sed -i "s/--target=arm-unknown-linux-gnueabihf/--target=armv7-unknown-linux-gnueabihf/g" build.sh # Use our toolchain export AR=arm-linux-gnueabihf-ar export CC=arm-linux-gnueabihf-gcc export STRIP=arm-linux-gnueabihf-strip - sed -i '/source \/usr\/local\/oecore-x86_64/d' src/mupdf_wrapper/build-kobo.sh # Compile all to dist/ ./clean.sh diff --git a/package/puzzles/package b/package/puzzles/package index c8be2ea79..8ac7d3e84 100644 --- a/package/puzzles/package +++ b/package/puzzles/package @@ -5,7 +5,8 @@ pkgnames=(puzzles) timestamp=2021-03-04T14:03-08:00 maintainer="Mattéo Delabre " -pkgver=0.2.2-3 +_ver=0.2.4 +pkgver=${_ver}-4 license=MIT pkgdesc="Simon Tatham's Puzzle Package" url="https://github.com/mrichards42/remarkable_puzzles" @@ -13,13 +14,13 @@ section="games" makedepends=(build:git) flags=(patch_rm2fb) -image=python:v2.1 +image=python:v2.3.2 source=( "https://github.com/mrichards42/remarkable_puzzles/releases/download/v${pkgver%-*}/puzzles-source.tar.gz" puzzles.draft ) sha256sums=( - 3fe3686757e69d1267e830ba527d15ff6d1a68e34f830842dcaf35f58b43d501 + ae00474f6b1f7ced13bd6b1f18ff57b583fcd66c587a5180e87af997768345ff SKIP ) @@ -27,7 +28,7 @@ build() { pip3 install okp # do the build - ARCH=arm BUILD=release make puzzles -r + make puzzles ARCH=rm BUILD=release RMP_VERSION="${_ver}" } package() { diff --git a/package/quickjs/package b/package/quickjs/package index 78467226b..ef41e2092 100644 --- a/package/quickjs/package +++ b/package/quickjs/package @@ -5,29 +5,26 @@ pkgnames=(quickjs) pkgdesc="A small and embeddable Javascript engine" url=https://bellard.org/quickjs/ -pkgver=2020.11.08-2 +pkgver=2024.01.13-1 section="devel" -timestamp=2020-11-08T13:44Z +timestamp=2024-01-13T00:00Z maintainer="khanhas " license=MIT -image=base:v2.1 +image=base:v3.1 source=( - https://bellard.org/quickjs/quickjs-2020-11-08.tar.xz - quickjs.patch + https://bellard.org/quickjs/quickjs-2024-01-13.tar.xz ) sha256sums=( - 2e9d63dab390a95ed365238f21d8e9069187f7ed195782027f0ab311bb64187b - SKIP + 3c4bf8f895bfa54beb486c8d1218112771ecfc5ac3be1036851ef41568212e03 ) build() { - patch -u Makefile -i quickjs.patch - make qjs.arm + make CROSS_PREFIX="$CROSS_COMPILE" qjs qjscalc } package() { install -d "$pkgdir"/opt/bin - install -D -m 755 -t "$pkgdir"/opt/bin/ "$srcdir"/qjs.arm - mv "$pkgdir"/opt/bin/qjs.arm "$pkgdir"/opt/bin/qjs + install -D -m 755 -t "$pkgdir"/opt/bin/ "$srcdir"/qjs + ln -s qjs "$pkgdir"/opt/bin/qjscalc } diff --git a/package/quickjs/quickjs.patch b/package/quickjs/quickjs.patch deleted file mode 100644 index 250c666b5..000000000 --- a/package/quickjs/quickjs.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- Makefile 2020-11-08 23:21:09.000000000 +1000 -+++ Makefile.new 2021-02-10 14:36:08.954392400 +1000 -@@ -60,8 +60,8 @@ - endif - EXE=.exe - else -- CROSS_PREFIX= -- EXE= -+ CROSS_PREFIX=$(CROSS_COMPILE) -+ EXE=.arm - endif - ifdef CONFIG_CLANG - HOST_CC=clang diff --git a/package/reboot-guard/package b/package/reboot-guard/package index 61825f748..965c8a59b 100644 --- a/package/reboot-guard/package +++ b/package/reboot-guard/package @@ -5,7 +5,7 @@ pkgnames=(reboot-guard) pkgdesc="Block systemd-initiated poweroff/reboot/halt until configurable condition checks pass" url=https://github.com/stephanritscher/reboot-guard -pkgver=1.0.1-6 +pkgver=1.0.1-8 timestamp=2020-05-04T06:16Z section="devel" maintainer="Eeems " @@ -34,9 +34,7 @@ configure() { } preremove() { - if systemctl list-units --full -all | grep -Fq 'rguard.service'; then - systemctl disable --now rguard - fi + disable-unit rguard.service } postremove() { diff --git a/package/recrossable/package b/package/recrossable/package index 7b191353b..476b87bef 100644 --- a/package/recrossable/package +++ b/package/recrossable/package @@ -5,7 +5,7 @@ pkgnames=(recrossable) pkgdesc="Solve crossword puzzles" url=https://github.com/sandsmark/recrossable -pkgver=0.0.0-7 +pkgver=0.0.0-8 timestamp=2021-01-15T12:58:22Z section="games" maintainer="Mattéo Delabre " diff --git a/package/regenda/package b/package/regenda/package new file mode 100644 index 000000000..1f2b48c9b --- /dev/null +++ b/package/regenda/package @@ -0,0 +1,55 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(regenda) +pkgdesc="Caldav agenda app" +url=https://github.com/tenJirka/reGenda +pkgver=0.0.2-2 +timestamp=2023-09-06T06:45Z +section="utils" +maintainer="tenJirka " +license=GPL3 +makedepends=(build:python3-venv) +installdepends=(python3 python3-lxml python3-pytz python3-yaml python3-requests python3-dateutil python3-six python3-urllib3 python3-idna simple) +flags=(patch_rm2fb) +source=(https://github.com/tenJirka/reGenda/archive/refs/tags/0.0.2.zip) +sha256sums=(4f51de514945f9cfc6a1852181baab4bb0f4daadb222e8ddb05929f17e2044d9) +image=python + +build() { + python3 -m venv venv + # shellcheck disable=SC1091 + source venv/bin/activate + mkdir "$srcdir"/python_modules + pip install caldav rm_pysas -t "$srcdir"/python_modules +} + +package() { + install -D -m 644 -t "$pkgdir"/opt/etc/draft/ "$srcdir"/regenda.draft + install -D -m 644 -t "$pkgdir"/opt/etc/reGenda/ "$srcdir"/config.yml.example + install -D -m 644 "$srcdir"/icon.png "$pkgdir"/opt/etc/draft/icons/reGenda.png + install -D -m 755 -t "$pkgdir"/opt/usr/lib/reGenda/ "$srcdir"/run.py + install -D -m 644 -t "$pkgdir"/opt/usr/lib/reGenda/ "$srcdir"/languages.py + install -D -m 644 -t "$pkgdir"/opt/usr/lib/reGenda/ "$srcdir"/calendar_caldav.py + mkdir "$pkgdir"/opt/bin/ + ln -s /opt/usr/lib/reGenda/run.py "$pkgdir"/opt/bin/reGenda + cp -r "$srcdir"/python_modules/caldav* "$pkgdir"/opt/usr/lib/reGenda/ + cp -r "$srcdir"/python_modules/icalendar* "$pkgdir"/opt/usr/lib/reGenda/ + cp -r "$srcdir"/python_modules/rm_pySAS* "$pkgdir"/opt/usr/lib/reGenda/ + cp -r "$srcdir"/python_modules/recurring_ical_events* "$pkgdir"/opt/usr/lib/reGenda/ + cp -r "$srcdir"/python_modules/tzlocal* "$pkgdir"/opt/usr/lib/reGenda/ + cp -r "$srcdir"/python_modules/vobject* "$pkgdir"/opt/usr/lib/reGenda/ + cp -r "$srcdir"/python_modules/x_wr_timezone* "$pkgdir"/opt/usr/lib/reGenda/ +} + +configure() { + if [ ! -f /opt/etc/reGenda/config.yml ]; then + cp /opt/etc/reGenda/config.yml.example /opt/etc/reGenda/config.yml + echo -e "\033[33mYou have to config server in /opt/etc/reGenda/config.yml, see https://github.com/tenJirka/reGenda for help.\033[0;39m" + fi +} + +postremove() { + rm -f /opt/usr/lib/reGenda/**/*.cpython-*.pyc +} diff --git a/package/remarkable-stylus/package b/package/remarkable-stylus/package index 6d374e4fa..d54f87f97 100644 --- a/package/remarkable-stylus/package +++ b/package/remarkable-stylus/package @@ -2,8 +2,9 @@ # Copyright (c) 2021 The Toltec Contributors # SPDX-License-Identifier: MIT +archs=(rmallos2) pkgnames=(remarkable-stylus) -pkgver=0.0.3-2 +pkgver=0.0.3-3 pkgdesc="Generate a key press upon pressing the button of a Lamy AL-star EMR pen" timestamp=2020-11-19T20:07:29Z maintainer="Eeems " diff --git a/package/remarkable_templates/package b/package/remarkable_templates/package new file mode 100644 index 000000000..6cae08725 --- /dev/null +++ b/package/remarkable_templates/package @@ -0,0 +1,142 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=( + template-daily-planner + template-weekly-planner + template-journal + template-meeting-notes + template-smart-goals + template-good-time-journal +) +url=https://github.com/msencer/remarkable_templates +pkgver=0.0.0-1 +timestamp=2023-07-27T12:28:59Z +section="templates" +maintainer="Eeems " +license=MIT +installdepends=(templatectl) + +source=("https://github.com/msencer/remarkable_templates/archive/03282d34b905e7e6431132b022b5a9cb3af116a2.zip") +sha256sums=(7a39d53767963f59c8d5b8a7ebda411b60d1256fe1077a3864cc43cd59281e03) + +template-daily-planner() { + pkgdesc="Daily Planner template" + package() { + install -D -m 755 \ + -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/pngs/daily_planner.png + } + configure() { + templatectl add \ + --name "Daily Planner" \ + --filename "daily_planner" \ + --category "Custom" \ + --category "Life/organize" \ + --icon_code "e9da" + } + preremove() { + templatectl remove --name "Daily Planner" + } +} + +template-weekly-planner() { + pkgdesc="Weekly Planner template" + package() { + install -D -m 755 \ + -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/pngs/weekly_planner.png + } + configure() { + templatectl add \ + --name "Weekly Planner" \ + --filename "weekly_planner" \ + --category "Custom" \ + --category "Life/organize" \ + --icon_code "e997" + } + preremove() { + templatectl remove --name "Weekly Planner" + } +} + +template-journal() { + pkgdesc="Journal template" + package() { + install -D -m 755 \ + -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/pngs/journal.png + } + configure() { + templatectl add \ + --name "Journal" \ + --filename "journal" \ + --category "Custom" \ + --category "Life/organize" \ + --icon_code "e991" + } + preremove() { + templatectl remove --name "Journal" + } +} + +template-meeting-notes() { + pkgdesc="Meeting Notes template" + package() { + install -D -m 755 \ + -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/pngs/meeting_notes.png + } + configure() { + templatectl add \ + --name "1:1 / Meeting Notes" \ + --filename "meeting_notes" \ + --category "Custom" \ + --category "Life/organize" \ + --icon_code "e9d8" + } + preremove() { + templatectl remove --name "1:1 / Meeting Notes" + } +} + +template-smart-goals() { + pkgdesc="Smart Goals template" + package() { + install -D -m 755 \ + -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/pngs/goals.png + } + configure() { + templatectl add \ + --name "Smart Goals" \ + --filename "goals" \ + --category "Custom" \ + --category "Life/organize" \ + --icon_code "e98f" + } + preremove() { + templatectl remove --name "Smart Goals" + } +} + +template-good-time-journal() { + pkgdesc="Smart Goals template" + package() { + install -D -m 755 \ + -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/pngs/gt_journal.png + } + configure() { + templatectl add \ + --name "Good Time Journal" \ + --filename "gt_journal" \ + --category "Custom" \ + --category "Life/organize" \ + --icon_code "e9b2" + } + preremove() { + templatectl remove --name "Good Time Journal" + } +} diff --git a/package/restream/package b/package/restream/package index bae5968e0..3c1bf017c 100644 --- a/package/restream/package +++ b/package/restream/package @@ -5,20 +5,17 @@ pkgnames=(restream) pkgdesc="Binary framebuffer capture tool for the reStream script" url=https://github.com/rien/reStream -pkgver=1.1-2 -timestamp=2021-01-28T23:25:40Z +pkgver=1.2.0-1 +timestamp=2021-11-04T19:09:14Z section="screensharing" maintainer="Dan Shick " license=MIT image=rust:v2.1 -source=("https://github.com/rien/reStream/archive/${pkgver%-*}.tar.gz") -sha256sums=(89fa4c8adfcdfb5266e11d1f8ed4c5d8dac12a68a7ee5622cf21f833bca1704f) +source=("https://github.com/rien/reStream/archive/refs/tags/${pkgver%-*}.tar.gz") +sha256sums=(4166142b15e1e7363dac302aa92aad5b44e0514cab233abecb51414952c1d5a1) build() { - # Fall back to system-wide config - rm .cargo/config - cargo build --release --bin restream } diff --git a/package/reterm/package b/package/reterm/package new file mode 100644 index 000000000..f8dee0995 --- /dev/null +++ b/package/reterm/package @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT +pkgnames=(reterm) +pkgdesc="Landscape terminal support for the Remarkable 2 + type cover" +section="admin" +pkgver="20230628.1927-2" +timestamp="2023-06-28T19:28:06Z" +maintainer="Eeems " +url="https://github.com/i-am-shodan/ReTerm" +license=MIT +_gitcommit="5730f56cf25642b9752fb9d7987a40f6af6b5f59" +source=(https://github.com/i-am-shodan/ReTerm/archive/refs/tags/release_20230628_1927.tar.gz) +sha256sums=(3a6db39cfb83606c4ac5153fe2ac0319ab5c8322c73172178534c047a15c635b) +image=dotnet6:latest +makedepends=(build:gawk build:git) + +prepare() { + cd "$srcdir" + git config --global --add safe.directory /src + git init + git remote add origin https://github.com/i-am-shodan/ReTerm.git + git fetch --depth=1 origin "$_gitcommit" + git checkout -f "$_gitcommit" + git submodule update --init --force +} + +build() { + dotnet publish \ + -r linux-arm \ + --self-contained true \ + -p:PublishSingleFile=true \ + -p:PublishedTrimmed=true \ + -p:PublishReadyToRun=true \ + -p:Configuration=Release \ + -p:PublishReadyToRunShowWarnings=true \ + src/ReTerm/ReTerm.csproj +} + +package() { + local pubdir + pubdir="$srcdir"/src/ReTerm/bin/Release/net6.0/linux-arm/publish + install -D -m 755 -t "$pkgdir"/opt/usr/lib/reterm "$pubdir"/ReTerm + install -D -m 755 -T "$pubdir"/ReTerm.sh "$pkgdir"/opt/bin/ReTerm + sed -i 's|/home/root/ReTerm/ReTerm|/opt/usr/lib/reterm/ReTerm|' "$pkgdir"/opt/bin/ReTerm + install -D -m 644 -t "$pkgdir"/opt/etc/draft "$srcdir"/draft/reterm.draft + sed -i 's|/home/root/ReTerm/ReTerm.sh|/opt/bin/ReTerm|' "$pkgdir"/opt/etc/draft/reterm.draft + sed -i 's|killall -9 dotnet|killall ReTerm|' "$pkgdir"/opt/etc/draft/reterm.draft + install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons "$srcdir"/draft/reterm.png + install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/oxide/reterm.oxide +} diff --git a/package/retris/package b/package/retris/package index 173b5d8ba..db8a00839 100644 --- a/package/retris/package +++ b/package/retris/package @@ -5,7 +5,7 @@ pkgnames=(retris) pkgdesc="Tetris game" url=https://github.com/LinusCDE/retris -pkgver=0.6.3-3 +pkgver=0.6.3-4 timestamp=2021-01-30T02:41Z section="games" maintainer="Linus K. " diff --git a/package/rm2-suspend-fix/package b/package/rm2-suspend-fix/package index dc4a1d0cb..4a6eb0151 100644 --- a/package/rm2-suspend-fix/package +++ b/package/rm2-suspend-fix/package @@ -6,9 +6,9 @@ archs=(rm2) pkgnames=(rm2-suspend-fix) pkgdesc="Fix issue where suspend breaks networking on the reMarkable 2" url=https://toltec-dev.org/ -pkgver=0.0.0-2 +pkgver=0.0.0-3 timestamp=2021-01-04T22:40Z -section="devel" +section="utils" maintainer="Eeems " license=MIT diff --git a/package/rmfakecloud-proxy/package b/package/rmfakecloud-proxy/package index 5b31846ad..2ea0502d7 100644 --- a/package/rmfakecloud-proxy/package +++ b/package/rmfakecloud-proxy/package @@ -7,7 +7,7 @@ pkgdesc="Connect Xochitl to a rmfakecloud server" _url=https://github.com/ddvk/rmfakecloud-proxy url="$_url" _upver=0.0.3 -pkgver="$_upver-4" +pkgver="$_upver-6" timestamp=2022-02-26T22:59Z section="utils" maintainer="Mattéo Delabre " @@ -55,7 +55,7 @@ configure() { install-hosts else uninstall-certificates - systemctl disable --now rmfakecloud-proxy + disable-unit rmfakecloud-proxy.service uninstall-hosts fi diff --git a/package/rmfakecloud-proxy/rmfakecloudctl b/package/rmfakecloud-proxy/rmfakecloudctl index 0dd4ada42..11e7053a0 100644 --- a/package/rmfakecloud-proxy/rmfakecloudctl +++ b/package/rmfakecloud-proxy/rmfakecloudctl @@ -75,7 +75,7 @@ disconnect-cloud() { # Mark all files as not synced grep sync "$xochitl_data_dir"/*.metadata -l \ - | xargs sed -i 's/synced\": true/synced\": false/' + | xargs -r sed -i 's/synced\": true/synced\": false/' # Disconnect from cloud sed -i '/^devicetoken=/d' "$xochitl_conf_path" diff --git a/package/rmfm/package b/package/rmfm/package new file mode 100644 index 000000000..81c25a3ad --- /dev/null +++ b/package/rmfm/package @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Copyright (c) 2020 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(rmfm) +pkgdesc="Bare-bones file manager using Node.js and sas" +url="https://forgejo.sny.sh/sun/rmFM" +pkgver=1.5.1-1 +timestamp=2023-12-06T08:51:41+01:00 +section=utils +maintainer="Sunny " +license=Unlicense +installdepends=(node simple) + +source=( + https://forgejo.sny.sh/sun/rmFM/archive/1.5.1.zip + path_fix.patch +) +sha256sums=( + 054569a5e1f420b9046ee2c4067749a1e0bccd88acc216e485b9665a42f4dd60 + SKIP +) + +prepare() { + # Assume node to be in /opt/bin + # This is a temporary fix for not working in remux + patch -d "$srcdir" < "$srcdir"/path_fix.patch +} + +package() { + install -D -m 755 "$srcdir"/rmfm "$pkgdir"/opt/bin/rmfm + install -D -m 644 "$srcdir"/rmfm.draft "$pkgdir"/opt/etc/draft/rmfm.draft + install -D -m 644 "$srcdir"/rmfm.png "$pkgdir"/opt/etc/draft/icons/rmfm.png +} diff --git a/package/rmfm/path_fix.patch b/package/rmfm/path_fix.patch new file mode 100644 index 000000000..d8c314aef --- /dev/null +++ b/package/rmfm/path_fix.patch @@ -0,0 +1,7 @@ +diff --git a/rmfm b/rmfm +index 63eeb98..b28dbd0 100755 +--- a/rmfm ++++ b/rmfm +@@ -1 +1 @@ +-#!/usr/bin/env node ++#!/opt/bin/node diff --git a/package/rmkit/changelog b/package/rmkit/changelog index 0314a5001..09d14f032 100644 --- a/package/rmkit/changelog +++ b/package/rmkit/changelog @@ -1,3 +1,55 @@ +2024-01-11 raisjn + + harmony + + * fix for buffer crash / weird buffers when saved buffer is wrong dims + + remux + + * add launcher-ctrl APIs + + iago + + * add table shape (yogatbear) + + rmkit + + * refactor how scene stack works + * fixes for image code + + genie + + * add support for conf directory + +2023-03-12 raisjn + + harmony + + * fix exporting individual layers + + rmkit + + * swap M and N on keyboard + * fix image thumbnail code + + simple: + + * add "range" input widget + * add "canvas" widget + * less debug output + * make images clickable + * move 'timeout' to its own thread instead of jamming task queue + * ignore empty lines + + remux + + * add "suspend" to remux FIFO api + + rpncalc + + * make it more hp48 like (@cesss) + + 2022-05-06 raisjn remux diff --git a/package/rmkit/launcherctl-remux b/package/rmkit/launcherctl-remux new file mode 100755 index 000000000..46538ba50 --- /dev/null +++ b/package/rmkit/launcherctl-remux @@ -0,0 +1,167 @@ +#!/bin/bash +set -e +remux_pid() { + systemctl show --no-pager --property MainPID remux.service | sed 's|MainPID=||' +} +remux_ppid() { + grep "PPid:" "/proc/$(remux_pid)/status" | awk '{print $2}' +} +draft_apps() { + find {/opt,}/etc/draft -maxdepth 1 -type f 2> /dev/null | while read -r file; do + name="$(grep 'name=' "$file" | sed 's|^name=||')" + call="$(grep 'call=' "$file" | sed 's|^call=||')" + echo -e "${name}\t${call}" + done +} +running_remux_apps() { + /opt/libexec/ps-procps-ng --ppid "$(remux_ppid)" -o pid,state,args | tail -n +2 | while read -r info; do + if [[ "$(echo "$info" | awk '{print $2}')" != "$1" ]]; then + continue + fi + pid="$(echo "$info" | awk '{print $1}')" + cmdline="$(echo "$info" | awk '{for (i=3; i<=NF; i++) print $i}')" + draft_apps | while read -r info; do + name="$(echo "$info" | cut -f1)" + if [[ "$name" == "xochitl" ]]; then + if [[ "$(realpath "/proc/${pid}/exe")" == "/usr/bin/xochitl" ]]; then + echo "$name" + break + fi + fi + call="$(echo "$info" | cut -f2)" + if [[ "$cmdline" == "$call" ]]; then + echo "$name" + break + fi + if ! [ -f "$call" ]; then + continue + fi + if [[ "$(realpath "/proc/${pid}/exe")" == "$(realpath "$call")" ]]; then + echo "$name" + break + fi + done + done +} +kill_pid() { + pid="$1" + if [[ "$(awk '{print $3}' "/proc/${pid}/stat")" == "T" ]]; then + kill -CONT "$pid" + fi + kill -TERM "$pid" + # Wait 5s for process to exit + start="$(date +'%s')" + while kill -0 "$pid" 2> /dev/null; do + sleep 0.5 + if [ "$(date +'%s')" -gt $((start + 5)) ]; then + break + fi + done + if kill -0 "$pid" 2> /dev/null; then + # If process is still running, force kill it + kill -KILL "$pid" + fi +} +case "$1" in + is-active) + systemctl is-active --quiet remux.service + ;; + is-enabled) + systemctl is-enabled --quiet remux.service + ;; + logs) + if [ $# -eq 2 ] && [[ "$2" == "-f" ]] || [[ "$2" == "--follow" ]]; then + journalctl --follow --all --unit remux.service + else + journalctl --no-pager --all --unit remux.service + fi + ;; + start) + systemctl start remux.service + ;; + stop) + systemctl stop remux.service + ;; + enable) + systemctl enable remux.service + ;; + disable) + systemctl disable remux.service + ;; + apps) + find {/opt,}/etc/draft -maxdepth 1 -type f 2> /dev/null | while read -r file; do + grep 'name=' "$file" | sed 's|^name=||' + done + ;; + running) + running_remux_apps S + ;; + paused) + running_remux_apps T + ;; + launch | resume) + echo "launch $2" > /run/remux.api + ;; + close) + draft_apps | while read -r info; do + name="$(echo "$info" | cut -f1)" + if [[ "$name" != "$2" ]]; then + continue + fi + call="$(echo "$info" | cut -f2)" + /opt/libexec/ps-procps-ng --ppid "$(remux_ppid)" -o pid,args | tail -n +2 | while read -r info; do + pid="$(echo "$info" | awk '{print $1}')" + if [[ "$name" == "xochitl" ]]; then + if [[ "$(realpath "/proc/${pid}/exe")" == "/usr/bin/xochitl" ]]; then + kill_pid "$pid" + continue + fi + fi + cmdline="$(echo "$info" | awk '{for (i=2; i<=NF; i++) print $i}')" + if [[ "$cmdline" == "$call" ]]; then + kill_pid "$pid" + continue + fi + if ! [ -f "$call" ]; then + continue + fi + if [[ "$(realpath "/proc/${pid}/exe")" == "$(realpath "$call")" ]]; then + kill_pid "$pid" + fi + done + done + ;; + pause) + draft_apps | while read -r info; do + name="$(echo "$info" | cut -f1)" + if [[ "$name" != "$2" ]]; then + continue + fi + call="$(echo "$info" | cut -f2)" + /opt/libexec/ps-procps-ng --ppid "$(remux_ppid)" -o pid,args | tail -n +2 | while read -r info; do + pid="$(echo "$info" | awk '{print $1}')" + if [[ "$name" == "xochitl" ]]; then + if [[ "$(realpath "/proc/${pid}/exe")" == "/usr/bin/xochitl" ]]; then + kill -STOP "$pid" + continue + fi + fi + cmdline="$(echo "$info" | awk '{for (i=2; i<=NF; i++) print $i}')" + if [[ "$cmdline" == "$call" ]]; then + kill -STOP "$pid" + continue + fi + if ! [ -f "$call" ]; then + continue + fi + if [[ "$(realpath "/proc/${pid}/exe")" == "$(realpath "$call")" ]]; then + kill -STOP "$pid" + fi + done + done + ;; + *) + echo "Remux does not support this method" + exit 1 + ;; +esac diff --git a/package/rmkit/package b/package/rmkit/package index 54d83c3ac..f1839892f 100644 --- a/package/rmkit/package +++ b/package/rmkit/package @@ -3,20 +3,22 @@ # SPDX-License-Identifier: MIT pkgnames=(bufshot dumbskull genie harmony iago lamp mines nao remux rpncalc simple wordlet) -timestamp=2022-06-23T20:03:10Z +timestamp=2024-01-11T20:03:10Z maintainer="raisjn " license=MIT installdepends=(display) -flags=(patch_rm2fb) +flags=() image=python:v2.1 source=( - https://github.com/rmkit-dev/rmkit/archive/070d5df29a71e55050a5e993f047f1590d69ec1c.zip + https://github.com/rmkit-dev/rmkit/archive/7edc291646c4a72b7b8a512205646a9ad6586fd6.zip remux.service genie.service + launcherctl-remux ) sha256sums=( - e7f0379d5ad9de61c32a296ab831780cfea73352fbccfe2472422165943457ef + 2861ea61ef272acd0d1d9ec4c80f44ef620be3f8ce58a356fbcbdb27e01dc9e8 + SKIP SKIP SKIP ) @@ -29,7 +31,7 @@ build() { bufshot() { pkgdesc="program for saving the framebuffer as a png" url="https://github.com/rmkit-dev/rmkit/tree/master/src/bufshot" - pkgver=0.1.2-2 + pkgver=0.1.2-3 section="utils" package() { @@ -40,20 +42,19 @@ bufshot() { dumbskull() { pkgdesc="Dungeon Crawl themed Solitaire" url="https://rmkit.dev/apps/dumbskull" - pkgver=0.0.1-2 + pkgver=0.0.1-4 section="games" package() { install -D -m 755 "$srcdir"/src/build/dumbskull "$pkgdir"/opt/bin/dumbskull install -D -m 644 "$srcdir"/src/dumbskull/dumbskull.draft "$pkgdir"/opt/etc/draft/dumbskull.draft } - } genie() { pkgdesc="Gesture engine that connects commands to gestures" url="https://rmkit.dev/apps/genie" - pkgver=0.1.6-2 + pkgver=0.1.7-2 section="utils" package() { @@ -68,8 +69,7 @@ genie() { } preremove() { - echo "Disabling $pkgname" - systemctl disable --now "$pkgname" + disable-unit "$pkgname.service" } postremove() { @@ -80,7 +80,7 @@ genie() { harmony() { pkgdesc="Procedural sketching app" url="https://rmkit.dev/apps/harmony" - pkgver=0.2.1-1 + pkgver=0.2.3-2 section="drawing" package() { @@ -97,7 +97,7 @@ harmony() { iago() { pkgdesc="overlay for drawing shapes via stroke injection" url="https://rmkit.dev/apps/iago" - pkgver=0.1.1-2 + pkgver=0.1.2-2 section="utils" installdepends+=("lamp") @@ -109,7 +109,7 @@ iago() { lamp() { pkgdesc="config based stroke injection utility" url="https://rmkit.dev/apps/lamp" - pkgver=0.1.1-2 + pkgver=0.1.1-3 section="utils" package() { @@ -120,7 +120,7 @@ lamp() { mines() { pkgdesc="Mine detection game" url="https://rmkit.dev/apps/minesweeper" - pkgver=0.1.4-2 + pkgver=0.1.4-4 section="games" package() { @@ -133,7 +133,7 @@ mines() { nao() { pkgdesc="Nao Package Manager: opkg UI built with SAS" url="https://rmkit.dev/apps/nao" - pkgver=0.1.2-3 + pkgver=0.1.2-4 section="admin" installdepends+=(simple) @@ -147,28 +147,33 @@ nao() { remux() { pkgdesc="Launcher that supports multi-tasking applications" url="https://rmkit.dev/apps/remux" - pkgver=0.2.3-1 + pkgver=0.3.0-6 section="launchers" + installdepends=(procps-ng-ps) + package() { install -D -m 755 "$srcdir"/src/build/remux "$pkgdir"/opt/bin/remux install -D -m 644 "$srcdir"/remux.service "$pkgdir"/lib/systemd/system/remux.service + install -D -T -m 755 "$srcdir"/launcherctl-remux "$pkgdir"/opt/share/launcherctl/"$pkgname" } configure() { systemctl daemon-reload - if ! is-enabled "$pkgname.service"; then + if ! launcherctl is-current-launcher "$pkgname"; then echo "" echo "Run the following command(s) to use $pkgname as your launcher" - how-to-enable "$pkgname.service" + echo "launcherctl switch-launcher --start $pkgname" echo "" fi } preremove() { - echo "Disabling $pkgname" - systemctl disable --now "$pkgname" + # Just in case more than one launcher is active, do individual checks + if launcherctl is-active-launcher "$pkgname" || launcherctl is-enabled-launcher "$pkgname"; then + launcherctl switch-launcher --start xochitl + fi } postremove() { @@ -179,7 +184,7 @@ remux() { rpncalc() { pkgdesc="RPN Calculator" url="https://rmkit.dev/apps/rpncalc" - pkgver=0.0.2-2 + pkgver=0.0.3-4 section="math" package() { @@ -187,13 +192,12 @@ rpncalc() { install -D -m 644 "$srcdir"/src/rpncalc/rpncalc.draft "$pkgdir"/opt/etc/draft/rpncalc.draft install -D -m 644 "$srcdir"/src/rpncalc/rpncalc.png "$pkgdir"/opt/etc/draft/icons/rpncalc.png } - } simple() { pkgdesc="Simple app script for writing scripted applications" url="https://rmkit.dev/apps/sas" - pkgver=0.1.5-2 + pkgver=0.2.1-2 section="devel" package() { @@ -204,12 +208,11 @@ simple() { wordlet() { pkgdesc="Wordle clone" url="https://rmkit.dev/apps/wordlet" - pkgver=0.0.1-2 + pkgver=0.0.2-4 section="games" package() { install -D -m 755 "$srcdir"/src/build/wordlet "$pkgdir"/opt/bin/wordlet install -D -m 644 "$srcdir"/src/wordlet/wordlet.draft "$pkgdir"/opt/etc/draft/wordlet.draft } - } diff --git a/package/signature-rm/package b/package/signature-rm/package new file mode 100644 index 000000000..d826d244c --- /dev/null +++ b/package/signature-rm/package @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +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-3 +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=(webinterface-onboot) +conflicts_rmallos2=(ddvk-hacks) + +source=( + "$url"/archive/b5561af4eb6a0f5aa6e98e1a1279066f0c4bd9b7.zip +) +sha256sums=( + 1a7cc8bf7a3f5a7cc9a10ca968bbb5a0082a065760f4cb7038fdb6b9aed4bb00 +) + +build() { + cargo build --release +} + +package() { + install -D -m 755 -t "$pkgdir"/opt/bin \ + "$srcdir/target/armv7-unknown-linux-gnueabihf/release/$pkgname" + + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" +} + +configure() { + echo + echo "Applying signature-rM" + signature-rm apply -y > /dev/null + echo "Success" + echo +} + +_restore() { + echo "Reverting /usr/bin/xochitl" + if signature-rm has-backup > /dev/null; then + signature-rm revert --backup -y > /dev/null + else + signature-rm revert --reverse -y > /dev/null + fi + echo "Success" + echo +} + +preremove() { + _restore +} + +preupgrade() { + _restore +} diff --git a/package/sill/package b/package/sill/package new file mode 100644 index 000000000..f34ee5fe2 --- /dev/null +++ b/package/sill/package @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Copyright (c) 2020 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(sill) +pkgdesc="Gesture-based text editor (and shell) for the reMarkable tablet" +url=https://github.com/bkirwi/sill +pkgver=0.1.1-1 +section="writing" +timestamp=2023-08-12T00:00Z +maintainer="Kai " +license="Apache-2.0" + +image=rust:v3.0 +source=( + https://github.com/bkirwi/sill/archive/refs/tags/v0.1.1.tar.gz + sill.draft +) +sha256sums=( + ed3ef2f7ff37101db16f7020e6af86da6c32e78d76247c91a1676b72ce87e3df + SKIP +) + +build() { + cargo build --release +} + +package() { + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/target/armv7-unknown-linux-gnueabihf/release/sill + install -D -m 644 "$srcdir"/sill.draft "$pkgdir"/opt/etc/draft/sill.draft +} diff --git a/package/sill/sill.draft b/package/sill/sill.draft new file mode 100644 index 000000000..58349bed1 --- /dev/null +++ b/package/sill/sill.draft @@ -0,0 +1,7 @@ +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +name=Sill +desc= Gesture-based text editor (and shell) for the reMarkable tablet +call=/opt/bin/sill +term=: diff --git a/package/splashcreens-wavy-lines/package b/package/splashcreens-wavy-lines/package new file mode 100644 index 000000000..86ed7f77d --- /dev/null +++ b/package/splashcreens-wavy-lines/package @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=( + splashscreen-starting-wavey-lines + splashscreen-suspended-wavey-lines +) +url=https://github.com/EnglishLFC/reMarkable +pkgver=0.0.0-1 +timestamp=2021-03-19T18:46:40Z +section="splashscreens" +maintainer="Eeems " +license=BSD-2-Clause +installdepends=(changescrn) + +source=("https://github.com/EnglishLFC/reMarkable/archive/a06b10ea9f28c784e6941085a30944c0489450f4.zip") +sha256sums=(ec5f0321342bf6b48bb1431f4b1cf4416c37681879b3ec6c9375f889077a0b7f) + +splashscreen-starting-wavey-lines() { + pkgdesc="Barnsley Fern battery empty splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -T "$srcdir"/splash/splash.png \ + "$pkgdir"/opt/share/remarkable/splashscreens/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-wavey-lines() { + pkgdesc="Barnsley Fern power off splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splash/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} diff --git a/package/splashscreens-1094/package b/package/splashscreens-1094/package new file mode 100644 index 000000000..12c395643 --- /dev/null +++ b/package/splashscreens-1094/package @@ -0,0 +1,118 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=( + splashscreen-poweroff-gallifreyan + splashscreen-suspended-gallifreyan + splashscreen-suspended-gallifreyan-dark + splashscreen-starting-gallifreyan + splashscreen-suspended-gallifreyan-2 + splashscreen-suspended-flower-pause +) +url=https://github.com/1094/rM-customizations +pkgver=0.0.0-1 +timestamp=2023-05-15T11:27:58Z +section="splashscreens" +maintainer="Eeems " +license=CC-BY-NC-3.0 +installdepends=(changescrn) + +source=("https://github.com/1094/rM-customizations/archive/623171a1268e9ff45a8669fa36637e3eabd4ca40.zip") +sha256sums=(8cc8d02fe04c12bacfc798c1f6737cb55f581f191e2bf54147256df265318a31) + +splashscreen-poweroff-gallifreyan() { + pkgdesc="Gallifreyan poweroff splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splash-screens/gallifreyan/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-suspended-gallifreyan() { + pkgdesc="Gallifreyan suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -T "$srcdir"/splash-screens/gallifreyan/sleeping-v1.png \ + "$pkgdir"/opt/share/remarkable/splashscreens/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-suspended-gallifreyan-dark() { + pkgdesc="Gallifreyan dark suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -T "$srcdir"/splash-screens/gallifreyan/sleeping-v3.png \ + "$pkgdir"/opt/share/remarkable/splashscreens/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-starting-gallifreyan() { + pkgdesc="Gallifreyan starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splash-screens/gallifreyan/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-gallifreyan-2() { + pkgdesc="Gallifreyan suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splash-screens/gallifreyan/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-suspended-flower-pause() { + pkgdesc="Flower suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -T "$srcdir"/splash-screens/misc/flower-pause.png \ + "$pkgdir"/opt/share/remarkable/splashscreens/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} diff --git a/package/splashscreens/package b/package/splashscreens/package new file mode 100644 index 000000000..224311751 --- /dev/null +++ b/package/splashscreens/package @@ -0,0 +1,705 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=( + splashscreen-batteryempty-barnsley_fern + splashscreen-poweroff-barnsley_fern + splashscreen-starting-barnsley_fern + splashscreen-suspended-barnsley_fern + + splashscreen-batteryempty-chaotic_ribbon + splashscreen-poweroff-chaotic_ribbon + splashscreen-starting-chaotic_ribbon + splashscreen-suspended-chaotic_ribbon + + splashscreen-batteryempty-collatz_sea_weed + splashscreen-poweroff-collatz_sea_weed + splashscreen-starting-collatz_sea_weed + splashscreen-suspended-collatz_sea_weed + + splashscreen-batteryempty-dragon_curve + splashscreen-poweroff-dragon_curve + splashscreen-starting-dragon_curve + splashscreen-suspended-dragon_curve + + splashscreen-batteryempty-fire + splashscreen-poweroff-fire + splashscreen-starting-fire + splashscreen-suspended-fire + + splashscreen-batteryempty-fractal_tree + splashscreen-poweroff-fractal_tree + splashscreen-starting-fractal_tree + splashscreen-suspended-fractal_tree + + splashscreen-batteryempty-sacks_spiral + splashscreen-poweroff-sacks_spiral + splashscreen-starting-sacks_spiral + splashscreen-suspended-sacks_spiral + + splashscreen-batteryempty-sierpinski_triangle + splashscreen-poweroff-sierpinski_triangle + splashscreen-starting-sierpinski_triangle + splashscreen-suspended-sierpinski_triangle + + splashscreen-batteryempty-snowy_hills + splashscreen-poweroff-snowy_hills + splashscreen-starting-snowy_hills + splashscreen-suspended-snowy_hills + + splashscreen-batteryempty-starr + splashscreen-poweroff-starr + splashscreen-starting-starr + splashscreen-suspended-starr +) +url=https://github.com/engeir/remarkable-splashscreens +pkgver=0.0.0-1 +timestamp=2023-05-19T06:37:08Z +section="splashscreens" +maintainer="Eeems " +license=MIT +installdepends=(changescrn) + +source=("https://github.com/engeir/remarkable-splashscreens/archive/18e2c2a4d1d278240079ff4eb848d5e5255cc3f2.zip") +sha256sums=(ac49db5539d3901e02b8b94b381bed6a98002371378bf2d4ffa804c80eae0efb) + +splashscreen-batteryempty-barnsley_fern() { + pkgdesc="Barnsley Fern battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/barnsley_fern/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-barnsley_fern() { + pkgdesc="Barnsley Fern power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/barnsley_fern/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-barnsley_fern() { + pkgdesc="Barnsley Fern starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/barnsley_fern/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-barnsley_fern() { + pkgdesc="Barnsley Fern suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/barnsley_fern/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-chaotic_ribbon() { + pkgdesc="Chaotic ribbon battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/chaotic_ribbon/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-chaotic_ribbon() { + pkgdesc="Chaotic ribbon power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/chaotic_ribbon/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-chaotic_ribbon() { + pkgdesc="Chaotic ribbon starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/chaotic_ribbon/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-chaotic_ribbon() { + pkgdesc="Chaotic ribbon suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/chaotic_ribbon/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-collatz_sea_weed() { + pkgdesc="Collatz sea weed battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/collatz_sea_weed/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-collatz_sea_weed() { + pkgdesc="Collatz sea weed power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/collatz_sea_weed/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-collatz_sea_weed() { + pkgdesc="Collatz sea weed starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/collatz_sea_weed/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-collatz_sea_weed() { + pkgdesc="Collatz sea weed suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/collatz_sea_weed/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-dragon_curve() { + pkgdesc="Dragon curve battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/dragon_curve/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-dragon_curve() { + pkgdesc="Dragon curve power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/dragon_curve/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-dragon_curve() { + pkgdesc="Dragon curve starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/dragon_curve/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-dragon_curve() { + pkgdesc="Dragon curve suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/dragon_curve/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-fire() { + pkgdesc="Fire battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fire/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-fire() { + pkgdesc="Fire power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fire/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-fire() { + pkgdesc="Fire starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fire/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-fire() { + pkgdesc="Fire suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fire/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-fractal_tree() { + pkgdesc="Fractal tree battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fractal_tree/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-fractal_tree() { + pkgdesc="Fractal tree power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fractal_tree/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-fractal_tree() { + pkgdesc="Fractal tree starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fractal_tree/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-fractal_tree() { + pkgdesc="Fractal tree suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/fractal_tree/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-sacks_spiral() { + pkgdesc="Sacks spiral battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sacks_spiral/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-sacks_spiral() { + pkgdesc="Sacks spiral power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sacks_spiral/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-sacks_spiral() { + pkgdesc="Sacks spiral starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sacks_spiral/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-sacks_spiral() { + pkgdesc="Sacks spiral suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sacks_spiral/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-sierpinski_triangle() { + pkgdesc="Sierpinski triangle battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sierpinski_triangle/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-sierpinski_triangle() { + pkgdesc="Sierpinski triangle power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sierpinski_triangle/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-sierpinski_triangle() { + pkgdesc="Sierpinski triangle starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sierpinski_triangle/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-sierpinski_triangle() { + pkgdesc="Sierpinski triangle suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/sierpinski_triangle/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-snowy_hills() { + pkgdesc="Snowy hills battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/snowy_hills/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-snowy_hills() { + pkgdesc="Snowy hills power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/snowy_hills/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-snowy_hills() { + pkgdesc="Snowy hills starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/snowy_hills/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-snowy_hills() { + pkgdesc="Snowy hills suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/snowy_hills/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} + +splashscreen-batteryempty-starr() { + pkgdesc="Starr battery empty splashscreen" + replaces=("splashscreen-batteryempty") + conflicts=("splashscreen-batteryempty") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/starr/batteryempty.png + } + configure() { + changescrn -c batteryempty /opt/share/remarkable/splashscreens/batteryempty.png + } + postremove() { + changescrn -r batteryempty + } +} + +splashscreen-poweroff-starr() { + pkgdesc="Starr power off splashscreen" + replaces=("splashscreen-poweroff") + conflicts=("splashscreen-poweroff") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/starr/poweroff.png + } + configure() { + changescrn -c poweroff /opt/share/remarkable/splashscreens/poweroff.png + } + postremove() { + changescrn -r poweroff + } +} + +splashscreen-starting-starr() { + pkgdesc="Starr starting splashscreen" + replaces=("splashscreen-starting") + conflicts=("splashscreen-starting") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/starr/starting.png + } + configure() { + changescrn -c starting /opt/share/remarkable/splashscreens/starting.png + } + postremove() { + changescrn -r starting + } +} + +splashscreen-suspended-starr() { + pkgdesc="Starr suspended splashscreen" + replaces=("splashscreen-suspended") + conflicts=("splashscreen-suspended") + package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/splashscreens \ + "$srcdir"/splashscreens/starr/suspended.png + } + configure() { + changescrn -c suspended /opt/share/remarkable/splashscreens/suspended.png + } + postremove() { + changescrn -r suspended + } +} diff --git a/package/sudoku/package b/package/sudoku/package new file mode 100644 index 000000000..24e7c8957 --- /dev/null +++ b/package/sudoku/package @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Copyright (c) 2024 HookedBehemoth +# SPDX-License-Identifier: GPL-3.0-only + +pkgnames=(sudoku) +pkgdesc="Sudoku for Remarkable" +url="https://github.com/HookedBehemoth/remarkable-sudoku" +pkgver=0.1.2-1 +timestamp=2023-02-04T22:49Z +section="games" +maintainer="Luis S. " +license=GPL-3.0-only +installdepends=(display) +flags=(patch_rm2fb) + +image=rust:v3.1 +source=("https://github.com/HookedBehemoth/remarkable-sudoku/archive/refs/tags/v${pkgver%-*}.tar.gz") +sha256sums=(08a801a6ffc3f328fc92c8aebadbcc7a123b1abebf5cbe276d5f9f52058ee864) + +build() { + cargo build --release +} + +package() { + install -D -m 755 -t "$pkgdir"/opt/bin \ + "$srcdir"/target/armv7-unknown-linux-gnueabihf/release/sudoku + install -D -m 644 -t "$pkgdir"/opt/etc/draft \ + "$srcdir"/sudoku.draft + install -D -m 644 -T "$srcdir"/res/702.png "$pkgdir"/opt/etc/draft/icons/sudoku.png + install -D -m 644 -t "$pkgdir"/opt/usr/share/applications \ + "$srcdir"/sudoku.oxide + install -D -m 644 -T "$srcdir"/res/702.png "$pkgdir"/opt/usr/share/icons/oxide/702x702/sudoku.png + install -D -m 644 -T "$srcdir"/res/48.png "$pkgdir"/opt/usr/share/icons/oxide/48x48/apps/sudoku.png +} diff --git a/package/sysfs_preload/package b/package/sysfs_preload/package new file mode 100644 index 000000000..73deb2392 --- /dev/null +++ b/package/sysfs_preload/package @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(sysfs_preload) +pkgdesc="A simple preload that forces any calls to /sys/power/state to use systemd instead." +url="https://github.com/Eeems-Org/sysfs_preload" +pkgver=1.0.1-2 +timestamp=2024-06-22T05:19Z +section=utils +maintainer="Eeems " +license=MIT + +image=qt:v3.1 +source=(https://github.com/Eeems-Org/sysfs_preload/archive/refs/tags/1.0.1.tar.gz) +sha256sums=(73627b68e3b2454efcc2d83e6ebdc2eb473f9cc2616ed1b9dd2acae159c54b3d) + +build() { + find . -name "*.pro" -type f -print0 \ + | xargs -r -0 sed -i 's/linux-oe-g++/linux-arm-remarkable-g++/g' + qmake + make -j"$(nproc)" + INSTALL_ROOT="dist" make install +} + +package() { + cp -ar "${srcdir}/dist/." "${pkgdir}" +} diff --git a/package/tailscale-systemd/package b/package/tailscale-systemd/package new file mode 100644 index 000000000..e8a7836f4 --- /dev/null +++ b/package/tailscale-systemd/package @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Copyright (c) 2020 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(tailscale-systemd) +pkgdesc="SystemD configuration for tailscale" +url=https://tailscale.com +pkgver=0.0.0-2 +section="utils" +timestamp=2023-07-12T00:00Z +maintainer="Kai " +license="BSD 3-Clause" +installdepends=(tailscale) + +source=( + tailscaled.service +) +sha256sums=( + SKIP +) + +package() { + install -D -m 644 -t "$pkgdir"/etc/systemd/system "$srcdir"/tailscaled.service +} + +configure() { + systemctl daemon-reload + systemctl enable tailscaled + systemctl start tailscaled +} + +preremove() { + disable-unit "tailscaled.service" +} + +postremove() { + systemctl daemon-reload +} diff --git a/package/tailscale-systemd/tailscaled.service b/package/tailscale-systemd/tailscaled.service new file mode 100644 index 000000000..35a9feb54 --- /dev/null +++ b/package/tailscale-systemd/tailscaled.service @@ -0,0 +1,24 @@ +[Unit] +Description=Tailscale node agent +Documentation=https://tailscale.com/kb/ +Wants=network-pre.target +After=network-pre.target + +[Service] +Environment="HOME=/home/root" +ExecStartPre=/opt/bin/tailscaled --cleanup +ExecStart=/opt/bin/tailscaled --state=/opt/var/lib/tailscale/tailscaled.state --socket=/opt/var/run/tailscale/tailscaled.sock --tun=userspace-networking --socks5-server=localhost:1055 --outbound-http-proxy-listen=localhost:1055 +ExecStopPost=/opt/bin/tailscaled --cleanup + +Restart=on-failure + +RuntimeDirectory=tailscale +RuntimeDirectoryMode=0755 +StateDirectory=tailscale +StateDirectoryMode=0700 +CacheDirectory=tailscale +CacheDirectoryMode=0750 +Type=notify + +[Install] +WantedBy=multi-user.target diff --git a/package/template-noso-grid/package b/package/template-noso-grid/package new file mode 100644 index 000000000..4ee1fc731 --- /dev/null +++ b/package/template-noso-grid/package @@ -0,0 +1,72 @@ +#!/usr/bin/env bash +# Copyright (c) 2022 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(template-noso-grid) +pkgdesc="Nosometric grid template" +url=https://github.com/RobotCaleb/noso_template +pkgver=1.0.0 +timestamp=2022-03-20T18:34Z +section="templates" +maintainer="Caleb Anderson " +license=MIT +installdepends=(templatectl) + +source=("https://github.com/RobotCaleb/noso_template/archive/refs/tags/v${pkgver%-*}.zip") +sha256sums=(cd7cfcb0c2e9b9734a5e79c00182a4d27858e2c6e2501da54f4d58569171a734) + +package() { + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/cube-high/noso-cube-high.png + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/cube-high/noso-cube-high.svg + + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/cube-low/noso-cube-low.png + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/cube-low/noso-cube-low.svg + + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/cube-mid/noso-cube-mid.png + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/cube-mid/noso-cube-mid.svg + + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/tall-high/noso-tall-high.png + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/tall-high/noso-tall-high.svg + + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/tall-low/noso-tall-low.png + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/tall-low/noso-tall-low.svg + + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/tall-mid/noso-tall-mid.png + install -D -m 755 -t "$pkgdir"/opt/share/remarkable/templates \ + "$srcdir"/templates/tall-mid/noso-tall-mid.svg +} + +configure() { + templatectl add -n "Noso Cube Low Density" -f "noso-cube-low.png" \ + -c "Custom" -c "Grids" + templatectl add -n "Noso Cube Mid Density" -f "noso-cube-mid.png" \ + -c "Custom" -c "Grids" + templatectl add -n "Noso Cube High Density" -f "noso-cube-high.png" \ + -c "Custom" -c "Grids" + templatectl add -n "Noso Tall Low Density" -f "noso-tall-low.png" \ + -c "Custom" -c "Grids" + templatectl add -n "Noso Tall Mid Density" -f "noso-tall-mid.png" \ + -c "Custom" -c "Grids" + templatectl add -n "Noso Tall High Density" -f "noso-tall-high.png" \ + -c "Custom" -c "Grids" +} + +preremove() { + templatectl remove --name "Noso Cube Low Density" + templatectl remove --name "Noso Cube Mid Density" + templatectl remove --name "Noso Cube High Density" + templatectl remove --name "Noso Tall Low Density" + templatectl remove --name "Noso Tall Mid Density" + templatectl remove --name "Noso Tall High Density" +} diff --git a/package/templatectl/package b/package/templatectl/package index ee2374bef..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-3 +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() { @@ -41,7 +43,15 @@ configure() { } postremove() { - remove-bind-mount /usr/share/remarkable/templates + local bind_path + local unit_name + local unit_path + bind_path=/usr/share/remarkable/templates + unit_name="$(systemd-escape --path "$bind_path").mount" + unit_path="/lib/systemd/system/$unit_name" + if [[ -e $unit_path ]]; then + remove-bind-mount "$bind_path" + fi echo "To fully remove templatectl you'll need to run the following command:" echo " rm -rf /home/root/.entware/share/remarkable/templates" diff --git a/package/tilem/package b/package/tilem/package index 436678c87..adca938fe 100644 --- a/package/tilem/package +++ b/package/tilem/package @@ -5,26 +5,45 @@ pkgnames=(tilem) pkgdesc="TI-84+ calculator emulator" url=https://github.com/timower/rM2-stuff/tree/master/apps/tilem -pkgver=0.0.7-2 -timestamp=2021-04-30T10:42Z +_tag=0.1.2 +pkgver=${_tag}-1 +timestamp=2024-05-29T17:05:56Z maintainer="Mattéo Delabre " license=GPL-3.0 section="utils" -image=base:v2.1 +image=base:v3.1 installdepends=(display) +flags=(nostrip) -source=(https://github.com/timower/rM2-stuff/archive/refs/tags/v0.0.7.tar.gz) -sha256sums=(ed2db5f1aa7c9e8b0bead53bd60cb8fd9eec24c028d789fdbdc4b1655d6c78ce) +source=() +sha256sums=() + +prepare() { + cd "$srcdir" + mkdir -p tilem + cd tilem + git init + git lfs install + git remote add origin https://github.com/timower/rM2-stuff.git + git fetch --depth 1 origin tag v${_tag} --no-tags + git checkout v${_tag} + git lfs fetch + git lfs checkout +} build() { - mkdir build + cd "$srcdir" mkdir install - cd build - cmake -DCMAKE_TOOLCHAIN_FILE="/usr/share/cmake/$CHOST.cmake" \ - -DCMAKE_INSTALL_PREFIX="../install" -DCMAKE_BUILD_TYPE=Release .. - cd apps/tilem - make - make install + cd tilem + cmake --preset release-toltec + cmake \ + --build build/release-toltec \ + --target tilem + cmake \ + --install build/release-toltec \ + --prefix ../install \ + --component tilem \ + --strip } package() { diff --git a/package/toltec-base/opt-usr-bin.sh b/package/toltec-base/opt-usr-bin.sh new file mode 100644 index 000000000..9ff6643dc --- /dev/null +++ b/package/toltec-base/opt-usr-bin.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +export PATH=/opt/usr/bin:$PATH diff --git a/package/toltec-base/package b/package/toltec-base/package index 7392b91de..6e3d8be49 100644 --- a/package/toltec-base/package +++ b/package/toltec-base/package @@ -1,23 +1,69 @@ #!/usr/bin/env bash -# Copyright (c) 2021 The Toltec Contributors +# 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.0-1 -timestamp=2022-02-28T00:12Z +pkgver=1.4-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 launcherctl wget-ssl ca-certificates entware-rc) +installdepends_rm1os2=(open-remarkable-shutdown) +installdepends_rm1os3=(open-remarkable-shutdown) +installdepends_rm2os2=(rm2-suspend-fix) +installdepends_rm2os3=(rm2-suspend-fix) -source=() -sha256sums=() +source=(opt-usr-bin.sh) +sha256sums=(SKIP) package() { - true + install -D -m 755 -t "$pkgdir"/etc/profile.d/ "$srcdir"/opt-usr-bin.sh +} + +configure() { + ln -sf /opt/etc/profile /etc/profile.d/toltec.sh + # shellcheck disable=SC2016 + sed -i \ + -e 's|^export TERM=xterm|if \[ -z "$TERM" \];then export TERM=xterm;fi|' \ + /opt/etc/profile + echo "Disabling automatic update" + disable-unit update-engine.service + 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() { + 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 + if ! is-enabled update-engine.service; then + systemctl enable update-engine + fi } diff --git a/package/toltec-bootstrap/package b/package/toltec-bootstrap/package index a07acf822..90d201f50 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.2-1 -timestamp=2022-02-28T00:12Z +pkgver=0.4.5-1 +timestamp=2024-05-31T19:13Z section="utils" maintainer="Eeems " license=MIT @@ -53,14 +53,19 @@ 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 } + +postremove() { + # Reload rules without the input udev rule + udevadm control --reload-rules && udevadm trigger +} diff --git a/package/toltec-bootstrap/toltecctl b/package/toltec-bootstrap/toltecctl index 2480d6eee..5a26d3790 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 "Reinstalling 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,22 +717,72 @@ 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-1 + local wget_checksum=c258140f059d16d24503c62c1fdf747ca843fe4ba8fcd464a6e6bda8c3bbb6b5 + + 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 - "$opkg_path" remove --force-depends --force-remove "$pkgname" + "$opkg_path" remove --force-removal-of-essential-packages --force-depends --force-remove "$pkgname" done systemctl daemon-reload @@ -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,17 +1002,21 @@ 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" - reboot + log INFO "Rebooting" + systemctl reboot + ;; + + status) + status ;; help | -h | --help) @@ -497,7 +1024,7 @@ MSG ;; *) - echo -e "Error: Invalid command '$action'\n" + log ERROR "Invalid command '$action'\n" help exit 1 ;; diff --git a/package/toltec-completion/_launcherctl b/package/toltec-completion/_launcherctl new file mode 100644 index 000000000..66deee8ac --- /dev/null +++ b/package/toltec-completion/_launcherctl @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT +# shellcheck disable=SC2016,SC2199,SC2207 + +_launcherctl() { + local cur prev words cword split + _init_completion -s || return + if [[ $cword -eq 1 ]]; then + COMPREPLY=($(compgen -W 'help status logs list-launchers switch-launcher start-launcher stop-launcher list-apps list-running-apps list-paused-apps start-app stop-app pause-app resume-app is-current-launcher is-enabled-launcher is-active-launcher' -- "$cur")) + return + fi + case ${words[1]} in + logs) + if [[ $cword -eq 2 ]]; then + COMPREPLY+=($(compgen -W "--follow" -- "$cur")) + fi + return + ;; + switch-launcher) + if [[ $cword -eq 2 ]]; then + COMPREPLY+=($(compgen -W "--start $(launcherctl list-launchers)" -- "$cur")) + elif [[ $cword -eq 3 ]]; then + COMPREPLY+=($(compgen -W "$(launcherctl list-launchers)" -- "$cur")) + fi + return + ;; + start-app) + if [[ $cword -eq 2 ]]; then + COMPREPLY+=($(compgen -W "$(launcherctl list-apps)" -- "$cur")) + fi + ;; + stop-app | pause-app) + if [[ $cword -eq 2 ]]; then + COMPREPLY+=($(compgen -W "$(launcherctl list-running-apps)" -- "$cur")) + fi + ;; + resume-app) + if [[ $cword -eq 2 ]]; then + COMPREPLY+=($(compgen -W "$(launcherctl list-paused-apps)" -- "$cur")) + fi + ;; + esac +} + +complete -F _launcherctl launcherctl diff --git a/package/toltec-completion/_rcctl b/package/toltec-completion/_rcctl new file mode 100644 index 000000000..7cefec693 --- /dev/null +++ b/package/toltec-completion/_rcctl @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT +# shellcheck disable=SC2016,SC2199,SC2207 + +_rcctl() { + local cur prev words cword split + _init_completion -s || return + if [[ $cword -eq 1 ]]; then + COMPREPLY=($(compgen -W 'help start stop restart enable disable status logs list' -- "$cur")) + return + fi + case ${words[1]} in + start | stop | restart | enable | disable | status) + if [[ $cword -eq 2 ]]; then + COMPREPLY+=($(compgen -W "$(rcctl list)" -- "$cur")) + fi + return + ;; + logs) + if [[ $cword -eq 2 ]]; then + COMPREPLY+=($(compgen -W "--follow $(rcctl list)" -- "$cur")) + elif [[ $cword -eq 3 ]]; then + COMPREPLY+=($(compgen -W "$(rcctl list)" -- "$cur")) + fi + return + ;; + esac +} + +complete -F _rcctl rcctl 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..698f50c8b 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.4.0-2 timestamp=2022-01-23T23:29Z section="utils" maintainer="Linus K. " @@ -15,10 +15,14 @@ installdepends=(bash-completion) source=( _opkg _toltecctl + _launcherctl + _rcctl ) sha256sums=( SKIP SKIP + SKIP + SKIP ) package() { diff --git a/package/toltec-deletions/package b/package/toltec-deletions/package new file mode 100644 index 000000000..4d78a343c --- /dev/null +++ b/package/toltec-deletions/package @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +archs=(rm1os2 rm1os3 rm2os2 rm2os3) +pkgnames=(toltec-deletions) +pkgdesc="Metapackage to handle package deletions between OS versions" +url=https://toltec-dev.org/ +pkgver=0.1-9 +timestamp=2023-12-03T04:51:58Z +section="utils" +maintainer="Eeems " +license=MIT +installdepends=(toltec-bootstrap) +conflicts_rm1os2=() +replaces_rm1os2=() +conflicts_rm2os2=() +replaces_rm2os2=() +conflicts_rm1os3=( + ddvk-hacks + fuse + wireguard + innernet-client + gocryptfs + remarkable-stylus +) +replaces_rm1os3=( + ddvk-hacks + fuse + wireguard + innernet-client + gocryptfs + remarkable-stylus +) +conflicts_rm2os3=( + ddvk-hacks + fuse + wireguard + innernet-client + gocryptfs + remarkable-stylus + open-remarkable-shutdown +) +replaces_rm2os3=( + ddvk-hacks + fuse + wireguard + innernet-client + gocryptfs + remarkable-stylus + open-remarkable-shutdown +) + +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/vnsee/package b/package/vnsee/package index 4ed1a8b1c..057220d0c 100644 --- a/package/vnsee/package +++ b/package/vnsee/package @@ -5,7 +5,7 @@ pkgnames=(vnsee) pkgdesc="VNC client allowing you to use the device as a second screen" url=https://github.com/matteodelabre/vnsee -pkgver=0.4.1-1 +pkgver=0.4.1-2 timestamp=2021-08-29T13:45:26Z section="screensharing" maintainer="Mattéo Delabre " diff --git a/package/webinterface-localhost/package b/package/webinterface-localhost/package new file mode 100644 index 000000000..da657551a --- /dev/null +++ b/package/webinterface-localhost/package @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# Copyright (c) 2020 The Toltec Contributors +# SPDX-License-Identifier: MIT + +_pkgname="webinterface-localhost" +pkgnames=("$_pkgname") +pkgdesc="View the web interface if running, on localhost. Useful for tailscale." +url=https://toltec-dev.org/ +pkgver=0.0.0-1 +timestamp=2024-03-11T13:03:16Z +section="utils" +maintainer="rM-self-serve <122753594+rM-self-serve@users.noreply.github.com>" +license=MIT + +source=( + "$_pkgname.socket" + "$_pkgname.service" +) + +sha256sums=( + SKIP + SKIP +) + +package() { + install -D -m 644 -t "$pkgdir/lib/systemd/system" \ + "$srcdir/$_pkgname.socket" + install -D -m 644 -t "$pkgdir/lib/systemd/system" \ + "$srcdir/$_pkgname.service" +} + +configure() { + systemctl daemon-reload + + if is-active "$pkgname".socket; then + echo "Restarting $pkgname" + systemctl restart "$pkgname".socket + fi + + systemctl enable --now "$pkgname.socket" +} + +preremove() { + disable-unit "$pkgname.socket" +} + +postremove() { + systemctl daemon-reload +} diff --git a/package/webinterface-localhost/webinterface-localhost.service b/package/webinterface-localhost/webinterface-localhost.service new file mode 100644 index 000000000..bf93761a3 --- /dev/null +++ b/package/webinterface-localhost/webinterface-localhost.service @@ -0,0 +1,8 @@ +[Unit] +Description=View the web interface if running, on localhost +Requires=webinterface-localhost.socket +After=webinterface-localhost.socket + +[Service] +Type=notify +ExecStart=/lib/systemd/systemd-socket-proxyd 10.11.99.1:80 diff --git a/package/webinterface-localhost/webinterface-localhost.socket b/package/webinterface-localhost/webinterface-localhost.socket new file mode 100644 index 000000000..25c2f8e90 --- /dev/null +++ b/package/webinterface-localhost/webinterface-localhost.socket @@ -0,0 +1,7 @@ +[Socket] +Description=View the web interface if running, on localhost +ListenStream=127.0.0.1:80 +FreeBind=true + +[Install] +WantedBy=sockets.target diff --git a/package/webinterface-onboot/package b/package/webinterface-onboot/package new file mode 100644 index 000000000..0040ffc06 --- /dev/null +++ b/package/webinterface-onboot/package @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +archs=(rmallos2 rmallos3) +pkgnames=("webinterface-onboot") +pkgdesc="Start the web interface without the cable, on boot." +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=(signature-rm) +conflicts_rmallos2=(ddvk-hacks) +installdepends=(libbfd) + +source=( + "$url"/archive/e184b6a37ccba0ebeacd34faf63c8f4cdfa5c448.zip + "webinterface-onboot-toltec.service" +) +sha256sums=( + 2e3666b1875f874ef09da2bbd163295b89e9e241f1e59e77349b0e2db716b8ff + SKIP +) + +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" + + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" +} + +configure() { + systemctl daemon-reload + + echo + echo "Applying usb0 ip persistence" + webinterface-onboot apply-prstip -y > /dev/null + echo "Success" + if webinterface-onboot is-hack-version > /dev/null; then + echo + echo "Applying binary modification" + webinterface-onboot apply-hack -y > /dev/null + echo "Success" + fi + + echo + echo "Run the following command to use $pkgname" + how-to-enable "$pkgname.service" + echo + echo "Then restart xochitl or the device" +} + +_restore() { + if webinterface-onboot is-prstip-applied > /dev/null; then + echo + echo "Reverting usb0 ip persistence" + webinterface-onboot revert-prstip -y > /dev/null + echo "Success" + fi + + if webinterface-onboot is-hack-applied > /dev/null; then + echo + echo "Reverting binary modification" + if webinterface-onboot has-backup > /dev/null; then + webinterface-onboot revert-hack --backup -y > /dev/null + else + webinterface-onboot revert-hack --reverse -y > /dev/null + fi + echo "Success" + fi +} + +preremove() { + disable-unit "$pkgname.service" + _restore +} + +preupgrade() { + _restore +} + +postremove() { + systemctl daemon-reload +} diff --git a/package/webinterface-onboot/webinterface-onboot-toltec.service b/package/webinterface-onboot/webinterface-onboot-toltec.service new file mode 100644 index 000000000..563cba5bd --- /dev/null +++ b/package/webinterface-onboot/webinterface-onboot-toltec.service @@ -0,0 +1,13 @@ +[Unit] +Description=Enable the web interface on boot +StartLimitIntervalSec=600 +StartLimitBurst=4 +After=home.mount sys-subsystem-net-devices-usb0.device + +[Service] +Environment=HOME=/home/root +Type=oneshot +ExecStart=/opt/bin/webinterface-onboot local-exec + +[Install] +WantedBy=multi-user.target diff --git a/package/webinterface-upload-button/package b/package/webinterface-upload-button/package new file mode 100644 index 000000000..bcd8d982b --- /dev/null +++ b/package/webinterface-upload-button/package @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=("webinterface-upload-button") +pkgdesc="A simple upload button for the web interface" +url="https://github.com/rM-self-serve/webinterface-upload-button" +pkgver=1.1.1-3 +timestamp=2023-12-16T15:35:49Z +section="utils" +maintainer="rM-self-serve <122753594+rM-self-serve@users.noreply.github.com>" +license=MIT + +source=( + "$url"/archive/1d28b2d91c0179059017696ae5a33aa49e1e7c7d.zip +) +sha256sums=( + f967cad7607da6458cb0e307b662db66026747922f98ad19f7e2265b9cab1f47 +) + +package() { + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir/$pkgname" + install -D -m 644 -t "$pkgdir"/usr/share/remarkable/webui/ "$srcdir/$pkgname.js" + + mkdir -p "$pkgdir"/opt/share/toltec/reenable.d + touch "$pkgdir"/opt/share/toltec/reenable.d/"$pkgname" +} + +configure() { + echo + echo "Applying webinterface-upload-button" + webinterface-upload-button apply -y > /dev/null + echo "Success" + echo +} + +_restore() { + echo + echo "Reverting webinterface-upload-button" + webinterface-upload-button revert -y > /dev/null + echo "Success" + echo +} + +preremove() { + _restore +} + +preupgrade() { + _restore +} diff --git a/package/webinterface-wifi/package b/package/webinterface-wifi/package new file mode 100644 index 000000000..655beab42 --- /dev/null +++ b/package/webinterface-wifi/package @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# Copyright (c) 2020 The Toltec Contributors +# SPDX-License-Identifier: MIT + +_pkgname="webinterface-wifi" +pkgnames=("$_pkgname") +pkgdesc="View the web interface if running, over wifi" +url="https://github.com/rM-self-serve/$_pkgname" +pkgver=2.0.0-2 +timestamp=2023-11-26T00:02:11Z +section="utils" +maintainer="rM-self-serve <122753594+rM-self-serve@users.noreply.github.com>" +license=MIT +image=rust:v3.1 + +_pkgalias="webint-wifi" +_configdir="/home/root/.config/$_pkgname" +_etcdir="/opt/etc/$_pkgname" + +source=( + "$url/archive/4513d5cbc5e323f2959987f3bc9e300b0aaddb19.zip" + "$_pkgname-toltec.service" +) + +sha256sums=( + a23c05faf4ccaafea9222255399c8c3a121079dd07970c8768b4315606eb7834 + SKIP +) + +build() { + WIW_DATADIR="/opt/etc" cargo build --release +} + +package() { + install -D -m 755 -t "$pkgdir/opt/bin" \ + "$srcdir/target/armv7-unknown-linux-gnueabihf/release/$_pkgname" + ln -s "/opt/bin/$_pkgname" "$pkgdir/opt/bin/$_pkgalias" + + install -D -m 644 "$srcdir/$_pkgname-toltec.service" \ + "$pkgdir/lib/systemd/system/$_pkgname.service" + + install -D -m 644 -t "$pkgdir""$_etcdir/docs" \ + "$srcdir/README.MD" "$srcdir"/config/*.toml + install -D -m 644 -t "$pkgdir""$_etcdir/docs/config_examples" \ + "$srcdir"/config/examples/*.toml + install -D -m 644 -t "$pkgdir""$_etcdir"/assets \ + "$srcdir/assets/favicon.ico" + install -d "$pkgdir""$_etcdir/ssl" \ + "$pkgdir""$_etcdir/auth" \ + "$pkgdir""$_configdir" +} + +configure() { + [[ -f "$_configdir/config.toml" ]] \ + || cp "$_etcdir/docs/config.default.toml" \ + "$_configdir/config.toml" + + systemctl daemon-reload + + if is-active "$pkgname"; then + echo "Restarting $pkgname" + systemctl restart "$pkgname" + fi + + echo "" + echo "Run '\$ $pkgname' for usage information and a link to" + echo "the documentation. You can also find the documentation locally" + echo "at /opt/etc/webinterface-wifi/docs/" + echo "" + echo "Run the following command to use $pkgname" + how-to-enable "$pkgname.service" +} + +preremove() { + disable-unit "$pkgname.service" +} + +postremove() { + rmdir "$_etcdir"/*/* "$_etcdir"/* "$_etcdir" 2> /dev/null || true + systemctl daemon-reload +} diff --git a/package/webinterface-wifi/webinterface-wifi-toltec.service b/package/webinterface-wifi/webinterface-wifi-toltec.service new file mode 100644 index 000000000..b3efab933 --- /dev/null +++ b/package/webinterface-wifi/webinterface-wifi-toltec.service @@ -0,0 +1,15 @@ +[Unit] +Description=View the web interface if running, over wifi +StartLimitIntervalSec=600 +StartLimitBurst=4 +After=home.mount + +[Service] +Type=simple +Environment=HOME=/home/root +Environment=WEBINT_WIFI_RUN_ENV=DAEMON +ExecStart=/opt/bin/webinterface-wifi local-exec +Restart=on-failure + +[Install] +WantedBy=multi-user.target diff --git a/package/whiteboard-hypercard/package b/package/whiteboard-hypercard/package index 36dc05edc..9cb9a468b 100644 --- a/package/whiteboard-hypercard/package +++ b/package/whiteboard-hypercard/package @@ -1,35 +1,37 @@ #!/usr/bin/env bash -# Copyright (c) 2021 The Toltec Contributors +# Copyright (c) 2024 The Toltec Contributors # SPDX-License-Identifier: MIT pkgnames=(whiteboard-hypercard) pkgdesc="Real-time collaboration, drawing or whiteboarding" url=https://github.com/fenollp/reMarkable-tools -pkgver=0.3.4-1 -timestamp=2021-10-25T15:45Z +pkgver=0.5.0-1 +timestamp=2024-09-12T19:00:22Z section="drawing" maintainer="Pierre Fenoll " -license=Apache-2.0 +license=CC-BY-NC-ND installdepends=(display) flags=(patch_rm2fb) -image=rust:v2.2 +image=rust:v3.2 source=( - https://github.com/fenollp/reMarkable-tools/archive/v0.3.4.zip + https://github.com/fenollp/reMarkable-tools/archive/refs/tags/v0.5.0.zip whiteboard-hypercard.draft ) sha256sums=( - b343e1b4af9e0bf247ff2fab8331648ddd89941fb5c0ea9a45417d3bb4b20193 + 668f0b1dbc6027f6f6b8ab69f65c844a718f38115f79b9ce79e060a1cef3edfb SKIP ) build() { - cd marauder + pushd marauder rustup component add rustfmt - cargo build --release --bin whiteboard --locked + cargo fetch + cargo build --release --package=marauder --bin=whiteboard --locked --frozen --offline --target=armv7-unknown-linux-gnueabihf + popd } package() { - install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/marauder/target/armv7-unknown-linux-gnueabihf/release/whiteboard + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/target/armv7-unknown-linux-gnueabihf/release/whiteboard install -D -m 644 -t "$pkgdir"/opt/etc/draft "$srcdir"/whiteboard-hypercard.draft } diff --git a/package/whiteboard-hypercard/whiteboard-hypercard.draft b/package/whiteboard-hypercard/whiteboard-hypercard.draft index 19800df55..11c499816 100644 --- a/package/whiteboard-hypercard/whiteboard-hypercard.draft +++ b/package/whiteboard-hypercard/whiteboard-hypercard.draft @@ -1,4 +1,4 @@ -# Copyright (c) 2020 The Toltec Contributors +# Copyright (c) 2024 The Toltec Contributors # SPDX-License-Identifier: MIT name=whiteboard diff --git a/package/wikipedia/package b/package/wikipedia/package index a7c44adf6..a03eb4d22 100644 --- a/package/wikipedia/package +++ b/package/wikipedia/package @@ -5,7 +5,7 @@ pkgnames=(wikipedia) pkgdesc="The free encyclopedia" url=https://github.com/dps/remarkable-wikipedia -pkgver=0.1.0-3 +pkgver=0.1.0-4 timestamp=2021-03-11T04:50Z section="readers" maintainer="David Singleton " diff --git a/package/wireguard/package b/package/wireguard/package index d01ce5f3a..80c511938 100755 --- a/package/wireguard/package +++ b/package/wireguard/package @@ -1,54 +1,40 @@ #!/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-3 -_wireguardtoolsver=1.0.20210223 +pkgver=1.0.20220627-1 timestamp=2021-02-19T14:08Z section=kernel maintainer="Jonah Weissman " license=GPL-2.0-only -makedepends=(build:bc build:lzop build:git) +makedepends=(build:bc build:lzop build:git build:flex build:bison build:libssl-dev) flags=(nostrip) +installdepends=(wireguard-tools) _kernelrepo=https://github.com/remarkable/linux _kernelrevs=( - 1774e2a6a091fdc081324e966d3db0aa9df75c0b - d4e7e07a390f8b2544ca09d69142d18114149004 + bb6be69d6f71fced2fc63c61372bf96e5f7da565 + bb6be69d6f71fced2fc63c61372bf96e5f7da565 ) _defconfigs=( arch/arm/configs/zero-gravitas_defconfig arch/arm/configs/zero-sugar_defconfig ) -image=base:v2.1 +image=base:v3.2 source=( "https://git.zx2c4.com/wireguard-linux-compat/snapshot/wireguard-linux-compat-${pkgver%-*}.tar.xz" - "https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-${_wireguardtoolsver}.tar.xz" fix-multiple-yylloc-definitions.patch ) -noextract=("wireguard-tools-${_wireguardtoolsver}.tar.xz") sha256sums=( - 99d35296b8d847a0d4db97a4dda96b464311a6354e75fe0bef6e7c4578690f00 - 1f72da217044622d79e0bab57779e136a3df795e3761a3fc1dc0941a9055877c + 362d412693c8fe82de00283435818d5c5def7f15e2433a07a9fe99d0518f63c0 SKIP ) -prepare() { - bsdtar -x \ - --directory "$srcdir" \ - --file "$srcdir/wireguard-tools-${_wireguardtoolsver}.tar.xz" - mv "$srcdir/wireguard-tools-${_wireguardtoolsver}" "$srcdir/wireguard-tools" - # the symlink at src/wg-quick/wg needs something to point to - touch "$srcdir/wireguard-tools/src/wg" -} - build() { - make -C wireguard-tools/src PLATFORM=linux "CC=${CROSS_COMPILE}cc" - mkdir pkg git init linux for i in $(seq 0 1); do @@ -80,8 +66,6 @@ build() { } package() { - make -C "$srcdir/wireguard-tools/src" DESTDIR="$pkgdir" WITH_WGQUICK=yes \ - WITH_SYSTEMDUNITS=yes WITH_BASHCOMPLETION=no install mkdir -p "$pkgdir/lib/modules" cp -r "$srcdir/pkg"/* "$pkgdir/lib/modules" } diff --git a/package/xochitl/kill-xochitl b/package/xochitl/kill-xochitl new file mode 100644 index 000000000..f3a18c5f2 --- /dev/null +++ b/package/xochitl/kill-xochitl @@ -0,0 +1,5 @@ +#!/usr/bin/env bash +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +killall xochitl diff --git a/package/xochitl/launcherctl-xochitl b/package/xochitl/launcherctl-xochitl new file mode 100755 index 000000000..66c90364b --- /dev/null +++ b/package/xochitl/launcherctl-xochitl @@ -0,0 +1,41 @@ +#!/bin/bash +set -e +case "$1" in + is-active) + systemctl is-active --quiet xochitl.service + ;; + is-enabled) + systemctl is-enabled --quiet xochitl.service + ;; + logs) + if [ $# -eq 2 ] && [[ "$2" == "-f" ]] || [[ "$2" == "--follow" ]]; then + journalctl --follow --all --unit xochitl.service + else + journalctl --no-pager --all --unit xochitl.service + fi + ;; + start | launch) + systemctl start xochitl.service + ;; + stop | close) + systemctl stop xochitl.service + ;; + enable) + systemctl enable xochitl.service + ;; + disable) + systemctl disable xochitl.service + ;; + apps) + echo "xochitl" + ;; + running) + if "$0" is-active; then + echo "xochitl" + fi + ;; + *) + echo "Xochitl does not support this method" + exit 1 + ;; +esac diff --git a/package/xochitl/manual-sync@.service b/package/xochitl/manual-sync@.service new file mode 100644 index 000000000..386011a02 --- /dev/null +++ b/package/xochitl/manual-sync@.service @@ -0,0 +1,21 @@ +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT + +[Unit] +Description=reMarkable Document Sync without the xochitl.service dependency +After=dbus.socket +StartLimitIntervalSec=60 +StartLimitBurst=4 +Conflicts=%i.service + +[Service] +# Do NOT make this dbus, systemd will kill the service when it should be +# running otherwise. +Type=simple +BusName=no.remarkable.sync +ExecStart=/usr/bin/%i --service +Restart=on-failure +RestartForceExitStatus=SIGHUP SIGINT SIGTERM SIGPIPE + +[Install] +WantedBy=multi-user.target diff --git a/package/xochitl/package b/package/xochitl/package index 6ea840edf..ba890d642 100644 --- a/package/xochitl/package +++ b/package/xochitl/package @@ -5,8 +5,8 @@ pkgnames=(xochitl) pkgdesc="Read documents and take notes" url=https://remarkable.com -pkgver=0.0.0-13 -timestamp=2022-03-05T23:26Z +pkgver=0.0.0-21 +timestamp=2022-11-07T20:19:57Z section="readers" maintainer="Mattéo Delabre " license=MIT @@ -24,6 +24,8 @@ source=( toltec-after-launcher.conf toltec-wrapper.conf env-readme + manual-sync@.service + launcherctl-xochitl ) sha256sums=( SKIP @@ -33,6 +35,8 @@ sha256sums=( SKIP SKIP SKIP + SKIP + SKIP ) package() { @@ -49,6 +53,7 @@ package() { install -D -m 644 -t "$pkgdir"/opt/etc/draft "$srcdir"/xochitl.draft install -D -m 644 -t "$pkgdir"/opt/etc/draft/icons "$srcdir"/xochitl.png install -D -m 644 -t "$pkgdir"/opt/usr/share/applications "$srcdir"/xochitl.oxide + install -D -T -m 755 "$srcdir"/launcherctl-xochitl "$pkgdir"/opt/share/launcherctl/"$pkgname" install -D -m 644 -t "$pkgdir"/etc/systemd/system/xochitl.service.d \ "$srcdir"/toltec-wrapper.conf @@ -56,11 +61,33 @@ package() { "$srcdir"/toltec-after-launcher.conf install -D -m 644 -t "$pkgdir"/etc/systemd/system/remarkable-reboot.service.d \ "$srcdir"/toltec-after-launcher.conf + install -D -m 644 -t "$pkgdir"/etc/systemd/system \ + "$srcdir"/manual-sync@.service } configure() { systemctl daemon-reload + # sync.service and rm-sync.service interfere with launchers + # we use manual-sync@.service instead + if [ -f /usr/bin/sync ] && ! is-masked sync.service; then + systemctl mask sync.service + fi + + if [ -f /usr/bin/rm-sync ] && ! is-masked rm-sync.service; then + systemctl mask rm-sync.service + fi + + # manual-sync.service has been changed to manual-sync@.service + # Make sure to disable and stop the old version + disable-unit manual-sync.service + + if [ -f /usr/bin/rm-sync ] && ! is-active manual-sync@rm-sync.service; then + systemctl enable --now manual-sync@rm-sync.service + elif [ -f /usr/bin/sync ] && ! is-active manual-sync@sync.service; then + systemctl enable --now manual-sync@sync.service + fi + if is-enabled xochitl.service && ! is-enabled launcher.service; then # This package changes xochitl.service to alias it to launcher.service # when enabled. If xochitl was previously enabled, force the creation @@ -69,9 +96,21 @@ configure() { fi } +preremove() { + disable-unit manual-sync@rm-sync.service + disable-unit manual-sync@sync.service +} + postremove() { systemctl daemon-reload + if [ -f /usr/bin/sync ] && is-masked sync.service; then + systemctl unmask sync.service + fi + if [ -f /usr/bin/rm-sync ] && is-masked rm-sync.service; then + systemctl unmask rm-sync.service + fi + if is-enabled xochitl.service && is-enabled launcher.service; then # If xochitl is currently the active launcher, make sure the # launcher.service alias is removed diff --git a/package/xochitl/xochitl b/package/xochitl/xochitl index de6256f0d..4a2eb95f2 100644 --- a/package/xochitl/xochitl +++ b/package/xochitl/xochitl @@ -9,4 +9,22 @@ for file in /opt/etc/xochitl.env.d/*.env; do source "$file" fi done -exec /usr/bin/xochitl "$@" + +# If for some reason, sync.service is no longer masked, re-mask it +# The package install should have handled this, but something may +# have changed it. +if [[ "x$(systemctl is-enabled sync.service)" != "xmasked" ]]; then + systemctl mask sync.service +fi + +if [[ "x$(systemctl is-enabled rm-sync.service)" != "xmasked" ]]; then + systemctl mask rm-sync.service +fi + +if [ -f /usr/bin/rm-sync ] && ! is-active manual-sync@rm-sync.service; then + systemctl enable --now manual-sync@rm-sync.service +elif [ -f /usr/bin/sync ] && ! is-active manual-sync@sync.service; then + systemctl enable --now manual-sync@sync.service +fi + +exec -a /usr/bin/xochitl /usr/bin/xochitl "$@" diff --git a/package/xochitl/xochitl.oxide b/package/xochitl/xochitl.oxide index 533828a2d..1ebe793b9 100644 --- a/package/xochitl/xochitl.oxide +++ b/package/xochitl/xochitl.oxide @@ -3,27 +3,5 @@ "description": "Read documents and take notes", "bin": "/opt/bin/xochitl", "icon": "/opt/etc/draft/icons/xochitl.png", - "flags": ["nosplash", "chroot"], - "permissions": ["power"], - "directories": [ - "/dev/shm", - "/etc", - "/home/root", - "/opt/etc", - "/run/dbus", - "/run/systemd/resolve", - "/run/udev", - "/tmp/runtime-root", - "/usr/share", - "/usr/share/remarkable/templates", - "/var/cache/fontconfig", - "/var/lib/dbus", - ], - "environment": { - "QMLSCENE_DEVICE": "epaper", - "QT_QPA_PLATFORM": "epaper", - "QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS": "rotate=180", - "HOME": "/home/root", - "XDG_RUNTIME_DIR": "/tmp/runtime-root" - } + "flags": ["nosplash"] } diff --git a/package/yaft/package b/package/yaft/package index 4ba55525f..5a635896a 100644 --- a/package/yaft/package +++ b/package/yaft/package @@ -1,30 +1,49 @@ #!/usr/bin/env bash -# Copyright (c) 2020 The Toltec Contributors +# Copyright (c) 2022 The Toltec Contributors # SPDX-License-Identifier: MIT pkgnames=(yaft) pkgdesc="Yet another framebuffer terminal" url=https://github.com/timower/rM2-stuff/tree/master/apps/yaft -pkgver=0.0.4-4 -timestamp=2021-04-30T10:42Z +_tag=0.1.2 +pkgver=${_tag}-1 +timestamp=2024-05-29T17:05:56Z maintainer="Mattéo Delabre " license=GPL-3.0 section="admin" -image=base:v2.1 -installdepends=(display) +image=base:v3.1 +installdepends=(display terminfo) +flags=(nostrip) -source=(https://github.com/timower/rM2-stuff/archive/refs/tags/v0.0.4.tar.gz) -sha256sums=(dee471ac19ea43ba741f826c9a0a17d7a01bda6472043d400fbcab6fad1931fe) +source=() +sha256sums=() + +prepare() { + cd "$srcdir" + mkdir -p yaft + cd yaft + git init + git lfs install + git remote add origin https://github.com/timower/rM2-stuff.git + git fetch --depth 1 origin tag v${_tag} --no-tags + git checkout v${_tag} + git lfs fetch + git lfs checkout +} build() { - mkdir build + cd "$srcdir" mkdir install - cd build - cmake -DCMAKE_TOOLCHAIN_FILE="/usr/share/cmake/$CHOST.cmake" \ - -DCMAKE_INSTALL_PREFIX="../install" -DCMAKE_BUILD_TYPE=Release .. - cd apps/yaft - make - make install + cd yaft + cmake --preset release-toltec + cmake \ + --build build/release-toltec \ + --target yaft + cmake \ + --install build/release-toltec \ + --prefix ../install \ + --component yaft \ + --strip } package() { diff --git a/package/zerotier-one/package b/package/zerotier-one/package new file mode 100644 index 000000000..5e4827fb4 --- /dev/null +++ b/package/zerotier-one/package @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +# Copyright (c) 2023 The Toltec Contributors +# SPDX-License-Identifier: MIT + +pkgnames=(zerotier zerotier-one zerotier-one-doc zerotier-selftest) +url=https://github.com/zerotier/ZeroTierOne +_upver=1.14.1 +pkgver=${_upver}-1 +timestamp=2023-03-23T17:39:31Z +maintainer="Eeems " +license=BUSL-1.1 +section="utils" +image=base:v3.0 + +source=("https://github.com/zerotier/ZeroTierOne/archive/refs/tags/${_upver}.zip") +sha256sums=(fcf30ce797dbca757f3e882e004a3f953ebe12ae13f03d804b3fb184ee3c9714) + +build() { + sed -i \ + -e 's|/usr/sbin|/opt/bin|' \ + -e 's|/usr/share|/opt/share|' \ + -e 's|/var/lib|/opt/var/lib|' \ + make-linux.mk \ + debian/zerotier-one.service + sed -i \ + -e 's|/var/lib/zerotier-one|/opt/var/lib/zerotier-one|' \ + osdep/OSUtils.cpp + sed -i \ + -e 's|/var/lib/zerotier|/opt/var/lib/zerotier|' \ + doc/zerotier-cli.1 \ + doc/zerotier-cli.1.md \ + doc/zerotier-one.8 \ + doc/zerotier-one.8.md + # Disable SSO as the rust build is broken in rust:v3.0 due to issues with dependencies + export ZT_SSO_SUPPORTED=0 + export ZT_EMBEDDED=1 + export CC=arm-linux-gnueabihf-gcc + export CXX=arm-linux-gnueabihf-g++ + export AR=arm-linux-gnueabihf-ar + export STRIP=arm-linux-gnueabihf-strip + make + make selftest +} + +zerotier() { + pkgdesc="A Smart Ethernet Switch for Earth" + installdepends=(zerotier-one) + # Using 1: to make sure our version always overrides the entware version + pkgver="1:${pkgver}" + package() { + # This is just a wrapper package + true + } +} + +zerotier-one() { + pkgdesc="A Smart Ethernet Switch for Earth" + package() { + cd "$srcdir" + DESTDIR="$pkgdir" make install + rm -r "$pkgdir"/opt/share + install -D -m0644 debian/zerotier-one.service "$pkgdir"/etc/systemd/system/zerotier-one.service + } + configure() { + if ! is-enabled zerotier-one.service; then + how-to-enable zerotier-one.service + fi + if is-active zerotier-one.service; then + systemctl restart zerotier-one.service + fi + } + preremove() { + disable-unit zerotier-one.service + } +} + +zerotier-one-doc() { + installdepends=(man-db) + pkgdesc="Man files for zerotier-one" + package() { + cd "$srcdir" + DESTDIR="$pkgdir" make install + rm -r "$pkgdir"/opt/bin + rm -r "$pkgdir"/opt/var + } +} + +zerotier-selftest() { + pkgdesc="Unit test zerotier to ensure that it works as expected on the system" + package() { + install -D -m 755 -t "$pkgdir"/opt/bin "$srcdir"/zerotier-selftest + } +} diff --git a/package/zoneinfo-utils/package b/package/zoneinfo-utils/package index f31bd7eb8..8caab1ce8 100644 --- a/package/zoneinfo-utils/package +++ b/package/zoneinfo-utils/package @@ -7,23 +7,24 @@ pkgnames=(zoneinfo-utils) pkgdesc="Utilities for interacting with zoneinfo files" url=https://www.iana.org/time-zones -_tzver=2021a -pkgver="$_tzver"-2 -timestamp=2020-05-04T06:16Z +_tzver=2023c +pkgver="$_tzver"-1 +timestamp=2023-03-28T00:00Z section=utils maintainer="Eeems " license="custom: public domain" installdepends=(zoneinfo-core) makedepends=(build:gawk) +flags=(nostrip) -image=base:v2.1 +image=base:v3.0 source=( "https://www.iana.org/time-zones/repository/releases/tzcode${_tzver}.tar.gz" "https://www.iana.org/time-zones/repository/releases/tzdata${_tzver}.tar.gz" ) sha256sums=( - eb46bfa124b5b6bd13d61a609bfde8351bd192894708d33aa06e5c1e255802d0 - 39e7d2ba08c68cbaefc8de3227aab0dec2521be8042cf56855f7dc3a9fb14e08 + 46d17f2bb19ad73290f03a203006152e0fa0d7b11e5b71467c4a823811b214e7 + 3f510b5d1b4ae9bb38e485aa302a776b317fb3637bdb6404c4adf7b6cadd965c ) prepare() { @@ -35,17 +36,20 @@ build() { pushd .x86 > /dev/null shopt -s extglob - cp -r ../* . - make VERSION="$_tzver" + ln -s ../* . + make VERSION="$_tzver" zic + mv zic ../zic.x86 popd > /dev/null - + rm -r .x86 make VERSION="$_tzver" CC=arm-linux-gnueabihf-cc + "${CROSS_COMPILE}strip" --strip-all zic zdump } package() { pushd "${srcdir}" > /dev/null - local zic=.x86/zic + + local zic=./zic.x86 # install tzcode stuff make DESTDIR="${pkgdir}" zic="$zic" install # install license diff --git a/package/zshelf/package b/package/zshelf/package index bd1491464..0562ac3e3 100644 --- a/package/zshelf/package +++ b/package/zshelf/package @@ -5,7 +5,7 @@ pkgnames=(zshelf) pkgdesc="Z-Library browser and downloader" url=https://github.com/khanhas/zshelf -pkgver=0.3.1-3 +pkgver=0.3.1-4 section=utils timestamp=2021-02-20T01:45Z maintainer="khanhas " diff --git a/requirements.txt b/requirements.txt index b18273a33..7aadcde47 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,28 +1,19 @@ -appdirs==1.4.4 -astroid==2.4.2 -black==20.8b1 -certifi==2020.12.5 -chardet==4.0.0 -click==7.1.2 -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.8.1 -pyelftools==0.27 -pylint==2.6.0 -python-dateutil==2.8.1 -regex==2020.11.13 -requests==2.25.1 -six==1.15.0 +black==24.8.0 +certifi==2023.7.22 +idna==3.4 +isort==5.12.0 +Jinja2==3.1.2 +lazy-object-proxy==1.9.0 +mypy-extensions==1.0.0 +mypy==1.7.1 +pylint==3.0.3 +six==1.16.0 +toltecmk==0.3.3 toml==0.10.2 -typed-ast==1.4.2 -typing-extensions==3.7.4.3 -urllib3==1.26.2 -websocket-client==0.57.0 -wrapt==1.12.1 +types-python-dateutil==2.8.19.14 +types-requests==2.31.0.2 +typing-extensions==4.7.1 +websocket-client==1.6.1 + +# Pinned due to https://github.com/docker/docker-py/issues/3256 +requests==2.31.0 diff --git a/scripts/bootstrap/bootstrap b/scripts/bootstrap/bootstrap index 6a278c10d..15da30019 100755 --- a/scripts/bootstrap/bootstrap +++ b/scripts/bootstrap/bootstrap @@ -15,6 +15,11 @@ # # +if [ -z "$BASH" ] || [[ "$(ps | awk '$1=='$$' { n=split($5,a,"/"); print a[n] }')" != "bash" ]]; then + echo "bootstrap must be run with bash" + exit 1 +fi + set -eEuo pipefail # Path to the temporary local wget and Opkg binaries @@ -61,17 +66,39 @@ exists-non-empty() { [[ -d $1 ]] && files="$(ls -A -- "$1")" && [[ -n $files ]] } +already-installed-message() { + log "Toltec is already installed or partially installed" + log "To re-enable Toltec after a system upgrade, run 'toltecctl reenable'" + log "To reinstall Toltec, run 'toltecctl uninstall' first" +} + # Check whether a Toltec install already exists or if conflicting files # remain from previous installs check-installed() { - if [[ ! -f $toltecctl_path ]]; then - return + local unit_path + local unit + # This should mimic get-bind-mount-path as close as possible to ensure it's always + # the path that an install or reenable would generate. + unit_path="/lib/systemd/system/$(systemd-escape --path /opt).mount" + unit="$(basename "$unit_path")" + if [[ -f $unit_path ]] && systemctl --quiet is-active "$unit" 2> /dev/null; then + log ERROR "opt.mount is currently active" + already-installed-message + exit 1 fi - - if exists-non-empty /opt || exists-non-empty /home/root/.entware; then - log "Toltec is already installed or partially installed" - log "To re-enable Toltec after a system upgrade, run 'toltecctl reenable'" - log "To reinstall Toltec, run 'toltecctl uninstall' first" + if [[ "$(grep ' /opt ' /proc/mounts)" != "" ]]; then + log ERROR "/opt is currently mounted" + already-installed-message + exit 1 + fi + if exists-non-empty /opt; then + log ERROR "/opt exists and is not empty" + already-installed-message + exit 1 + fi + if exists-non-empty /home/root/.entware; then + log ERROR "/home/root/.entware exists and is not empty" + already-installed-message exit 1 fi } @@ -79,8 +106,8 @@ check-installed() { # Install a local wget binary which supports TLS (the original one # installed on the reMarkable does not) in the PATH wget-bootstrap() { - local wget_remote=http://toltec-dev.org/thirdparty/bin/wget-v1.21.1 - local wget_checksum=8798fcdabbe560722a02f95b30385926e4452e2c98c15c2c217583eaa0db30fc + local wget_remote=http://toltec-dev.org/thirdparty/bin/wget-v1.21.1-1 + local wget_checksum=c258140f059d16d24503c62c1fdf747ca843fe4ba8fcd464a6e6bda8c3bbb6b5 if [[ ! -x $wget_path ]]; then if [[ -e $wget_path ]]; then @@ -89,7 +116,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")" @@ -165,8 +192,7 @@ main() { local pkg_filename="/tmp/$pkg_basename" wget --no-verbose "$toltec_remote/$pkg_basename" -O "$pkg_filename" - opkg install --add-arch rmall:200 --offline-root / --force-depends \ - "$pkg_filename" > /dev/null 2>&1 + tar -zxvOf "$pkg_filename" ./data.tar.gz | tar -zxf - -C / rm "$pkg_filename" # shellcheck source=../../package/toltec-bootstrap/toltecctl @@ -175,6 +201,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 @@ -225,23 +257,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/toltec/__init__.py b/scripts/build/__init__.py similarity index 100% rename from scripts/toltec/__init__.py rename to scripts/build/__init__.py diff --git a/scripts/toltec/graphlib.py b/scripts/build/graphlib.py similarity index 99% rename from scripts/toltec/graphlib.py rename to scripts/build/graphlib.py index 2a303928c..12c12446d 100644 --- a/scripts/toltec/graphlib.py +++ b/scripts/build/graphlib.py @@ -225,6 +225,7 @@ def _find_cycle(self) -> Optional[List[_T]]: seen = set() node2stacki: MutableMapping[_T, int] = {} + # pylint: disable-next=consider-using-dict-items for node in n2i: if node in seen: continue diff --git a/scripts/toltec/paths.py b/scripts/build/paths.py similarity index 100% rename from scripts/toltec/paths.py rename to scripts/build/paths.py diff --git a/scripts/toltec/repo.py b/scripts/build/repo.py similarity index 66% rename from scripts/toltec/repo.py rename to scripts/build/repo.py index c99fe3988..d8dac134d 100644 --- a/scripts/toltec/repo.py +++ b/scripts/build/repo.py @@ -3,20 +3,36 @@ """ Build the package repository. """ - -from datetime import datetime -import gzip -from enum import Enum, auto import logging import os -import textwrap -from typing import Dict, Iterable, List, Optional, Set +import pathlib +import shutil + +from datetime import datetime +from enum import auto +from enum import Enum +from typing import ( + Dict, + Iterable, + List, + Optional, +) + import requests +from jinja2 import ( + Environment, + FileSystemLoader, +) +from toltec import parse_recipe # type: ignore +from toltec.recipe import ( + Package, # type: ignore + Recipe, # type: ignore +) +from toltec.util import HTTP_DATE_FORMAT # type: ignore +from toltec.version import DependencyKind # type: ignore + from .graphlib import TopologicalSorter -from .recipe import GenericRecipe, Package -from .util import file_sha256, group_by, HTTP_DATE_FORMAT -from .version import DependencyKind -from . import templating +from .util import group_by logger = logging.getLogger(__name__) @@ -24,6 +40,8 @@ class PackageStatus(Enum): """Possible existence statuses of a built package.""" + # pylint: disable=invalid-name + # The package already existed in the local filesystem before the build AlreadyExists = auto() @@ -33,6 +51,8 @@ class PackageStatus(Enum): # The package is missing both from the local filesystem and the remote repo Missing = auto() + # pylint: enable=invalid-name + GroupedPackages = Dict[PackageStatus, Dict[str, Dict[str, List[Package]]]] @@ -52,8 +72,13 @@ def __init__(self, recipe_dir: str, repo_dir: str) -> None: self.generic_recipes = {} for name in os.listdir(self.recipe_dir): - if name[0] != ".": - self.generic_recipes[name] = GenericRecipe.from_file( + path = pathlib.Path(self.recipe_dir) / name + if ( + name[0] != "." + and os.path.isdir(path) + and os.path.exists(path / "package") + ): + self.generic_recipes[name] = parse_recipe( os.path.join(self.recipe_dir, name) ) @@ -79,7 +104,7 @@ def fetch_packages(self, remote: Optional[str]) -> GroupedPackages: fetched_generic = {} missing_generic = {} - for arch, recipe in generic_recipe.recipes.items(): + for arch, recipe in generic_recipe.items(): fetched_arch = [] missing_arch = [] @@ -92,7 +117,7 @@ def fetch_packages(self, remote: Optional[str]) -> GroupedPackages: logger.info( "Package %s (%s) is missing", package.pkgid(), - recipe.name, + os.path.basename(recipe.path), ) missing_arch.append(package) @@ -110,9 +135,7 @@ def fetch_packages(self, remote: Optional[str]) -> GroupedPackages: return results - def fetch_package( - self, package: Package, remote: Optional[str] - ) -> PackageStatus: + def fetch_package(self, package: Package, remote: Optional[str]) -> PackageStatus: """ Check if a package exists locally and fetch it otherwise. @@ -132,7 +155,7 @@ def fetch_package( remote_path = os.path.join(remote, filename) - req = requests.get(remote_path) + req = requests.get(remote_path, timeout=5) if req.status_code != 200: return PackageStatus.Missing @@ -155,8 +178,8 @@ def fetch_package( def order_dependencies( self, - generic_recipes: List[GenericRecipe], - ) -> Iterable[GenericRecipe]: + generic_recipes: List[Dict[str, Recipe]], + ) -> Iterable[dict[str, Recipe]]: """ Order a list of recipes so that all recipes that a recipe needs come before that recipe in the list. @@ -172,70 +195,24 @@ def order_dependencies( parent_recipes = {} for generic_recipe in generic_recipes: - for recipe in generic_recipe.recipes.values(): - for package in recipe.packages.values(): - parent_recipes[package.name] = generic_recipe.name + for recipe in generic_recipe.values(): + for package in recipe.packages.values(): # type: ignore + parent_recipes[package.name] = os.path.basename(recipe.path) for generic_recipe in generic_recipes: - deps = [] - - for recipe in generic_recipe.recipes.values(): - for dep in recipe.makedepends: + for recipe in generic_recipe.values(): + deps = [] + for dep in recipe.makedepends: # type: ignore if ( - dep.kind == DependencyKind.Host + dep.kind == DependencyKind.HOST and dep.package in parent_recipes ): deps.append(parent_recipes[dep.package]) - toposort.add(generic_recipe.name, *deps) + toposort.add(os.path.basename(recipe.path), *deps) return [self.generic_recipes[name] for name in toposort.static_order()] - def make_index(self) -> None: - """Generate index files for all the packages in the repo.""" - logger.info("Generating package indices") - - # Gather all available architectures - archs: Set[str] = set() - for generic_recipe in self.generic_recipes.values(): - archs.update(generic_recipe.recipes.keys()) - - # Generate one index per architecture - for arch in archs: - arch_dir = os.path.join(self.repo_dir, arch) - os.makedirs(arch_dir, exist_ok=True) - - index_path = os.path.join(arch_dir, "Packages") - index_gzip_path = os.path.join(arch_dir, "Packages.gz") - - with open(index_path, "w") as index_file: - with gzip.open(index_gzip_path, "wt") as index_gzip_file: - for generic_recipe in self.generic_recipes.values(): - if not arch in generic_recipe.recipes: - continue - - recipe = generic_recipe.recipes[arch] - - for package in recipe.packages.values(): - filename = package.filename() - local_path = os.path.join(self.repo_dir, filename) - - if not os.path.isfile(local_path): - continue - - control = package.control_fields() - control += textwrap.dedent( - f"""\ - Filename: {os.path.basename(filename)} - SHA256sum: {file_sha256(local_path)} - Size: {os.path.getsize(local_path)} - - """ - ) - - index_file.write(control) - index_gzip_file.write(control) - def make_listing(self) -> None: """Generate the static web listing for packages in the repo.""" logger.info("Generating web listing") @@ -243,7 +220,7 @@ def make_listing(self) -> None: packages = [ package for generic_recipe in self.generic_recipes.values() - for recipe in generic_recipe.recipes.values() + for recipe in generic_recipe.values() for package in recipe.packages.values() ] @@ -256,7 +233,20 @@ def make_listing(self) -> None: } listing_path = os.path.join(self.repo_dir, "index.html") - template = templating.env.get_template("listing.html") - + template = Environment( + loader=FileSystemLoader( + pathlib.Path(__file__).parent.resolve() / ".." / "templates" + ), + autoescape=True, + ).get_template("listing.html") + + # 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) diff --git a/scripts/build/util.py b/scripts/build/util.py new file mode 100644 index 000000000..36c0721fe --- /dev/null +++ b/scripts/build/util.py @@ -0,0 +1,44 @@ +# Copyright (c) 2021 The Toltec Contributors +# SPDX-License-Identifier: MIT +"""Collection of useful functions.""" + +import itertools +from typing import ( + Any, + Callable, + Dict, + List, + Protocol, + Sequence, + TypeVar, +) + + +# See +class SupportsLessThan(Protocol): # pylint:disable=too-few-public-methods + """Types that support the less-than operator.""" + + def __lt__(self, other: Any) -> bool: + ... + + +Key = TypeVar("Key", bound=SupportsLessThan) +Value = TypeVar("Value") + + +def group_by( + in_seq: Sequence[Value], key_fn: Callable[[Value], Key] +) -> Dict[Key, List[Value]]: + """ + Group elements of a list. + + :param in_seq: list of elements to group + :param key_fn: mapping of each element onto a group + :returns: dictionary of groups + """ + return dict( + (key, list(group)) + for key, group in itertools.groupby( + sorted(in_seq, key=key_fn), key=key_fn + ) + ) diff --git a/scripts/install-lib b/scripts/install-lib deleted file mode 100644 index 5096106cb..000000000 --- a/scripts/install-lib +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2020 The Toltec Contributors -# SPDX-License-Identifier: MIT - -# -# install-lib -# -# Common functions used by the install scripts -# - -# Check whether a systemd unit exists and is in an enabled-like state -# ("enabled", "enabled-runtime", "alias", "static", "indirect", "generated" -# or "transient") -# -# Arguments: -# -# $1 - Name of the systemd unit, e.g. "xochitl.service" or "xochitl" -# -# Exit code: -# -# 0 if the unit exists and is enabled, 1 otherwise -is-enabled() { - systemctl --quiet is-enabled "$1" 2> /dev/null -} - -# Check whether a systemd unit is in an active state -# ("running") -# -# Arguments: -# -# $1 - Name of the systemd unit, e.g. "xochitl.service" or "xochitl" -# -# Exit code: -# -# 0 if the unit exists and is enabled, 1 otherwise -is-active() { - systemctl --quiet is-active "$1" 2> /dev/null -} - -# Get a list of systemd units with which the given unit conflicts -# -# Arguments: -# -# $1 - Full name of the systemd unit, e.g. "xochitl.service" -# -# Output: -# -# List of conflicting units -get-conflicts() { - # Find enabled units that have a conflicting name - for name in $(systemctl cat "$1" | awk -F'=' '/^Alias=/{print $2}'); do - local realname - if realname="$(basename "$(readlink "/etc/systemd/system/$name")")"; then - echo "$realname" - fi - done - - # Find units that are declared as conflicting - # (systemd automatically adds a conflict with "shutdown.target" to all - # service units see systemd.service(5), section "Automatic Dependencies") - systemctl show "$1" | awk -F'=' '/^Conflicts=/{print $2}' \ - | sed 's|\bshutdown.target\b||' -} - -# Print instructions about how to enable a given systemd service and disable -# the services that conflict with it -# -# Arguments: -# -# $1 - Full name of the systemd unit, e.g. "draft.service" -# -# Output: -# -# Commands to run to achieve the desired result -how-to-enable() { - for conflict in $(get-conflicts "$1"); do - if is-enabled "$conflict"; then - echo "$ systemctl disable --now ${conflict/.service/}" - fi - done - - echo "$ systemctl enable --now ${1/.service/}" -} - -# Reload Oxide applications if tarnish is running -# -# Output: -# -# Status message -reload-oxide-apps() { - if ! is-active tarnish.service; then - return - fi - echo -n "Reloading Oxide applications: " - if ! /opt/bin/rot apps call reload 2> /dev/null; then - echo "Failed!" - else - echo "Done!" - fi -} - -# Create or update a bind mount systemd unit and enable it -# -# Arguments: -# -# $1 - Source directory -# $2 - Mount point -add-bind-mount() { - local unit_name - local unit_path - unit_name="$(systemd-escape --path "$2").mount" - unit_path="/lib/systemd/system/$unit_name" - - if [[ -e $unit_path ]]; then - echo "Bind mount configuration for '$2' already exists, updating" - else - echo "Mounting '$1' over '$2'" - fi - - cat > "$unit_path" << UNIT -[Unit] -Description=Bind mount $1 over $2 -DefaultDependencies=no -Conflicts=umount.target -Before=local-fs.target umount.target - -[Mount] -What=$1 -Where=$2 -Type=none -Options=bind - -[Install] -WantedBy=local-fs.target -UNIT - - systemctl daemon-reload - systemctl enable "$unit_name" - systemctl restart "$unit_name" -} - -# Disable and remove a bind mount systemd unit -# -# Arguments: -# -# $1 - Mount point -remove-bind-mount() { - local unit_name - local unit_path - unit_name="$(systemd-escape --path "$1").mount" - unit_path="/lib/systemd/system/$unit_name" - - if [[ ! -e $unit_path ]]; then - echo "No existing bind mount for '$1'" - return 1 - fi - - echo "Removing mount over '$1'" - systemctl disable "$unit_name" - systemctl stop "$unit_name" - rm "$unit_path" - systemctl daemon-reload -} diff --git a/scripts/package_build.py b/scripts/package_build.py index ae546a9f6..8f70f891f 100755 --- a/scripts/package_build.py +++ b/scripts/package_build.py @@ -5,13 +5,20 @@ import argparse import logging +import os import sys -from typing import Dict, List, Optional -from toltec import paths -from toltec.builder import Builder -from toltec.repo import Repo -from toltec.recipe import Package -from toltec.util import argparse_add_verbose, LOGGING_FORMAT +from typing import ( + Dict, + List, + Optional, +) +from build import paths +from build.repo import Repo +from toltec import parse_recipe # type: ignore +from toltec.builder import Builder # type: ignore +from toltec.recipe import Package # type: ignore +from toltec.repo import make_index # type: ignore +from toltec.util import argparse_add_verbose, LOGGING_FORMAT # type: ignore parser = argparse.ArgumentParser(description=__doc__) @@ -43,25 +50,24 @@ logging.basicConfig(format=LOGGING_FORMAT, level=args.verbose) repo = Repo(paths.RECIPE_DIR, paths.REPO_DIR) builder = Builder(paths.WORK_DIR, paths.REPO_DIR) - -generic_recipe = repo.generic_recipes[args.recipe_name] arch_packages: Optional[Dict[str, Optional[List[Package]]]] = None -if args.arch_name or args.packages_names: - arch_packages = {} - - for arch in generic_recipe.recipes.keys(): - if args.packages_names: - arch_packages[arch] = [ - generic_recipe.recipes[arch].packages[pkg_name] - for pkg_name in args.packages_names - ] - else: - arch_packages[arch] = None - -builder = Builder(paths.WORK_DIR, paths.REPO_DIR) +with Builder( + os.path.join(paths.WORK_DIR, args.recipe_name), paths.REPO_DIR +) as builder: + recipe_bundle = parse_recipe(f"package/{args.recipe_name}") + build_matrix: Optional[Dict[str, Optional[List[Package]]]] = None + if args.arch_name or args.packages_names: + build_matrix = {} + for arch, recipes in recipe_bundle.items(): + if args.package_name: + build_matrix[arch] = [ + recipes.packages[pkg_name] for pkg_name in args.package_name + ] + else: + build_matrix[arch] = None -if not builder.make(generic_recipe, arch_packages): - sys.exit(1) + if not builder.make(recipe_bundle, build_matrix, False): + sys.exit(1) -repo.make_index() + make_index(paths.REPO_DIR) diff --git a/scripts/repo_build.py b/scripts/repo_build.py index 4e7d8c69f..592ce204f 100755 --- a/scripts/repo_build.py +++ b/scripts/repo_build.py @@ -6,10 +6,18 @@ import argparse import logging import os -from toltec import paths -from toltec.builder import Builder -from toltec.repo import Repo, PackageStatus -from toltec.util import argparse_add_verbose, LOGGING_FORMAT +from typing import ( + Dict, + List, + Optional, +) +from build import paths +from build.repo import Repo, PackageStatus +from toltec.recipe import Package # type: ignore +from toltec import parse_recipe # type: ignore +from toltec.builder import Builder # type: ignore +from toltec.repo import make_index # type: ignore +from toltec.util import argparse_add_verbose, LOGGING_FORMAT # type: ignore parser = argparse.ArgumentParser(description=__doc__) @@ -47,9 +55,10 @@ logging.basicConfig(format=LOGGING_FORMAT, level=args.verbose) repo = Repo(paths.RECIPE_DIR, paths.REPO_DIR) -builder = Builder(paths.WORK_DIR, paths.REPO_DIR) results = repo.fetch_packages(remote) -repo.make_index() + +os.makedirs(paths.REPO_DIR, exist_ok=True) +make_index(paths.REPO_DIR) fetched = results[PackageStatus.Fetched] missing = results[PackageStatus.Missing] @@ -58,9 +67,29 @@ ) for generic_recipe in ordered_missing: - if missing[generic_recipe.name]: - builder.make(generic_recipe, missing[generic_recipe.name]) - repo.make_index() + # Will need to rework toltec_old.repo into something inline and actually easy to work + # with Currently generic_recipe is a Dict[str, Recipe] where the index is the arch. Every + # single entry will have the same path, so we can use that for the name of the generic + # recipe we are actually building. + name = os.path.basename(next(iter(generic_recipe.values())).path) + if missing[name]: + with Builder( + os.path.join(paths.WORK_DIR, name), paths.REPO_DIR + ) as builder: + recipe_bundle = parse_recipe(os.path.join(paths.RECIPE_DIR, name)) + build_matrix: Optional[Dict[str, Optional[List[Package]]]] = None + old_build_matrix = missing[name] + if old_build_matrix: + build_matrix = {} + + for arch, recipes in old_build_matrix.items(): + build_matrix[arch] = [ + recipe_bundle[arch].packages[pkg_name] + for pkg_name in recipe_bundle[arch].packages + ] + builder.make(recipe_bundle, build_matrix, False) + + make_index(paths.REPO_DIR) if args.diff: for name in fetched: @@ -70,5 +99,6 @@ local_path = os.path.join(repo.repo_dir, filename) os.remove(local_path) -repo.make_index() +make_index(paths.REPO_DIR) repo.make_listing() +repo.make_compatibility() diff --git a/scripts/toltec/templates/listing.html b/scripts/templates/listing.html similarity index 100% rename from scripts/toltec/templates/listing.html rename to scripts/templates/listing.html diff --git a/scripts/toltec/bash.py b/scripts/toltec/bash.py deleted file mode 100644 index cb194e253..000000000 --- a/scripts/toltec/bash.py +++ /dev/null @@ -1,419 +0,0 @@ -# Copyright (c) 2021 The Toltec Contributors -# SPDX-License-Identifier: MIT -"""Bridge Bash with Python.""" - -import os -import shlex -import subprocess -from typing import Dict, Generator, List, Optional, Tuple, Union -from docker.client import DockerClient - -AssociativeArray = Dict[str, str] -IndexedArray = List[Optional[str]] -LogGenerator = Generator[str, None, None] -Any = Union[str, AssociativeArray, IndexedArray] -Variables = Dict[str, Optional[Any]] -Functions = Dict[str, str] - - -class ScriptError(Exception): - """Raised when a launched Bash script exits with a non-zero code.""" - - -# Variables which are defined by default by Bash. Those variables are excluded -# from the result of `get_declarations()`. Subset of the list at: -# -default_variables = { - "BASH", - "BASHOPTS", - "BASHPID", - "BASH_ALIASES", - "BASH_ARGC", - "BASH_ARGV", - "BASH_ARGV0", - "BASH_CMDS", - "BASH_COMMAND", - "BASH_LINENO", - "BASH_SOURCE", - "BASH_SUBSHELL", - "BASH_VERSINFO", - "BASH_VERSION", - "COLUMNS", - "COMP_WORDBREAKS", - "DIRSTACK", - "EPOCHREALTIME", - "EPOCHSECONDS", - "EUID", - "FUNCNAME", - "GROUPS", - "HISTCMD", - "HISTFILE", - "HISTFILESIZE", - "HISTSIZE", - "HOSTNAME", - "HOSTTYPE", - "IFS", - "LINENO", - "LINES", - "MACHTYPE", - "MAILCHECK", - "OLDPWD", - "OPTERR", - "OPTIND", - "OSTYPE", - "PATH", - "PIPESTATUS", - "PPID", - "PS1", - "PS2", - "PS4", - "PWD", - "RANDOM", - "SECONDS", - "SHELL", - "SHELLOPTS", - "SHLVL", - "SRANDOM", - "TERM", - "UID", - "_", -} - - -def get_declarations(src: str) -> Tuple[Variables, Functions]: - """ - Extract all variables and functions defined by a Bash script. - - If a function or a variable is defined or assigned multiple times - in the script, only the final value is extracted. The script must not - output anything on the standard output stream. - - :param src: source string of the considered Bash string - :returns: a tuple containing the declared variables and functions - """ - src += """ -declare -f -declare -p -""" - env: Dict[str, str] = { - "PATH": os.environ["PATH"], - } - - declarations_subshell = ( - subprocess.run( # pylint:disable=subprocess-run-check - ["/usr/bin/env", "bash"], - input=src.encode(), - capture_output=True, - env=env, - ) - ) - - if declarations_subshell.returncode == 2: - raise ScriptError( - f"Bash syntax error\n\ -{declarations_subshell.stderr.decode()}" - ) - - if declarations_subshell.returncode != 0: - raise ScriptError( - f"Bash error\n\ -{declarations_subshell.stderr.decode()}" - ) - - declarations = declarations_subshell.stdout.decode() - - # Parse `declare` statements and function statements - lexer = shlex.shlex(declarations, posix=True) - lexer.wordchars = lexer.wordchars + "-" - - variables = {} - functions = {} - - while True: - token = lexer.get_token() - - if token == lexer.eof: - break - - next_token = lexer.get_token() - - if token == "declare" and next_token[0] == "-": - lexer.push_token(next_token) - name, value = _parse_var(lexer) - - if name not in default_variables: - variables[name] = value - else: - assert next_token == "(" - assert lexer.get_token() == ")" - start, end = _parse_func(lexer) - functions[token] = declarations[start:end] - - return variables, functions - - -def put_variables(variables: Variables) -> str: - """ - Generate a Bash script fragment which defines a set of variables. - - :param variables: set of variables to define - :returns: generated Bash fragment - """ - result = "" - - for name, value in variables.items(): - if value is None: - result += f"declare -- {name}\n" - elif isinstance(value, str): - result += f"declare -- {name}={_generate_string(value)}\n" - elif isinstance(value, list): - result += f"declare -a {name}={_generate_indexed(value)}\n" - elif isinstance(value, dict): - result += f"declare -A {name}={_generate_assoc(value)}\n" - else: - raise ValueError( - f"Unsupported type {type(value)} for variable \ -{name}" - ) - - return result - - -def put_functions(functions: Functions) -> str: - """ - Generate a Bash script which defines a set of functions. - - :param functions: set of functions to define - :returns: generated Bash fragment - """ - result = "" - - for name, value in functions.items(): - result += f"{name}() {{\n{value}\n}}\n" - - return result - - -def _parse_string(token: str) -> str: - """Remove escape sequences from a Bash string.""" - return token.replace("\\$", "$") - - -def _generate_string(string: str) -> str: - """Generate a Bash string.""" - return shlex.quote(string) - - -def _parse_indexed(lexer: shlex.shlex) -> IndexedArray: - """Parse an indexed Bash array.""" - assert lexer.get_token() == "(" - result: List[Optional[str]] = [] - - while True: - token = lexer.get_token() - assert token != lexer.eof - - if token == ")": - break - - assert token == "[" - index = int(lexer.get_token()) - assert lexer.get_token() == "]" - assert lexer.get_token() == "=" - value = _parse_string(lexer.get_token()) - - # Grow the result array so that the index exists - if index >= len(result): - result.extend([None] * (index - len(result) + 1)) - - result[index] = value - - return result - - -def _generate_indexed(array: IndexedArray) -> str: - """Generate an indexed Bash array.""" - return ( - "(" - + " ".join( - f"[{index}]={_generate_string(value)}" - for index, value in enumerate(array) - if value is not None - ) - + ")" - ) - - -def _parse_assoc(lexer: shlex.shlex) -> AssociativeArray: - """Parse an associative Bash array.""" - assert lexer.get_token() == "(" - result = {} - - while True: - token = lexer.get_token() - assert token != lexer.eof - - if token == ")": - break - - assert token == "[" - key = lexer.get_token() - assert lexer.get_token() == "]" - assert lexer.get_token() == "=" - value = _parse_string(lexer.get_token()) - - result[key] = value - - return result - - -def _generate_assoc(array: AssociativeArray) -> str: - """Generate an associative Bash array.""" - return ( - "(" - + " ".join( - f"[{_generate_string(key)}]={_generate_string(value)}" - for key, value in array.items() - ) - + ")" - ) - - -def _parse_var(lexer: shlex.shlex) -> Tuple[str, Optional[Any]]: - """Parse a variable declaration.""" - flags_token = lexer.get_token() - - if flags_token != "--": - var_flags = set(flags_token[1:]) - else: - var_flags = set() - - var_name = lexer.get_token() - var_value: Optional[Any] = None - lookahead = lexer.get_token() - - if lookahead == "=": - if "a" in var_flags: - var_value = _parse_indexed(lexer) - elif "A" in var_flags: - var_value = _parse_assoc(lexer) - else: - var_value = _parse_string(lexer.get_token()) - else: - lexer.push_token(lookahead) - - return var_name, var_value - - -def _parse_func(lexer: shlex.shlex) -> Tuple[int, int]: - """Find the starting and end bounds of a function declaration.""" - assert lexer.get_token() == "{" - brace_depth = 1 - - start_byte = lexer.instream.tell() - - while brace_depth > 0: - token = lexer.get_token() - assert token != lexer.eof - - if token == "{": - brace_depth += 1 - elif token == "}": - brace_depth -= 1 - - end_byte = lexer.instream.tell() - 1 - return start_byte, end_byte - - -def run_script(variables: Variables, script: str) -> LogGenerator: - """ - Run a Bash script and stream its output. - - :param variables: Bash variables to set before running the script - :param script: Bash script to execute - :returns: generator yielding output lines from the script - :raises ScriptError: if the script exits with a non-zero code - """ - process = subprocess.Popen( - ["/usr/bin/env", "bash"], - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - ) - - assert process.stdin is not None - assert process.stdout is not None - process.stdin.write( - "\n".join( - ( - "set -euo pipefail", - put_variables(variables), - "script() {", - script, - "}", - "script", - ) - ).encode() - ) - process.stdin.close() - - while process.poll() is None: - line = process.stdout.readline() - if line: - yield line.decode().strip() - - if process.returncode != 0: - raise ScriptError(f"Script exited with code {process.returncode}") - - -def run_script_in_container( - docker: DockerClient, - image: str, - mounts: List, - variables: Variables, - script: str, -) -> LogGenerator: - """ - Run a Bash script inside a Docker container and stream its output. - - :param docker: Docker client - :param image: image to use for the new container - :param mounts: paths to mount in the container - :param variables: Bash variables to set before running the script - :param script: Bash script to execute - :returns: generator yielding output lines from the script - :raises ScriptError: if the script exits with a non-zero code - """ - container = docker.containers.run( - image, - mounts=mounts, - command=[ - "/usr/bin/env", - "bash", - "-c", - "\n".join( - ( - "set -euo pipefail", - put_variables(variables), - "script() {", - script, - "}", - "script", - ) - ), - ], - security_opt=["label=disable"], - detach=True, - ) - - try: - for line in container.logs(stream=True): - if line: - yield line.decode().strip() - - result = container.wait() - - if result["StatusCode"] != 0: - raise ScriptError(f"Script exited with code {result['StatusCode']}") - finally: - container.remove() diff --git a/scripts/toltec/builder.py b/scripts/toltec/builder.py deleted file mode 100644 index 6a5401747..000000000 --- a/scripts/toltec/builder.py +++ /dev/null @@ -1,689 +0,0 @@ -# Copyright (c) 2021 The Toltec Contributors -# SPDX-License-Identifier: MIT -"""Build recipes and create packages.""" - -import shutil -from typing import ( - Any, - Dict, - Deque, - List, - Mapping, - MutableMapping, - NamedTuple, - Optional, - Tuple, -) -from collections import deque -import re -import os -import shlex -import logging -import textwrap -import docker -from elftools.elf.elffile import ELFFile, ELFError -import requests -from . import bash, util, ipk, paths -from .recipe import GenericRecipe, Recipe, Package, BuildFlags -from .version import DependencyKind - -logger = logging.getLogger(__name__) - - -class BuildError(Exception): - """Raised when a build step fails.""" - - -class PostprocessingCandidates(NamedTuple): - """List of binaries on which post-processing needs to be done.""" - - strip_arm: List[str] - strip_x86: List[str] - patch_rm2fb: List[str] - - -class BuildContextAdapter(logging.LoggerAdapter): - """Prefix log entries with information about the current build target.""" - - def process( - self, msg: str, kwargs: MutableMapping[str, Any] - ) -> Tuple[str, MutableMapping[str, Any]]: - prefix = "" - - if "recipe" in self.extra: - prefix += self.extra["recipe"] - - if "arch" in self.extra: - prefix += f" [{self.extra['arch']}]" - - if "package" in self.extra: - prefix += f" ({self.extra['package']})" - - if prefix: - return f"{prefix}: {msg}", kwargs - - return msg, kwargs - - -class Builder: # pylint: disable=too-few-public-methods - """Helper class for building recipes.""" - - # Detect non-local paths - URL_REGEX = re.compile(r"[a-z]+://") - - # Prefix for all Toltec Docker images - IMAGE_PREFIX = "ghcr.io/toltec-dev/" - - # Toltec Docker image used for generic tasks - DEFAULT_IMAGE = "toolchain:v1.3.1" - - def __init__(self, work_dir: str, repo_dir: str) -> None: - """ - Create a builder helper. - - :param work_dir: directory where packages are built - :param repo_dir: directory where built packages are stored - """ - self.work_dir = work_dir - os.makedirs(work_dir, exist_ok=True) - - self.repo_dir = repo_dir - os.makedirs(repo_dir, exist_ok=True) - - self.install_lib = "" - install_lib_path = os.path.join(paths.SCRIPTS_DIR, "install-lib") - - self.context: Dict[str, str] = {} - self.adapter = BuildContextAdapter(logger, self.context) - - with open(install_lib_path, "r") as file: - for line in file: - if not line.strip().startswith("#"): - self.install_lib += line - - try: - self.docker = docker.from_env() - except docker.errors.DockerException as err: - raise BuildError( - "Unable to connect to the Docker daemon. \ -Please check that the service is running and that you have the necessary \ -permissions." - ) from err - - def make( - self, - generic_recipe: GenericRecipe, - arch_packages: Optional[Mapping[str, Optional[List[Package]]]] = None, - ) -> bool: - """ - Build packages defined by a recipe. - - :param generic_recipe: recipe to make - :param arch_packages: set of packages to build for each - architecture (default: all supported architectures - and all declared packages) - :returns: true if all the requested packages were built correctly - """ - self.context["recipe"] = generic_recipe.name - build_dir = os.path.join(self.work_dir, generic_recipe.name) - - if not util.check_directory( - build_dir, - f"The build directory '{os.path.relpath(build_dir)}' for recipe \ -'{generic_recipe.name}' already exists.\nWould you like to [c]ancel, [r]emove \ -that directory, or [k]eep it (not recommended)?", - ): - return False - - for name in ( - list(arch_packages.keys()) - if arch_packages is not None - else list(generic_recipe.recipes.keys()) - ): - if not self._make_arch( - generic_recipe.recipes[name], - os.path.join(build_dir, name), - arch_packages[name] if arch_packages is not None else None, - ): - return False - - return True - - def _make_arch( - self, - recipe: Recipe, - build_dir: str, - packages: Optional[List[Package]] = None, - ) -> bool: - self.context["arch"] = recipe.arch - - src_dir = os.path.join(build_dir, "src") - os.makedirs(src_dir, exist_ok=True) - self._fetch_sources(recipe, src_dir) - self._prepare(recipe, src_dir) - - base_pkg_dir = os.path.join(build_dir, "pkg") - os.makedirs(base_pkg_dir, exist_ok=True) - - self._build(recipe, src_dir) - self._postprocessing(recipe, src_dir) - - for package in ( - packages if packages is not None else recipe.packages.values() - ): - self.context["package"] = package.name - pkg_dir = os.path.join(base_pkg_dir, package.name) - os.makedirs(pkg_dir, exist_ok=True) - - self._package(package, src_dir, pkg_dir) - self._archive(package, pkg_dir) - del self.context["package"] - - del self.context["arch"] - return True - - def _fetch_sources( - self, - recipe: Recipe, - src_dir: str, - ) -> None: - """Fetch and extract all source files required to build a recipe.""" - self.adapter.info("Fetching source files") - - for source in recipe.sources: - filename = os.path.basename(source.url) - local_path = os.path.join(src_dir, filename) - - if self.URL_REGEX.match(source.url) is None: - # Get source file from the recipe’s directory - shutil.copy2( - os.path.join(recipe.parent.path, source.url), local_path - ) - else: - # Fetch source file from the network - req = requests.get(source.url) - - if req.status_code != 200: - raise BuildError( - f"Unexpected status code while fetching \ -source file '{source.url}', got {req.status_code}" - ) - - with open(local_path, "wb") as local: - for chunk in req.iter_content(chunk_size=1024): - local.write(chunk) - - # Verify checksum - file_sha = util.file_sha256(local_path) - if source.checksum != "SKIP" and file_sha != source.checksum: - raise BuildError( - f"Invalid checksum for source file {source.url}:\n" - f" expected {source.checksum}\n" - f" actual {file_sha}" - ) - - # Automatically extract source archives - if not source.noextract: - if not util.auto_extract(local_path, src_dir): - self.adapter.debug( - "Not extracting %s (unsupported archive type)", - local_path, - ) - - def _prepare(self, recipe: Recipe, src_dir: str) -> None: - """Prepare source files before building.""" - script = recipe.functions["prepare"] - - if not script: - self.adapter.debug("Skipping prepare (nothing to do)") - return - - self.adapter.info("Preparing source files") - logs = bash.run_script( - script=script, - variables={ - **recipe.variables, - **recipe.custom_variables, - "srcdir": src_dir, - }, - ) - - self._print_logs(logs, "prepare()") - - def _build(self, recipe: Recipe, src_dir: str) -> None: - """Build artifacts for a recipe.""" - script = recipe.functions["build"] - - if not script: - self.adapter.debug("Skipping build (nothing to do)") - return - - self.adapter.info("Building artifacts") - - # Set fixed atime and mtime for all the source files - epoch = int(recipe.timestamp.timestamp()) - - for filename in util.list_tree(src_dir): - os.utime(filename, (epoch, epoch)) - - mount_src = "/src" - repo_src = "/repo" - uid = os.getuid() - pre_script: List[str] = [] - - # Install required dependencies - build_deps = [] - host_deps = [] - - for dep in recipe.makedepends: - if dep.kind == DependencyKind.Build: - build_deps.append(dep.package) - elif dep.kind == DependencyKind.Host: - host_deps.append(dep.package) - - if build_deps: - pre_script.extend( - ( - "export DEBIAN_FRONTEND=noninteractive", - "apt-get update -qq", - "apt-get install -qq --no-install-recommends" - ' -o Dpkg::Options::="--force-confdef"' - ' -o Dpkg::Options::="--force-confold"' - " -- " + " ".join(build_deps), - ) - ) - - if host_deps: - opkg_conf_path = "$SYSROOT/etc/opkg/opkg.conf" - pre_script.extend( - ( - 'echo -n "dest root /', - "arch all 100", - "arch armv7-3.2 160", - "src/gz entware https://bin.entware.net/armv7sf-k3.2", - "arch rmall 200", - "src/gz toltec-rmall file:///repo/rmall", - f'" > "{opkg_conf_path}"', - ) - ) - - if recipe.arch != "rmall": - pre_script.extend( - ( - f'echo -n "arch {recipe.arch} 250', - f"src/gz toltec-{recipe.arch} file:///repo/{recipe.arch}", - f'" >> "{opkg_conf_path}"', - ) - ) - - pre_script.extend( - ( - "opkg update --verbosity=0", - "opkg install --verbosity=0 --no-install-recommends" - " -- " + " ".join(host_deps), - ) - ) - - logs = bash.run_script_in_container( - self.docker, - image=self.IMAGE_PREFIX + recipe.image, - mounts=[ - docker.types.Mount( - type="bind", - source=os.path.abspath(src_dir), - target=mount_src, - ), - docker.types.Mount( - type="bind", - source=os.path.abspath(self.repo_dir), - target=repo_src, - ), - ], - variables={ - **recipe.variables, - **recipe.custom_variables, - "srcdir": mount_src, - }, - script="\n".join( - ( - *pre_script, - f'cd "{mount_src}"', - script, - f'chown -R {uid}:{uid} "{mount_src}"', - ) - ), - ) - - self._print_logs(logs, "build()") - - def _postprocessing(self, recipe: Recipe, src_dir: str) -> None: - """Perform binary post-processing tasks such as stripping.""" - if ( - recipe.flags & BuildFlags.NOSTRIP - and not recipe.flags & BuildFlags.PATCH_RM2FB - ): - self.adapter.debug("Skipping post-processing (nothing to do)") - return - - self.adapter.info("Post-processing binaries") - - # Search for candidates - cand = self._postprocessing_candidates(src_dir) - - # Save original mtimes to restore them afterwards - # This will prevent any Makefile rules to be triggered again - # in packaging scripts that use `make install` - original_mtime = {} - - for file_path in (file for file_list in cand for file in file_list): - original_mtime[file_path] = os.stat(file_path).st_mtime_ns - - script = [] - mount_src = "/src" - - docker_file_path = lambda file_path: shlex.quote( - os.path.join(mount_src, os.path.relpath(file_path, src_dir)) - ) - - # Strip debugging symbols and unneeded sections - if not recipe.flags & BuildFlags.NOSTRIP: - if cand.strip_x86: - script.append( - "strip --strip-all -- " - + " ".join( - docker_file_path(file_path) - for file_path in cand.strip_x86 - ) - ) - - self.adapter.debug("x86 binaries to be stripped:") - - for file_path in cand.strip_x86: - self.adapter.debug( - " - %s", - os.path.relpath(file_path, src_dir), - ) - - if cand.strip_arm: - script.append( - '"${CROSS_COMPILE}strip" --strip-all -- ' - + " ".join( - docker_file_path(file_path) - for file_path in cand.strip_arm - ) - ) - - self.adapter.debug("ARM binaries to be stripped:") - - for file_path in cand.strip_arm: - self.adapter.debug( - " - %s", - os.path.relpath(file_path, src_dir), - ) - - # Add a dynamic dependency on the rm2fb client shim - if recipe.flags & BuildFlags.PATCH_RM2FB and cand.patch_rm2fb: - script = ( - [ - "export DEBIAN_FRONTEND=noninteractive", - "apt-get update -qq", - "apt-get install -qq --no-install-recommends patchelf", - ] - + script - + [ - "patchelf --add-needed librm2fb_client.so.1 " - + " ".join( - docker_file_path(file_path) - for file_path in cand.patch_rm2fb - ) - ] - ) - - self.adapter.debug("Binaries to be patched with rm2fb client:") - - for file_path in cand.patch_rm2fb: - self.adapter.debug( - " - %s", - os.path.relpath(file_path, src_dir), - ) - - if script: - logs = bash.run_script_in_container( - self.docker, - image=self.IMAGE_PREFIX + self.DEFAULT_IMAGE, - mounts=[ - docker.types.Mount( - type="bind", - source=os.path.abspath(src_dir), - target=mount_src, - ) - ], - variables={}, - script="\n".join(script), - ) - - self._print_logs(logs) - - # Restore original mtimes - for file_path, mtime in original_mtime.items(): - os.utime(file_path, ns=(mtime, mtime)) - - @staticmethod - def _postprocessing_candidates(src_dir: str) -> PostprocessingCandidates: - """Search for binaries that need to be post-processed.""" - strip_arm = [] - strip_x86 = [] - patch_rm2fb = [] - - for directory, _, files in os.walk(src_dir): - for file_name in files: - file_path = os.path.join(directory, file_name) - - try: - with open(file_path, "rb") as file: - info = ELFFile(file) - symtab = info.get_section_by_name(".symtab") - - if info.get_machine_arch() == "ARM": - if symtab: - strip_arm.append(file_path) - - dynamic = info.get_section_by_name(".dynamic") - rodata = info.get_section_by_name(".rodata") - - if ( - dynamic - and rodata - and rodata.data().find(b"/dev/fb0") != -1 - ): - patch_rm2fb.append(file_path) - elif ( - info.get_machine_arch() in ("x86", "x64") and symtab - ): - strip_x86.append(file_path) - except ELFError: - # Ignore non-ELF files - pass - except IsADirectoryError: - # Ignore directories - pass - - return PostprocessingCandidates( - strip_arm=strip_arm, - strip_x86=strip_x86, - patch_rm2fb=patch_rm2fb, - ) - - def _package(self, package: Package, src_dir: str, pkg_dir: str) -> None: - """Make a package from a recipe’s build artifacts.""" - self.adapter.info("Packaging build artifacts") - logs = bash.run_script( - script=package.functions["package"], - variables={ - **package.variables, - **package.custom_variables, - "srcdir": src_dir, - "pkgdir": pkg_dir, - }, - ) - - self._print_logs(logs, "package()") - self.adapter.debug("Resulting tree:") - - for filename in util.list_tree(pkg_dir): - self.adapter.debug( - " - %s", - os.path.normpath( - os.path.join("/", os.path.relpath(filename, pkg_dir)) - ), - ) - - def _archive(self, package: Package, pkg_dir: str) -> None: - """Create an archive for a package.""" - self.adapter.info("Creating archive") - ar_path = os.path.join(paths.REPO_DIR, package.filename()) - ar_dir = os.path.dirname(ar_path) - os.makedirs(ar_dir, exist_ok=True) - - # Inject Oxide-specific hook for reloading apps - if os.path.exists(os.path.join(pkg_dir, "opt/usr/share/applications")): - oxide_hook = "\nreload-oxide-apps\n" - package.functions["configure"] += oxide_hook - package.functions["postupgrade"] += oxide_hook - package.functions["postremove"] += oxide_hook - - # Convert install scripts to Debian format - scripts = {} - script_header = "\n".join( - ( - textwrap.dedent( - """\ - #!/usr/bin/env bash - set -euo pipefail - """ - ), - bash.put_variables( - { - **package.variables, - **package.custom_variables, - } - ), - bash.put_functions(package.custom_functions), - self.install_lib, - ) - ) - - for name, script, action in ( - ("preinstall", "preinst", "install"), - ("configure", "postinst", "configure"), - ): - if package.functions[name]: - scripts[script] = "\n".join( - ( - script_header, - textwrap.dedent( - f"""\ - if [[ $1 = {action} ]]; then - script() {{ - """ - ), - package.functions[name], - textwrap.dedent( - """\ - } - script - fi - """ - ), - ) - ) - - for step in ("pre", "post"): - if ( - package.functions[step + "upgrade"] - or package.functions[step + "remove"] - ): - script = script_header - - for action in ("upgrade", "remove"): - if package.functions[step + action]: - script += "\n".join( - ( - textwrap.dedent( - f"""\ - if [[ $1 = {action} ]]; then - script() {{ - """ - ), - package.functions[step + action], - textwrap.dedent( - """\ - } - script - fi - """ - ), - ) - ) - - scripts[step + "rm"] = script - - self.adapter.debug("Install scripts:") - - if scripts: - for script in sorted(scripts): - self.adapter.debug(" - %s", script) - else: - self.adapter.debug("(none)") - - epoch = int(package.parent.timestamp.timestamp()) - - with open(ar_path, "wb") as file: - ipk.make_ipk( - file, - epoch=epoch, - pkg_dir=pkg_dir, - metadata=package.control_fields(), - scripts=scripts, - ) - - # Set fixed atime and mtime for the resulting archive - os.utime(ar_path, (epoch, epoch)) - - def _print_logs( - self, - logs: bash.LogGenerator, - function_name: str = None, - max_lines_on_fail: int = 50, - ) -> None: - """ - Print logs to the debug output or buffer and print the last n log lines - if a ScriptError is caught. - - :param logs: generator of log lines - :param function_name: calling function name - :param max_lines_on_fail: number of context lines to print - in non-debug mode - """ - log_buffer: Deque[str] = deque() - try: - for line in logs: - if self.adapter.getEffectiveLevel() <= logging.DEBUG: - self.adapter.debug(line) - else: - if len(log_buffer) == max_lines_on_fail: - log_buffer.popleft() - log_buffer.append(line) - except bash.ScriptError as err: - if len(log_buffer) > 0: - self.adapter.info( - f"Only showing up to {max_lines_on_fail} lines of context. " - + "Use --verbose for the full output." - ) - for line in log_buffer: - self.adapter.error(line) - - if function_name: - self.adapter.error(f"{function_name} failed") - - raise err diff --git a/scripts/toltec/ipk.py b/scripts/toltec/ipk.py deleted file mode 100644 index 78678bd0c..000000000 --- a/scripts/toltec/ipk.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright (c) 2021 The Toltec Contributors -# SPDX-License-Identifier: MIT -"""Make ipk packages.""" - -from gzip import GzipFile -from typing import Dict, IO, Optional -from io import BytesIO -import tarfile -import operator -import os - - -def _targz_open(fileobj: IO[bytes], epoch: int) -> tarfile.TarFile: - """ - Open a gzip compressed tar archive for writing. - - Modified from :func:`tarfile.TarFile.gzopen` to support - setting the `mtime` attribute on `GzipFile`. - """ - gzipobj = GzipFile( - filename="", mode="wb", compresslevel=9, fileobj=fileobj, mtime=epoch - ) - - try: - archive = tarfile.TarFile( - mode="w", - fileobj=gzipobj, # type:ignore - format=tarfile.GNU_FORMAT, - ) - except: - gzipobj.close() - raise - - archive._extfileobj = False # type:ignore # pylint:disable=protected-access - return archive - - -def _clean_info( - root: Optional[str], epoch: int, info: tarfile.TarInfo -) -> tarfile.TarInfo: - """ - Remove variable data from an archive entry. - - :param root: absolute path to the root directory from which the - entry was added, or None to disable turning the name into a - relative path - :param epoch: fixed modification time to set - :param info: tarinfo object to set - :returns: changed tarinfo - """ - if root is not None: - info.name = os.path.relpath("/" + info.name, root) - - if not info.name.startswith("."): - info.name = "./" + info.name - - info.uid = 0 - info.gid = 0 - info.uname = "" - info.gname = "" - info.mtime = epoch - - return info - - -def _add_file( - archive: tarfile.TarFile, name: str, mode: int, epoch: int, data: bytes -) -> None: - """ - Add an in-memory file into a tar archive. - - :param archive: archive to append to - :param name: name of the file to add - :param mode: permissions of the file - :param epoch: fixed modification time to set - :param data: file contents - """ - info = tarfile.TarInfo("./" + name) - info.size = len(data) - info.mode = mode - archive.addfile(_clean_info(None, epoch, info), BytesIO(data)) - - -def make_control( - file: IO[bytes], epoch: int, metadata: str, scripts: Dict[str, str] -) -> None: - """ - Create the control sub-archive. - - See - and . - - :param file: file to which the sub-archive will be written - :param epoch: fixed modification time to set - :param metadata: package metadata (main control file) - :param scripts: optional maintainer scripts - """ - with _targz_open(file, epoch) as archive: - root_info = tarfile.TarInfo("./") - root_info.type = tarfile.DIRTYPE - archive.addfile(_clean_info(None, epoch, root_info)) - - _add_file(archive, "control", 0o644, epoch, metadata.encode()) - - for name, script in sorted(scripts.items(), key=operator.itemgetter(0)): - _add_file(archive, name, 0o755, epoch, script.encode()) - - -def make_data(file: IO[bytes], epoch: int, pkg_dir: str) -> None: - """ - Create the data sub-archive. - - :param file: file to which the sub-archive will be written - :param epoch: fixed modification time to set - :param pkg_dir: directory in which the package tree exists - """ - with _targz_open(file, epoch) as archive: - archive.add( - pkg_dir, filter=lambda info: _clean_info(pkg_dir, epoch, info) - ) - - -def make_ipk( - file: IO[bytes], - epoch: int, - pkg_dir: str, - metadata: str, - scripts: Dict[str, str], -) -> None: - """ - Create an ipk package. - - :param file: file to which the package will be written - :param epoch: fixed modification time to set - :param pkg_dir: directory in which the package tree exists - :param metadata: package metadata (main control file) - :param scripts: optional maintainer scripts - """ - with BytesIO() as control, BytesIO() as data, _targz_open( - file, epoch - ) as archive: - root_info = tarfile.TarInfo("./") - root_info.type = tarfile.DIRTYPE - archive.addfile(_clean_info(None, epoch, root_info)) - - make_control(control, epoch, metadata, scripts) - _add_file(archive, "control.tar.gz", 0o644, epoch, control.getvalue()) - - make_data(data, epoch, pkg_dir) - _add_file(archive, "data.tar.gz", 0o644, epoch, data.getvalue()) - - _add_file(archive, "debian-binary", 0o644, epoch, b"2.0\n") diff --git a/scripts/toltec/recipe.py b/scripts/toltec/recipe.py deleted file mode 100644 index e462be5ec..000000000 --- a/scripts/toltec/recipe.py +++ /dev/null @@ -1,536 +0,0 @@ -# Copyright (c) 2021 The Toltec Contributors -# SPDX-License-Identifier: MIT -""" -Parse recipes. - -A package is a final user-installable software archive. A recipe is a Bash file -which contains the instructions necessary to build one or more related -packages (in the latter case, it is called a split package). -""" - -from dataclasses import dataclass -from datetime import datetime -from enum import auto, Flag -from itertools import product -from typing import Dict, NamedTuple, Optional, Set -import os -import textwrap -import dateutil.parser -from .version import Version, Dependency, DependencyKind -from . import bash - - -class RecipeError(Exception): - """Raised when a recipe contains an error.""" - - -@dataclass -class GenericRecipe: # pylint:disable=too-many-instance-attributes - """Load recipes.""" - - name: str - path: str - recipes: Dict[str, "Recipe"] - - @staticmethod - def from_file(path: str) -> "GenericRecipe": - """ - Load a recipe from its directory. - - :param path: path to the directory containing the recipe definition - :returns: loaded recipe - """ - name = os.path.basename(path) - with open(os.path.join(path, "package"), "r") as recipe: - return GenericRecipe(name, path, recipe.read()) - - def __init__(self, name: str, path: str, definition: str): - """ - Load a recipe from a Bash source. - - :param name: name of the recipe - :param path: path to the directory containing the recipe definition - :param definition: source string of the recipe - :raises RecipeError: if the recipe contains an error - """ - self.name = name - self.path = path - variables, functions = bash.get_declarations(definition) - - archs = _pop_field_indexed(variables, "archs", ["rmall"]) - self.recipes = {} - - for arch in archs: - assert arch is not None - self._load_arch(arch, archs, variables.copy(), functions.copy()) - - def _load_arch( - self, - arch: str, - archs: bash.IndexedArray, - variables: bash.Variables, - functions: bash.Functions, - ) -> None: - """ - Instantiate a recipe for a given architecture. - - :param arch: target architecture - :param archs: available architectures - :param variables: Bash variables defined in the recipe - :param functions: Bash functions defined in the recipe - :raises RecipeError: if the recipe contains an error - """ - variables["arch"] = arch - - # Merge variables suffixed with the selected architecture - # into normal variables, drop other arch-specific variables - for name, value in list(variables.items()): - last_underscore = name.rfind("_") - - if last_underscore == -1: - continue - - var_arch = name[last_underscore + 1 :] - - if var_arch not in archs: - continue - - del variables[name] - - if var_arch != arch: - continue - - name = name[:last_underscore] - - if name not in variables: - variables[name] = value - else: - base_value = variables[name] - - if isinstance(base_value, str): - if not isinstance(value, str): - raise RecipeError( - f"Recipe '{self.name}' declares the \ -'{name}' field several times with different types" - ) - - variables[name] = value - - if isinstance(base_value, list): - if not isinstance(value, list): - raise RecipeError( - f"Recipe '{self.name}' declares the \ -'{name}' field several times with different types" - ) - - variables[name] = base_value + value - - self.recipes[arch] = Recipe( - self, f"{self.name}-{arch}", variables, functions - ) - - -class Source(NamedTuple): - """Source item needed to build a recipe.""" - - url: str - checksum: str - noextract: bool - - -class BuildFlags(Flag): - """Flags that guard special behaviors of the build system.""" - - NONE = auto() - - # Disable the automatic stripping of generated binaries - NOSTRIP = auto() - - # Patch all generated binaries with the rm2fb client shim - PATCH_RM2FB = auto() - - -@dataclass -class Recipe: # pylint:disable=too-many-instance-attributes - """Recipe specialized for a target architecture.""" - - parent: GenericRecipe - name: str - - variables: bash.Variables - custom_variables: bash.Variables - timestamp: datetime - sources: Set[Source] - makedepends: Set[Dependency] - maintainer: str - image: str - arch: str - flags: BuildFlags - - functions: bash.Functions - custom_functions: bash.Functions - - packages: Dict[str, "Package"] - - def __init__( - self, - parent: GenericRecipe, - name: str, - variables: bash.Variables, - functions: bash.Functions, - ): - """ - Load an architecture-specialized recipe. - - :param parent: recipe from which this is specialized - :param name: name of the recipe - :param variables: specialized Bash variables for the recipe - :param functions: specialized Bash functions for the recipe - :raises RecipeError: if the recipe contains an error - """ - self.parent = parent - self.name = name - - self.variables = {} - self.functions = {} - - self._load_fields(variables) - self._load_functions(functions) - self._load_packages(variables, functions) - - self.custom_variables = variables - self.custom_functions = functions - - def _load_fields(self, variables: bash.Variables) -> None: - """Parse and check standard fields.""" - flags = _pop_field_indexed(variables, "flags", []) - self.variables["flags"] = flags - self.flags = BuildFlags.NONE - - for flag in flags: - assert flag is not None - self.flags |= getattr(BuildFlags, flag.upper()) - - timestamp_str = _pop_field_string(variables, "timestamp") - self.variables["timestamp"] = timestamp_str - - try: - self.timestamp = dateutil.parser.isoparse(timestamp_str) - except ValueError as err: - raise RecipeError( - "Field 'timestamp' does not contain a valid ISO-8601 date" - ) from err - - sources = _pop_field_indexed(variables, "source", []) - self.variables["source"] = sources - - sha256sums = _pop_field_indexed(variables, "sha256sums", []) - self.variables["sha256sums"] = sha256sums - - noextract = _pop_field_indexed(variables, "noextract", []) - self.variables["noextract"] = noextract - - if len(sources) != len(sha256sums): - raise RecipeError( - f"Expected the same number of sources and checksums, got \ -{len(sources)} source(s) and {len(sha256sums)} checksum(s)" - ) - - self.sources = set() - - for source, checksum in zip(sources, sha256sums): - self.sources.add( - Source( - url=source or "", - checksum=checksum or "SKIP", - noextract=os.path.basename(source or "") in noextract, - ) - ) - - makedepends_raw = _pop_field_indexed(variables, "makedepends", []) - self.variables["makedepends"] = makedepends_raw - self.makedepends = { - Dependency.parse(dep or "") for dep in makedepends_raw - } - - self.maintainer = _pop_field_string(variables, "maintainer") - self.variables["maintainer"] = self.maintainer - - self.image = _pop_field_string(variables, "image", "") - self.variables["image"] = self.image - - self.arch = _pop_field_string(variables, "arch") - self.variables["arch"] = self.arch - - def _load_functions(self, functions: bash.Functions) -> None: - """Parse and check standard functions.""" - if self.image and "build" not in functions: - raise RecipeError( - "Missing build() function for a recipe which declares a \ -build image" - ) - - if not self.image and "build" in functions: - raise RecipeError( - "Missing image declaration for a recipe which has a \ -build() step" - ) - - self.functions["prepare"] = functions.pop("prepare", "") - self.functions["build"] = functions.pop("build", "") - - def _load_packages( - self, variables: bash.Variables, functions: bash.Functions - ) -> None: - """Load packages defined by this recipe.""" - pkgnames = _pop_field_indexed(variables, "pkgnames") - self.variables["pkgnames"] = pkgnames - self.packages = {} - - if len(pkgnames) == 1: - # Single-package recipe: use global declarations - pkg_name = pkgnames[0] - assert pkg_name is not None - variables["pkgname"] = pkg_name - self.packages[pkg_name] = Package(self, variables, functions) - else: - # Split-package recipe: load package-local declarations - pkg_decls = {} - - for sub_pkg_name in pkgnames: - assert sub_pkg_name is not None - - if sub_pkg_name not in functions: - raise RecipeError( - "Missing required function {sub_pkg_name}() for \ -corresponding package" - ) - - pkg_def = functions.pop(sub_pkg_name) - context = bash.put_variables( - { - **self.variables, - **variables, - "pkgname": sub_pkg_name, - } - ) - pkg_decls[sub_pkg_name] = bash.get_declarations( - context + pkg_def - ) - - for var_name in self.variables: - del pkg_decls[sub_pkg_name][0][var_name] - - for sub_pkg_name, (pkg_vars, pkg_funcs) in pkg_decls.items(): - self.packages[sub_pkg_name] = Package(self, pkg_vars, pkg_funcs) - - -@dataclass -class Package: # pylint:disable=too-many-instance-attributes - """Load packages.""" - - parent: Recipe - name: str - - variables: bash.Variables - custom_variables: bash.Variables - - version: Version - desc: str - url: str - section: str - license: str - installdepends: Set[Dependency] - conflicts: Set[Dependency] - replaces: Set[Dependency] - - functions: bash.Functions - custom_functions: bash.Functions - - def __init__( - self, - parent: Recipe, - variables: bash.Variables, - functions: bash.Functions, - ): - """ - Load a package. - - :param parent: specialized recipe which declares this package - :param variables: Bash variables declared in the package - :param functions: Bash functions declared in the package - :raises RecipeError: if the package contains an error - """ - self.parent = parent - self.variables = parent.variables.copy() - self.functions = {} - - self._load_fields(variables) - self._load_functions(functions) - self._load_custom(variables, functions) - - def _load_fields(self, variables: bash.Variables) -> None: - """Parse and check standard fields.""" - self.name = _pop_field_string(variables, "pkgname") - self.variables["pkgname"] = self.name - - pkgver_str = _pop_field_string(variables, "pkgver") - self.variables["pkgver"] = pkgver_str - self.version = Version.parse(pkgver_str) - - self.desc = _pop_field_string(variables, "pkgdesc") - self.variables["pkgdesc"] = self.desc - - self.url = _pop_field_string(variables, "url") - self.variables["url"] = self.url - - self.section = _pop_field_string(variables, "section") - self.variables["section"] = self.section - - self.license = _pop_field_string(variables, "license") - self.variables["license"] = self.license - - for field in ("installdepends", "conflicts", "replaces"): - field_raw = _pop_field_indexed(variables, field, []) - self.variables[field] = field_raw - setattr(self, field, set()) - - for dep_raw in field_raw: - assert dep_raw is not None - dep = Dependency.parse(dep_raw) - - if dep.kind != DependencyKind.Host: - raise RecipeError( - f"Only host packages are supported in the \ -'{field}' field" - ) - - getattr(self, field).add(dep) - - if self.parent.flags & BuildFlags.PATCH_RM2FB: - self.installdepends.add( - Dependency( - DependencyKind.Host, - "rm2fb-client", - ) - ) - - def _load_functions(self, functions: bash.Functions) -> None: - """Parse and check standard functions.""" - if "package" not in functions: - raise RecipeError( - f"Missing required function package() for package {self.name}" - ) - - self.functions["package"] = functions.pop("package") - - for action in ("preinstall", "configure"): - self.functions[action] = functions.pop(action, "") - - for rel, step in product(("pre", "post"), ("remove", "upgrade")): - self.functions[rel + step] = functions.pop(rel + step, "") - - def _load_custom( - self, variables: bash.Variables, functions: bash.Functions - ) -> None: - """Parse and check custom fields and functions.""" - for var_name in variables.keys(): - if not var_name.startswith("_"): - raise RecipeError( - f"Unknown field '{var_name}' in the definition of \ -package {self.name} ({self.parent.name}) — make sure to prefix the names of \ -custom fields with '_'" - ) - - for func_name in functions.keys(): - if not func_name.startswith("_"): - raise RecipeError( - f"Unknown function '{func_name}' in the definition of \ -package {self.name} ({self.parent.name}) — make sure to prefix the names of \ -custom functions with '_'" - ) - - self.custom_variables = variables - self.custom_functions = functions - - def pkgid(self) -> str: - """Get the unique identifier of this package.""" - return "_".join( - (self.name, str(self.version).replace(":", "_"), self.parent.arch) - ) - - def filename(self) -> str: - """Get the name of the archive corresponding to this package.""" - return os.path.join(self.parent.arch, self.pkgid() + ".ipk") - - def control_fields(self) -> str: - """Get the control fields for this package.""" - control = textwrap.dedent( - f"""\ - Package: {self.name} - Description: {self.desc} - Homepage: {self.url} - Version: {self.version} - Section: {self.section} - Maintainer: {self.parent.maintainer} - License: {self.license} - Architecture: {self.parent.arch} - """ - ) - - for debian_name, field in ( - ("Depends", self.installdepends), - ("Conflicts", self.conflicts), - ("Replaces", self.replaces), - ): - if field: - control += ( - debian_name - + ": " - + ", ".join(dep.to_debian() for dep in field if dep) - + "\n" - ) - - return control - - -# Helpers to check that fields of the right type are defined in a recipe -# and to otherwise return a default value -def _pop_field_string( - variables: bash.Variables, name: str, default: Optional[str] = None -) -> str: - if name not in variables: - if default is None: - raise RecipeError(f"Missing required field {name}") - return default - - value = variables.pop(name) - - if not isinstance(value, str): - raise RecipeError( - f"Field {name} must be a string, \ -got {type(variables[name]).__name__}" - ) - - return value - - -def _pop_field_indexed( - variables: bash.Variables, - name: str, - default: Optional[bash.IndexedArray] = None, -) -> bash.IndexedArray: - if name not in variables: - if default is None: - raise RecipeError(f"Missing required field '{name}'") - return default - - value = variables.pop(name) - - if not isinstance(value, list): - raise RecipeError( - f"Field '{name}' must be an indexed array, \ -got {type(variables[name]).__name__}" - ) - - return value diff --git a/scripts/toltec/templating.py b/scripts/toltec/templating.py deleted file mode 100644 index a23abbf46..000000000 --- a/scripts/toltec/templating.py +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2021 The Toltec Contributors -# SPDX-License-Identifier: MIT -""" -Load the Jinja2 templating engine. -""" -from jinja2 import Environment, PackageLoader - -env = Environment( - loader=PackageLoader("toltec", "templates"), - autoescape=True, -) diff --git a/scripts/toltec/util.py b/scripts/toltec/util.py deleted file mode 100644 index d9e623d1b..000000000 --- a/scripts/toltec/util.py +++ /dev/null @@ -1,332 +0,0 @@ -# Copyright (c) 2021 The Toltec Contributors -# SPDX-License-Identifier: MIT -"""Collection of useful functions.""" - -import argparse -from collections.abc import Iterable -import hashlib -import logging -import itertools -import os -import shutil -import sys -from typing import ( - Any, - Callable, - Dict, - IO, - List, - Optional, - Protocol, - Sequence, - TypeVar, -) -import zipfile -import tarfile - -# Date format used in HTTP headers such as Last-Modified -HTTP_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S %Z" - -# Logging format for build scripts -LOGGING_FORMAT = "[%(levelname)8s] %(name)s: %(message)s" - - -def argparse_add_verbose(parser: argparse.ArgumentParser) -> None: - """Add an option for setting the verbosity level.""" - parser.add_argument( - "-v", - "--verbose", - action="store_const", - const=logging.DEBUG, - default=logging.INFO, - help="show debugging information", - ) - - -def file_sha256(path: str) -> str: - """Compute the SHA-256 checksum of a file.""" - sha256 = hashlib.sha256() - buffer = bytearray(128 * 1024) - view = memoryview(buffer) - - with open(path, "rb", buffering=0) as file: - for length in iter(lambda: file.readinto(view), 0): # type:ignore - sha256.update(view[:length]) - - return sha256.hexdigest() - - -def split_all_parts(path: str) -> List[str]: - """Split a file path into all its directory components.""" - parts = [] - prefix = path - - while prefix not in ("", "/"): - prefix, base = os.path.split(prefix) - if base: - parts.append(base) - - parts.reverse() - return parts - - -def split_all_exts(path: str) -> List[str]: - """Get the list of extensions in a file path.""" - exts = [] - remaining = path - - while True: - remaining, ext = os.path.splitext(remaining) - if ext: - exts.append(ext) - else: - break - - return exts - - -def all_equal(seq: Iterable) -> bool: - """Check that all elements of a sequence are equal.""" - grouped = itertools.groupby(seq) - first = next(grouped, (None, grouped)) - second = next(grouped, None) - return first and not second - - -def remove_prefix(filenames: List[str]) -> Dict[str, str]: - """Find and remove the longest directory prefix shared by all files.""" - split_filenames = [split_all_parts(filename) for filename in filenames] - - # Find the longest directory prefix shared by all files - min_len = min(len(filename) for filename in split_filenames) - prefix = 0 - - while prefix < min_len and all_equal( - filename[prefix] for filename in split_filenames - ): - prefix += 1 - - # If there’s only one file, keep the last component - if len(filenames) == 1: - prefix -= 1 - - mapping = {} - - for filename, split_filename in zip(filenames, split_filenames): - if split_filename[prefix:]: - mapping[filename] = os.path.join(*split_filename[prefix:]) - - return mapping - - -def auto_extract(archive_path: str, dest_path: str) -> bool: - """ - Automatically extract an archive and strip useless components. - - :param archive_path: path to the archive to extract - :param dest_path: destination folder for the archive contents - :returns: true if something was extracted, false if not a supported archive - """ - exts = split_all_exts(archive_path) - - if not exts: - return False - - if exts[0] == ".zip": - with zipfile.ZipFile(archive_path) as zip_archive: - _auto_extract( - zip_archive.namelist(), - zip_archive.getinfo, - zip_archive.open, - lambda member: member.is_dir(), - lambda member: False, - lambda member: member.external_attr >> 16 & 0x1FF, - dest_path, - ) - return True - - if exts[0] == ".tar" or ( - len(exts) >= 2 - and exts[0] in (".gz", ".bz2", ".xz") - and exts[1] == ".tar" - ): - with tarfile.open(archive_path, mode="r") as tar_archive: - _auto_extract( - tar_archive.getnames(), - tar_archive.getmember, - tar_archive.extractfile, - lambda member: member.isdir(), - lambda member: member.issym(), - lambda member: member.mode, - dest_path, - ) - return True - - return False - - -def _auto_extract( # pylint:disable=too-many-arguments,disable=too-many-locals - members: List[str], - getinfo: Callable[[str], Any], - extract: Callable[[Any], Optional[IO[bytes]]], - isdir: Callable[[Any], bool], - issym: Callable[[Any], bool], - getmode: Callable[[Any], int], - dest_path: str, -) -> None: - """ - Generic implementation of automatic archive extraction. - - :param members: list of members of the archive - :param getinfo: get an entry object from an entry name in the archive - :param extract: get a reading stream corresponding to an archive entry - :param isdir: get whether an entry is a directory or not - :param issym: get whether an entry is a symbolic link or not - :param getmode: get the permission bits for an entry - :param destpath: destinatio folder for the archive contents - """ - stripped_map = remove_prefix(members) - - for filename, stripped in stripped_map.items(): - member = getinfo(filename) - file_path = os.path.join(dest_path, stripped) - - if isdir(member): - os.makedirs(file_path, exist_ok=True) - else: - if issym(member): - os.symlink(member.linkname, file_path) - else: - basedir = os.path.dirname(file_path) - if not os.path.exists(basedir): - os.makedirs(basedir, exist_ok=True) - - source = extract(member) - assert source is not None - - with source, open(file_path, "wb") as target: - shutil.copyfileobj(source, target) - - mode = getmode(member) - if mode != 0: - os.chmod(file_path, mode) - - -def query_user( - question: str, - default: str, - options: Optional[List[str]] = None, - aliases: Optional[Dict[str, str]] = None, -) -> str: - """ - Ask the user to make a choice. - - :param question: message to display before the choice - :param default: default choice if the user inputs an empty string - :param options: list of valid options (should be lowercase strings) - :param aliases: accepted aliases for the valid options - :returns: option chosen by the user - """ - options = options or ["y", "n"] - aliases = aliases or {"yes": "y", "no": "n"} - - if default not in options: - raise ValueError(f"Default value {default} is not a valid option") - - prompt = "/".join( - option if option != default else option.upper() for option in options - ) - - while True: - sys.stdout.write(f"{question} [{prompt}] ") - choice = input().lower() - - if not choice: - return default - - if choice in options: - return choice - - if choice in aliases: - return aliases[choice] - - print("Invalid answer. Please choose among the valid options.") - - -def check_directory(path: str, message: str) -> bool: - """ - Create a directory and ask the user what to do if it already exists. - - :param path: path to the directory to create - :param message: message to display before asking the user interactively - :returns: false if the user chose to cancel the current operation - """ - try: - os.mkdir(path) - except FileExistsError: - ans = query_user( - message, - default="c", - options=["c", "r", "k"], - aliases={ - "cancel": "c", - "remove": "r", - "keep": "k", - }, - ) - - if ans == "c": - return False - - if ans == "r": - shutil.rmtree(path) - os.mkdir(path) - - return True - - -def list_tree(root: str) -> List[str]: - """ - Get a sorted list of all files and folders under a given root folder. - - :param root: root folder to start from - :returns: sorted list of items under the root folder - """ - result = [] - - for directory, _, files in os.walk(root): - result.append(directory) - for file in files: - result.append(os.path.join(directory, file)) - - return sorted(result) - - -# See -class SupportsLessThan(Protocol): # pylint:disable=too-few-public-methods - """Types that support the less-than operator.""" - - def __lt__(self, other: Any) -> bool: - ... - - -Key = TypeVar("Key", bound=SupportsLessThan) -Value = TypeVar("Value") - - -def group_by( - in_seq: Sequence[Value], key_fn: Callable[[Value], Key] -) -> Dict[Key, List[Value]]: - """ - Group elements of a list. - - :param in_seq: list of elements to group - :param key_fn: mapping of each element onto a group - :returns: dictionary of groups - """ - return dict( - (key, list(group)) - for key, group in itertools.groupby( - sorted(in_seq, key=key_fn), key=key_fn - ) - ) diff --git a/scripts/toltec/version.py b/scripts/toltec/version.py deleted file mode 100644 index 67dcb46f4..000000000 --- a/scripts/toltec/version.py +++ /dev/null @@ -1,212 +0,0 @@ -# Copyright (c) 2021 The Toltec Contributors -# SPDX-License-Identifier: MIT -"""Parse versions and dependency specifications.""" - -import re -from enum import Enum -from typing import Optional - -# Characters permitted in the upstream version part of a version number -_VERSION_CHARS = re.compile("^[A-Za-z0-9.+~-]+$") - -# Characters making up a version comparator -_COMPARATOR_CHARS = re.compile("[<>=]") - - -class VersionComparator(Enum): - """Operators used to compare two version numbers.""" - - LowerThan = "<<" - LowerThanOrEqual = "<=" - Equal = "=" - GreaterThanOrEqual = ">=" - GreaterThan = ">>" - - -class InvalidVersionError(Exception): - """Raised when parsing of an invalid version is attempted.""" - - -class Version: - """ - Parse package versions. - - See - for details about the format and the comparison rules. - """ - - def __init__(self, epoch: int, upstream: str, revision: str): - self.upstream = upstream - self.revision = revision - self.epoch = epoch - - if _VERSION_CHARS.fullmatch(upstream) is None: - raise InvalidVersionError( - f"Invalid chars in upstream version: '{upstream}'" - ) - - if _VERSION_CHARS.fullmatch(revision) is None: - raise InvalidVersionError( - f"Invalid chars in revision: '{revision}'" - ) - - self._original: Optional[str] = None - - @staticmethod - def parse(version: str) -> "Version": - """Parse a version number.""" - original = version - colon = version.find(":") - - if colon == -1: - epoch = 0 - else: - epoch = int(version[:colon]) - version = version[colon + 1 :] - - dash = version.find("-") - - if dash == -1: - revision = "0" - else: - revision = version[dash + 1 :] - version = version[:dash] - - upstream = version - - result = Version(epoch, upstream, revision) - result._original = original # pylint:disable=protected-access - return result - - def __str__(self) -> str: - if self._original is not None: - # Use the original parsed version string - return self._original - - epoch = "" if self.epoch == 0 else f"{self.epoch}:" - revision = ( - "" - if self.revision == "0" and "-" not in self.upstream - else f"-{self.revision}" - ) - - return f"{epoch}{self.upstream}{revision}" - - def __repr__(self) -> str: - return f"Version(upstream={repr(self.upstream)}, \ -revision={repr(self.revision)}, epoch={repr(self.epoch)})" - - -class DependencyKind(Enum): - """Kinds of dependencies that may be requested by a package.""" - - # Dependency installed in the system used to build a package - # (e.g., a Debian package) - Build = "build" - # Dependency installed alongside a package - # (e.g., another Entware or Toltec package) - Host = "host" - - -class InvalidDependencyError(Exception): - """Raised when parsing an invalid dependency specification.""" - - -class Dependency: - """ - Parse version-constrained dependencies. - - Toltec dependencies are declared using the following format: - - [host:|build:]package[(<<|<=|=|=>|>>)version] - - Dependencies of a package that start with `build:` correspond to packages - that must be installed in the build system. Dependencies that start with - `host:` or do not have a prefix correspond to packages that must be - installed alongside the built package, either in the host sysroot when - building the package, or in the target device when using it. - """ - - def __init__( - self, - kind: DependencyKind, - package: str, - version_comparator: VersionComparator = VersionComparator.Equal, - version: Optional[Version] = None, - ): - self.kind = kind - self.package = package - self.version_comparator = version_comparator - self.version = version - - self._original: Optional[str] = None - - @staticmethod - def parse(dependency: str) -> "Dependency": - """Parse a dependency specification.""" - original = dependency - kind = DependencyKind.Host - - for enum_kind in DependencyKind: - if dependency.startswith(enum_kind.value + ":"): - kind = enum_kind - dependency = dependency[len(enum_kind.value) + 1 :] - break - - comp_char_match = _COMPARATOR_CHARS.search(dependency) - - if comp_char_match is None: - package = dependency - version_comparator = VersionComparator.Equal - version = None - else: - comp_char = comp_char_match.start() - for enum_comparator in VersionComparator: - if dependency[comp_char:].startswith(enum_comparator.value): - package = dependency[:comp_char] - version_comparator = enum_comparator - version = Version.parse( - dependency[comp_char + len(enum_comparator.value) :] - ) - break - else: - raise InvalidDependencyError( - f"Invalid version comparator \ -'{dependency[comp_char : comp_char + 2]}'" - ) - - result = Dependency(kind, package, version_comparator, version) - result._original = original # pylint:disable=protected-access - return result - - def to_debian(self) -> str: - """ - Convert a dependency specification to the Debian format. - - See - for the syntax expected by Debian tools. - """ - if self.version is None: - return self.package - - return f"{self.package} ({self.version_comparator.value} \ -{self.version})" - - def __str__(self) -> str: - if self._original is not None: - # Use the original parsed dependency specification - return self._original - - kind = "build:" if self.kind == DependencyKind.Build else "host:" - - if self.version is None: - return f"{kind}{self.package}" - - return f"{kind}{self.package}{self.version_comparator.value}\ -{self.version}" - - def __repr__(self) -> str: - return f"Dependency(kind={repr(self.kind)}, \ -package={repr(self.package)}, \ -version_comparator={repr(self.version_comparator)}, \ -version={repr(self.version)})"