From 525a2f13bc7c4f8e443c3faf7dd5a8d6cb015748 Mon Sep 17 00:00:00 2001 From: Aryo Nazaradeh Date: Fri, 17 Jul 2026 13:03:40 -0700 Subject: [PATCH] anki: update to 26.05. Co-authored-by: Duncaen --- srcpkgs/anki/patches/cross-build.patch | 75 +++++++++ srcpkgs/anki/patches/disable_popup.patch | 10 -- .../patches/fix_distutils_not_found.patch | 8 - srcpkgs/anki/patches/fix_float.patch | 42 ----- srcpkgs/anki/patches/fix_mpv_args.patch | 29 ---- srcpkgs/anki/patches/fix_profile_save.patch | 15 -- srcpkgs/anki/patches/fix_unescape.patch | 11 -- srcpkgs/anki/patches/no-corepack.patch | 24 +++ srcpkgs/anki/patches/no-update.patch | 12 ++ .../anki/patches/reproducible-sveltekit.patch | 20 +++ .../anki/patches/strip-formatter-deps.patch | 8 + .../patches/strip-type-checking-deps.patch | 21 +++ srcpkgs/anki/template | 145 ++++++++++++++++-- 13 files changed, 295 insertions(+), 125 deletions(-) create mode 100644 srcpkgs/anki/patches/cross-build.patch delete mode 100644 srcpkgs/anki/patches/disable_popup.patch delete mode 100644 srcpkgs/anki/patches/fix_distutils_not_found.patch delete mode 100644 srcpkgs/anki/patches/fix_float.patch delete mode 100644 srcpkgs/anki/patches/fix_mpv_args.patch delete mode 100644 srcpkgs/anki/patches/fix_profile_save.patch delete mode 100644 srcpkgs/anki/patches/fix_unescape.patch create mode 100644 srcpkgs/anki/patches/no-corepack.patch create mode 100644 srcpkgs/anki/patches/no-update.patch create mode 100644 srcpkgs/anki/patches/reproducible-sveltekit.patch create mode 100644 srcpkgs/anki/patches/strip-formatter-deps.patch create mode 100644 srcpkgs/anki/patches/strip-type-checking-deps.patch diff --git a/srcpkgs/anki/patches/cross-build.patch b/srcpkgs/anki/patches/cross-build.patch new file mode 100644 index 00000000000000..980655fae12d3f --- /dev/null +++ b/srcpkgs/anki/patches/cross-build.patch @@ -0,0 +1,75 @@ +--- a/build/ninja_gen/src/build.rs ++++ b/build/ninja_gen/src/build.rs +@@ -53,7 +53,7 @@ + have_n2: which::which("n2").is_ok(), + }; + +- build.add_action("build:configure", ConfigureBuild {})?; ++ // build.add_action("build:configure", ConfigureBuild {})?; + + Ok(build) + } +--- a/build/ninja_gen/src/render.rs ++++ b/build/ninja_gen/src/render.rs +@@ -2,6 +2,7 @@ + // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + + use std::fmt::Write; ++use std::env; + + use anki_io::create_dir_all; + use anki_io::write_file_if_changed; +@@ -25,7 +26,8 @@ + writeln!(&mut buf, "builddir = {}", self.buildroot.as_str()).unwrap(); + writeln!( + &mut buf, +- "runner = $builddir/rust/release/{}", ++ "runner = $builddir/rust/{}/release/{}", ++ env::var("RUST_BUILD").unwrap(), + with_exe("runner") + ) + .unwrap(); +--- a/build/ninja_gen/src/cargo.rs ++++ b/build/ninja_gen/src/cargo.rs +@@ -97,7 +97,7 @@ + .release_override + .unwrap_or_else(|| build.build_profile()); + let release_arg = profile_arg_for_cargo(release_build).unwrap_or_default(); +- let target_arg = if let Some(target) = self.target { ++ let target_arg = if let Some(target) = &self.target { + format!("--target {target}") + } else { + "".into() +@@ -115,7 +115,7 @@ + let output_root = Utf8Path::new("$builddir/rust"); + for output in self.outputs { + let name = output.name(); +- let path = output.path(output_root, self.target, release_build); ++ let path = output.path(output_root, self.target.as_deref(), release_build); + build.add_outputs_ext(name, vec![path], true); + } + } +--- a/build/configure/src/platform.rs ++++ b/build/configure/src/platform.rs +@@ -6,8 +6,8 @@ + use ninja_gen::archives::Platform; + + /// Please see [`overriden_python_target_platform()`] for details. +-pub fn overriden_rust_target_triple() -> Option<&'static str> { +- overriden_python_wheel_platform().map(|p| p.as_rust_triple()) ++pub fn overriden_rust_target_triple() -> Option { ++ env::var("RUST_TARGET").ok() + } + + /// Usually None to use the host architecture, but: +--- a/build/ninja_gen/src/cargo.rs ++++ b/build/ninja_gen/src/cargo.rs +@@ -79,7 +79,7 @@ + pub struct CargoBuild<'a> { + pub inputs: BuildInput, + pub outputs: &'a [RustOutput<'a>], +- pub target: Option<&'static str>, ++ pub target: Option, + pub extra_args: &'a str, + pub release_override: Option, + } diff --git a/srcpkgs/anki/patches/disable_popup.patch b/srcpkgs/anki/patches/disable_popup.patch deleted file mode 100644 index 8b7a041fc656e5..00000000000000 --- a/srcpkgs/anki/patches/disable_popup.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/aqt/update.py -+++ b/aqt/update.py -@@ -31,6 +31,7 @@ class LatestVersionFinder(QThread): - return d - - def run(self): -+ return - if not self.config['updates']: - return - d = self._data() diff --git a/srcpkgs/anki/patches/fix_distutils_not_found.patch b/srcpkgs/anki/patches/fix_distutils_not_found.patch deleted file mode 100644 index 555c89bbf766b7..00000000000000 --- a/srcpkgs/anki/patches/fix_distutils_not_found.patch +++ /dev/null @@ -1,8 +0,0 @@ ---- a/anki/mpv.py -+++ b/anki/mpv.py -@@ -39 +39 @@ import inspect --from distutils.spawn import find_executable # pylint: disable=import-error,no-name-in-module -+from shutil import which -@@ -68 +68 @@ class MPVBase: -- executable = find_executable("mpv") -+ executable = which("mpv") diff --git a/srcpkgs/anki/patches/fix_float.patch b/srcpkgs/anki/patches/fix_float.patch deleted file mode 100644 index 333d76c8efd786..00000000000000 --- a/srcpkgs/anki/patches/fix_float.patch +++ /dev/null @@ -1,42 +0,0 @@ ---- a/aqt/deckconf.py -+++ b/aqt/deckconf.py -@@ -172,7 +172,7 @@ class DeckConf(QDialog): - f.lrnGradInt.setValue(c['ints'][0]) - f.lrnEasyInt.setValue(c['ints'][1]) - f.lrnEasyInt.setValue(c['ints'][1]) -- f.lrnFactor.setValue(c['initialFactor']/10.0) -+ f.lrnFactor.setValue(c['initialFactor']//10) - f.newOrder.setCurrentIndex(c['order']) - f.newPerDay.setValue(c['perDay']) - f.bury.setChecked(c.get("bury", True)) -@@ -180,7 +180,7 @@ class DeckConf(QDialog): - # rev - c = self.conf['rev'] - f.revPerDay.setValue(c['perDay']) -- f.easyBonus.setValue(c['ease4']*100) -+ f.easyBonus.setValue(int(c['ease4'])*100) - f.fi1.setValue(c['ivlFct']*100) - f.maxIvl.setValue(c['maxIvl']) - f.revplim.setText(self.parentLimText('rev')) -@@ -192,7 +192,7 @@ class DeckConf(QDialog): - # lapse - c = self.conf['lapse'] - f.lapSteps.setText(self.listToUser(c['delays'])) -- f.lapMult.setValue(c['mult']*100) -+ f.lapMult.setValue(int(c['mult'])*100) - f.lapMinInt.setValue(c['minInt']) - f.leechThreshold.setValue(c['leechFails']) - f.leechAction.setCurrentIndex(c['leechAction']) ---- a/aqt/preferences.py -+++ b/aqt/preferences.py -@@ -77,8 +77,8 @@ class Preferences(QDialog): - f.hwAccel.setVisible(False) - else: - f.hwAccel.setChecked(self.mw.pm.glMode() != "software") -- f.lrnCutoff.setValue(qc['collapseTime']/60.0) -- f.timeLimit.setValue(qc['timeLim']/60.0) -+ f.lrnCutoff.setValue(qc['collapseTime']//60) -+ f.timeLimit.setValue(qc['timeLim']//60) - f.showEstimates.setChecked(qc['estTimes']) - f.showProgress.setChecked(qc['dueCounts']) - f.nightMode.setChecked(qc.get("nightMode", False)) diff --git a/srcpkgs/anki/patches/fix_mpv_args.patch b/srcpkgs/anki/patches/fix_mpv_args.patch deleted file mode 100644 index 0b99dd8fe8567f..00000000000000 --- a/srcpkgs/anki/patches/fix_mpv_args.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- a/anki/mpv.py -+++ b/anki/mpv.py -@@ -104,9 +104,9 @@ - """ - self.argv = [self.executable] - self.argv += self.default_argv -- self.argv += ["--input-ipc-server", self._sock_filename] -+ self.argv += ["--input-ipc-server="+self._sock_filename] - if self.window_id is not None: -- self.argv += ["--wid", str(self.window_id)] -+ self.argv += ["--wid="+str(self.window_id)] - - def _start_process(self): - """Start the mpv process. - ---- a/anki/sound.py -+++ b/anki/sound.py -@@ -123,10 +123,7 @@ - - def setMpvConfigBase(base): - mpvConfPath = os.path.join(base, "mpv.conf") -- MpvManager.default_argv += [ -- "--no-config", -- "--include="+mpvConfPath, -- ] -+ MpvManager.default_argv += ["--include="+mpvConfPath] - - mpvManager = None - diff --git a/srcpkgs/anki/patches/fix_profile_save.patch b/srcpkgs/anki/patches/fix_profile_save.patch deleted file mode 100644 index 9d72a1a20e821b..00000000000000 --- a/srcpkgs/anki/patches/fix_profile_save.patch +++ /dev/null @@ -1,15 +0,0 @@ -Fixes crash related to saving profile data on exit. ---- a/aqt/profiles.py -+++ b/aqt/profiles.py -@@ -160,7 +160,10 @@ a flash drive.""" % self.base) - return up.load() - - def _pickle(self, obj): -- return pickle.dumps(obj, protocol=0) -+ for key, val in obj.items(): -+ if isinstance(val, QByteArray): -+ obj[key] = bytes(val) # type: ignore -+ return pickle.dumps(obj, protocol=4) - - def load(self, name): - assert name != "_global" diff --git a/srcpkgs/anki/patches/fix_unescape.patch b/srcpkgs/anki/patches/fix_unescape.patch deleted file mode 100644 index f7024bc7bf1555..00000000000000 --- a/srcpkgs/anki/patches/fix_unescape.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/aqt/reviewer.py -+++ b/aqt/reviewer.py -@@ -359,7 +359,7 @@ - cor = stripHTML(cor) - # ensure we don't chomp multiple whitespace - cor = cor.replace(" ", " ") -- cor = parser.unescape(cor) -+ cor = html.unescape(cor) - cor = cor.replace("\xa0", " ") - cor = cor.strip() - given = self.typedAnswer diff --git a/srcpkgs/anki/patches/no-corepack.patch b/srcpkgs/anki/patches/no-corepack.patch new file mode 100644 index 00000000000000..7f8223c503f745 --- /dev/null +++ b/srcpkgs/anki/patches/no-corepack.patch @@ -0,0 +1,24 @@ ++https://gitlab.archlinux.org/archlinux/packaging/packages/anki +--- i/build/ninja_gen/src/node.rs ++++ w/build/ninja_gen/src/node.rs +@@ -52,7 +52,7 @@ impl BuildAction for YarnSetup { + if cfg!(windows) { + "corepack.cmd enable yarn" + } else { +- "corepack enable yarn" ++ "true" + } + } + +diff --git i/package.json w/package.json +index f85945cd5..40ec95796 100644 +--- i/package.json ++++ w/package.json +@@ -92,6 +92,5 @@ + "Chrome 77", + "iOS 14.5" + ], +- "type": "module", +- "packageManager": "yarn@4.11.0" ++ "type": "module" + } diff --git a/srcpkgs/anki/patches/no-update.patch b/srcpkgs/anki/patches/no-update.patch new file mode 100644 index 00000000000000..5a8543a75924ec --- /dev/null +++ b/srcpkgs/anki/patches/no-update.patch @@ -0,0 +1,12 @@ ++https://gitlab.archlinux.org/archlinux/packaging/packages/anki +--- a/qt/aqt/update.py ++++ b/qt/aqt/update.py +@@ -11,6 +11,8 @@ from aqt.utils import openLink, show_warning, showText, tr + + + def check_for_update() -> None: ++ return ++ + from aqt import mw + + def do_check(_col: Collection) -> CheckForUpdateResponse: diff --git a/srcpkgs/anki/patches/reproducible-sveltekit.patch b/srcpkgs/anki/patches/reproducible-sveltekit.patch new file mode 100644 index 00000000000000..b5e0b00d720ddb --- /dev/null +++ b/srcpkgs/anki/patches/reproducible-sveltekit.patch @@ -0,0 +1,20 @@ ++https://gitlab.archlinux.org/archlinux/packaging/packages/anki +--- i/ts/svelte.config.js ++++ w/ts/svelte.config.js +@@ -1,5 +1,6 @@ + import adapter from "@sveltejs/adapter-static"; + import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; ++import { readFileSync } from "fs"; + import { dirname, join } from "path"; + import preprocess from "svelte-preprocess"; + import { fileURLToPath } from "url"; +@@ -17,6 +18,9 @@ const config = { + adapter: adapter( + { pages: "../out/sveltekit", fallback: "index.html", precompress: false }, + ), ++ version: { ++ name: readFileSync(join(tsFolder, "../.version"), "utf-8").trim(), ++ }, + alias: { + "@tslib": join(tsFolder, "lib/tslib"), + "@generated": join(tsFolder, "../out/ts/lib/generated"), diff --git a/srcpkgs/anki/patches/strip-formatter-deps.patch b/srcpkgs/anki/patches/strip-formatter-deps.patch new file mode 100644 index 00000000000000..39b27dc8db5036 --- /dev/null +++ b/srcpkgs/anki/patches/strip-formatter-deps.patch @@ -0,0 +1,8 @@ ++https://gitlab.archlinux.org/archlinux/packaging/packages/anki +--- i/pylib/tools/hookslib.py ++++ w/pylib/tools/hookslib.py +@@ -205,4 +205,3 @@ def write_file(path: str, hooks: list[Hook], prefix: str, suffix: str): + + with open(path, "wb") as file: + file.write(code.encode("utf8")) +- subprocess.run([sys.executable, "-m", "ruff", "format", "-q", path], check=True) diff --git a/srcpkgs/anki/patches/strip-type-checking-deps.patch b/srcpkgs/anki/patches/strip-type-checking-deps.patch new file mode 100644 index 00000000000000..9624a62f42c25b --- /dev/null +++ b/srcpkgs/anki/patches/strip-type-checking-deps.patch @@ -0,0 +1,21 @@ ++https://gitlab.archlinux.org/archlinux/packaging/packages/anki +--- i/build/configure/src/python.rs ++++ w/build/configure/src/python.rs +@@ -81,9 +81,7 @@ pub struct GenPythonProto { + impl BuildAction for GenPythonProto { + fn command(&self) -> &str { + "$protoc $ +- --plugin=protoc-gen-mypy=$protoc-gen-mypy $ + --python_out=$builddir/pylib $ +- --mypy_out=$builddir/pylib $ + -Iproto $in" + } + +@@ -101,7 +99,6 @@ impl BuildAction for GenPythonProto { + .collect(); + build.add_inputs("in", &self.proto_files); + build.add_inputs("protoc", inputs![":protoc_binary"]); +- build.add_inputs("protoc-gen-mypy", inputs![":pyenv:protoc-gen-mypy"]); + build.add_outputs("", python_outputs); + } + diff --git a/srcpkgs/anki/template b/srcpkgs/anki/template index 97ad67d6001a18..368d5083605c3c 100644 --- a/srcpkgs/anki/template +++ b/srcpkgs/anki/template @@ -1,20 +1,145 @@ # Template file for 'anki' pkgname=anki -version=2.1.15 -revision=7 -build_style=gnu-makefile -depends="python3-PyQt5-webengine python3-requests python3-SQLAlchemy - python3-PyAudio python3-mpv python3-Markdown python3-send2trash - python3-BeautifulSoup4 python3-decorator python3-jsonschema" +version=26.05 +revision=1 +_anki_core_i18n_commit=af7c60d7f1aa1b831eb3b893558e4c625309ac2b +_anki_desktop_ftl_commit=3a35d0aba2b1d04a69ddb471fb4d62645f6763d3 +build_helper="rust" +# Leaving out the texlive optional dependency. +# Its use case is niche, is a large package, and increases install time significantly. +# lame and mpv are also optional, but are common enough while small enoough packages. +hostmakedepends="cargo cargo-auditable rust rust-std ninja nodejs pkg-config + protobuf python3-installer python3-packaging-bootstrap python3-pyqt6 + python3-pyqt6-devel-tools python3-wheel rsync uv yarn + libzstd-devel liblzma-devel" +makedepends="rust-std libzstd-devel sqlite-devel" +depends="lame mpv python3 python3-BeautifulSoup4 python3-decorator + python3-distro python3-Flask python3-Flask-Cors python3-jsonschema + python3-Markdown python3-orjson python3-packaging python3-protobuf + python3-pyqt6 python3-pyqt6-declarative python3-pyqt6-gui + python3-pyqt6-multimedia python3-pyqt6-network python3-pyqt6-printsupport + python3-pyqt6-webchannel python3-pyqt6-webengine python3-pyqt6-widgets + python3-pysocks python3-requests python3-send2trash python3-truststore + python3-typing_extensions python3-waitress qt6-multimedia qt6-svg" short_desc="Spaced repetition flashcard program" maintainer="Orphaned " license="AGPL-3.0-or-later" homepage="https://apps.ankiweb.net" -changelog="https://apps.ankiweb.net/docs/changes.html" -distfiles="https://apps.ankiweb.net/downloads/archive/anki-$version-source.tgz" -checksum=5a53760164c77d619f55107a13099cffe620566a7f610b61b6c4b52487f3bb89 +changelog="https://github.com/ankitects/anki/releases" +distfiles=" + https://github.com/ankitects/anki/archive/refs/tags/${version}.tar.gz + https://github.com/ankitects/anki-core-i18n/archive/${_anki_core_i18n_commit}.tar.gz>anki-core-i18n-${_anki_core_i18n_commit}.tar.gz + https://github.com/ankitects/anki-desktop-ftl/archive/${_anki_desktop_ftl_commit}.tar.gz>anki-desktop-ftl-${_anki_desktop_ftl_commit}.tar.gz" +checksum="1890f30f04996f87fee2449bd5903156f3e28ea715c0bd307f075777047df101 + 4900cc528c810b2849561afdd8d6a23653f92fb06562efd07b053bcde8f9fc13 + 346ef7dc2ab336d645ed8b4e2a47c7546f3b1f1e059a62f2d73d17a0b958c58f" -python_version=3 +skip_extraction=" + anki-core-i18n-${_anki_core_i18n_commit}.tar.gz + anki-desktop-ftl-${_anki_desktop_ftl_commit}.tar.gz" + +post_extract() { + vsrcextract -C ftl/core-repo "anki-core-i18n-${_anki_core_i18n_commit}.tar.gz" + vsrcextract -C ftl/qt-repo "anki-desktop-ftl-${_anki_desktop_ftl_commit}.tar.gz" + + # use system versions of rust and python + echo >rust-toolchain.toml + rm .python-version + + cargo auditable fetch --locked --target "${RUST_TARGET}" + cargo auditable fetch --locked --target "${XBPS_RUST_TARGET}" + + mkdir -p out +} + +pre_configure() { + yarn install --immutable --modules-folder out/node_modules --ignore-scripts + ln -sf out/node_modules ./ + python3 -m venv --system-site-packages --without-pip out/pyenv/ + + # build.rs::maybe_update_buildhash() in the build process complains without this. + echo "xbps000" > out/buildhash + + # Needed for build.ninja + mkdir -p .git +} + +do_configure() { + # Necessary for LTO + Rust crate "ring", see + # https://gitlab.archlinux.org/archlinux/packaging/packages/pacman/-/issues/20 + # https://github.com/briansmith/ring/issues/1444 + export CFLAGS+=' -ffat-lto-objects' + + # Use local binaries instead of downloading them + export PYTHON_BINARY=/usr/bin/python3 + export PROTOC_BINARY=/usr/bin/protoc + export NODE_BINARY=/usr/bin/node + export YARN_BINARY=/usr/bin/yarn + export UV_BINARY=/usr/bin/uv + + export RELEASE=2 # Optimized build + export OFFLINE_BUILD=1 # Do not download anything, disables git checks + + export CARGO_TARGET_DIR="$PWD/out/rust" + export CARGO_BUILD_TARGET="${RUST_TARGET}" + + # workaround the cc-rs mixing CFLAGS for host and target. + # https://github.com/rust-lang/cc-rs/issues/1469 + export CFLAGS_${RUST_BUILD//-/_}="${CFLAGS_host}" \ + CXXFLAGS_${RUST_BUILD//-/_}="${CXXFLAGS_host}" \ + LDFLAGS_${RUST_BUILD//-/_}="${LDFLAGS_host}" \ + CFLAGS_${RUST_TARGET//-/_}="${CFLAGS}" \ + CXXFLAGS_${RUST_TARGET//-/_}="${CXXFLAGS}" \ + LDFLAGS_${RUST_TARGET//-/_}="${LDFLAGS}" \ + CFLAGS="" CXXFLAGS="" LDFLAGS="" + + RUSTFLAGS= cargo auditable build -p runner --release --target "${XBPS_RUST_TARGET}" + RUSTFLAGS= cargo auditable run -p configure --release --target "${XBPS_RUST_TARGET}" +} + +do_build() { + # Stop uv from downloading their prefered python version + export UV_NO_MANAGED_PYTHON=1 + + # Use local binaries instead of downloading them + export PYTHON_BINARY=/usr/bin/python3 + export PROTOC_BINARY=/usr/bin/protoc + export NODE_BINARY=/usr/bin/node + export YARN_BINARY=/usr/bin/yarn + export UV_BINARY=/usr/bin/uv + + export CARGO_TARGET_DIR="$PWD/out/rust" + export CARGO_BUILD_TARGET="${RUST_TARGET}" + + if [ "$CROSS_BUILD" ]; then + case "${XBPS_TARGET_MACHINE}" in + aarch64*) export LIN_ARM64=1 ;; + esac + fi + + # workaround the cc-rs mixing CFLAGS for host and target. + # https://github.com/rust-lang/cc-rs/issues/1469 + export CFLAGS_${RUST_BUILD//-/_}="${CFLAGS_host}" \ + CXXFLAGS_${RUST_BUILD//-/_}="${CXXFLAGS_host}" \ + LDFLAGS_${RUST_BUILD//-/_}="${LDFLAGS_host}" \ + CFLAGS_${RUST_TARGET//-/_}="${CFLAGS}" \ + CXXFLAGS_${RUST_TARGET//-/_}="${CXXFLAGS}" \ + LDFLAGS_${RUST_TARGET//-/_}="${LDFLAGS}" \ + CFLAGS="" CXXFLAGS="" LDFLAGS="" + "./out/rust/${XBPS_RUST_TARGET}/release/runner" build -- wheels -v +} + +do_install() { + for file in out/wheels/*.whl; do + python3 -m installer --destdir="${DESTDIR}" "${file}" + done + + vinstall qt/launcher/lin/anki.desktop 644 usr/share/applications + vinstall qt/launcher/lin/anki.png 644 usr/share/pixmaps + vinstall qt/launcher/lin/anki.xpm 644 usr/share/pixmaps + vinstall qt/launcher/lin/anki.xml 644 usr/share/mime/packages + vman qt/launcher/lin/anki.1 +} post_install() { vlicense LICENSE