Stop shelling out to pywal; use bread-theme's native extractor #6
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/drop-pywal"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Removes breadpaper's dependency on
wal(python-pywal):src/pywal.rsand thegenerate_palettewrapper.set()extracts the palette once viabread_theme::palette_from_image, writes it to bread-theme's global cache withwrite_global_palette, then reuses that same palette for every per-output file (previously it ranwal -i, then re-read~/.cache/walback out viaload_palette()).sync_focused_global()now writes the global palette from the per-output palette its caller already extracted, instead of re-running extraction.get()reads the last wallpaper fromcurrent.json(focused output, then the"*"entry, then any persisted output, in that order; documented on the function) instead of~/.cache/wal/wal.python-pywalfrombakery.tomlsystem_deps, and rewordsREADME.md,EVENTS.md, and the clap help text.Dependency note:
bread-themeis pointed at thefeature/native-palettebranch of bread-ecosystem (which carries the newpalette_from_image/write_global_paletteAPI) instead of a tag. This must be switched to the real release tag before merge, andCargo.lockneeds a refresh once that branch is pushed/released; it's left resolving to the previousv0.7.4lock entry for now since the branch isn't fetchable from a clean clone yet.Verified:
cargo build --release,cargo test --release(28 passed),cargo clippy --all-targets -- -D warnings,cargo fmt --check, all clean. Sincefeature/native-paletteisn't pushed yet, these were run with a temporary, uncommitted local path override to the in-progress bread-theme worktree, then reverted; the committedCargo.toml/Cargo.lockstate was not built against that override.Closes #5
Review: changes requested (not merging: depends on unreleased bread-theme)
CI is red:
check / check (push)fails on872596b. I reproduced it in a clean clone.cargo metadata --lockedfails with "cannot update the lock file" because the committed Cargo.lock still pins bread-theme at the old tag, while Cargo.toml points atbranch = "feature/native-palette". Without--locked, the clean clone builds, so the bread-theme bump itself compiles here (breadpaper has nostylesheet()call sites to update).Change requests
Cargo.toml:15to the releasetag = "vX.Y.Z"and commit the regeneratedCargo.lockfrom a build without any local[patch]override. CI must be green from a clean clone.src/lib.rs:36-44(set()) regenerates the shared stylesheet through the externalbread-theme reloadbinary. That binary re-reads the palette from the cache with its own copy ofload_palette. If the installed bread-theme CLI is older than the library breadpaper links, it reads~/.cache/wal/colors.jsonand not thepalette.jsonjust written, and the shared sheet goes out of sync with the per-output files. bakerybread_depshas no version floor to prevent that. Since the palette is already in hand, write the shared sheet in-process withtheme::write_shared_from(&palette), the same waysync_focused_global(src/lib.rs:163-167) does, and drop thereload_theme()call. The atomic rewrite of theme.css is what wakes the running apps. That also makes the global and focused paths consistent.IMAGE_EXTENSIONS(src/lib.rs:24) accepts webp, gif and bmp, but the current bread-theme branch only decodes png and jpeg.set()on a webp wallpaper applies it via awww, then fails atpalette_from_imageand leaves a stale palette. The fix belongs in bread-theme (#36). Add a test here once it lands, or reject formats bread-theme cannot decode invalidate()beforeapply_wallpaper, so a failure does not leave half-applied state.src/lib.rs:469: "never reaches awww/wal".Acceptance criteria as I read them (PAPER-5)
src/pywal.rsdeleted,generate_palettegone. Met.set()extracts once, writes the global cache and per-output files. Met (src/lib.rs:41-43,:78-82), apart from the stylesheet issue above.sync_focused_globalwrites the global palette from the palette it already has, with no second extraction. Met (src/lib.rs:163-167).get()reads current.json. Met (src/lib.rs:325-343). The focused output wins, then"*", then the first entry in BTreeMap order. The semantics change is reasonable and documented in the README. There is no unit test for the precedence; a test on aCurrentfixture would be cheap (the Hyprland lookup can stay untested).python-pywalremoved from bakery.toml, and README, EVENTS.md and the bakery description updated. Met.Rework happens on the existing branch
feature/drop-pywal, and this PR stays open. Do not open a second PR for PAPER-5.Pushed a follow-up commit addressing review:
set()now writes the shared stylesheet in-process viatheme::write_shared_from(&palette), no more shelling out tobread-theme reload. Confirmed nothing else relies on the external reload: it only re-rendered the shared sheet from the global cache, whichset()already keeps current viawrite_global_palette; per-output files are written separately in-process either way. Removed the now-deadtheme::reload()/reload_theme()wrapper.set()andset_on()now extract the palette before applying the wallpaper, so a decode failure leaves the old wallpaper and theme intact.resolve_current()(get()'s precedence logic split out) with tests covering focused output, "*" fallback, and first-persisted-entry fallback, stubbing the focused-output name instead of depending on a live Hyprland socket.Also refreshed Cargo.lock now that feature/native-palette is pushed (
cargo update -p bread-theme), verified withcargo build --lockedin a fresh clone (not a local path override). Still points at the branch, not a release tag; will need another lock refresh once bread-theme cuts its release.Verified: cargo build --release, cargo test --release (36 passed), cargo clippy --all-targets -- -D warnings, cargo fmt --check, all clean.
Correction: the test count above is wrong, it's 32 passed (28 existing plus the 4 new resolve_current tests), not 36.
Refreshed Cargo.lock again to bread-theme's latest feature/native-palette commit (3758f0c), since the branch got new commits after my previous refresh. Re-verified in a fresh clone: cargo build --release, cargo test --release (32 passed), cargo clippy --all-targets -- -D warnings, cargo fmt --check, all clean.
Second-round review: two small changes, plus the relock (not merging)
CI is green on
96526b9(run 140, fresh clone building bread-theme at 3758f0c), and the PR is mergeable.The round-1 items are resolved:
set()extracts beforeapply_wallpaper(src/lib.rs:34-47), and a decode failure now returns before anything changes.theme::write_shared_from(src/lib.rs:57). Thebread-theme reloadshell-out andtheme::reloadare gone.get()precedence is split intoresolve_currentwith four behavioural tests: focused entry,"*"fallback, first-entry fallback, and empty isErr.current.jsonin bos#52 ({"outputs":{"*": ...}}) deserialises intocurrent.rs'sCurrent, andget()returns it on a fresh install.Change requests
src/lib.rs:146-157(set_on) still half-applies in the other direction.theme::generate_for_outputwritespalettes/<output>.jsonandthemes/<output>.cssbeforewallpaper::apply_on. If awww fails (daemon not up, bad output name), that monitor recolours to the new palette while it keeps the old wallpaper, and current.json is not updated. A laterapplythen restores the old wallpaper next to the new palette. Extract withbread_theme::palette_from_image(&path)first, thenapply_on, then write the per-output files with the existingwrite_output_theme(output, &palette). That matchesset()'s order: extract, apply, write.README.md:19still listsbread-themeas a required$PATHbinary forset. set no longer execs anything but awww. Move bread-theme to a note: the bakery dependency is still useful for the CLI and other apps, but breadpaper does not need it on PATH.Cargo.toml:15frombranch = "feature/native-palette"to the release tag and commit the regenerated Cargo.lock. Merging #36 deletes that branch, so the current lock will not resolve in a fresh clone after that.For the user (not blocking this PR's code)
breadpaper is the first consumer that statically links bread-theme's ImageMagick- and IJG-derived extractor, while
bakery.tomlstill declareslicense_file = "LICENSE"(MIT). See the licensing section of Breadway/bread-ecosystem#36 (comment). The IJG licence wants an "based in part on the work of the Independent JPEG Group" statement in the documentation of executable-only distributions.Acceptance criteria (PAPER-5), as I read them
walsubprocess, palette extracted natively. Met (src/pywal.rsdeleted).set().set_on()still has the writes-before-apply ordering above.src/lib.rs:56-57,sync_focused_global).get()works without~/.cache/wal/wal. Met, with tests.system_deps. Met.Rework happens on the existing branch
feature/drop-pywal, and PR #6 stays open. Do not open a second PR for this key.Round-3 update, addressing the second-round review:
set_onnow extracts viabread_theme::palette_from_image(no side effects) beforewallpaper::apply_on, and writes the per-output theme files only after the wallpaper apply succeeds, matchingset()'s order. Anawwwfailure can no longer leave a monitor recoloured without the wallpaper changing.README.md:19: dropped the stale "bread-theme must be on $PATH" line.extractfeature (its licensing split movedpalette_from_image/generate_outputbehind it). Since this binary now statically links ImageMagick/libjpeg-turbo(IJG) code viabread-palette-extract, addedNOTICE,LICENSE-ImageMagick,LICENSE-libjpeg-turbo, abreadpaper noticesubcommand, and a README licence note. Cargo.toml license is nowMIT AND ImageMagick AND IJG.Cargo.lockagainst bread-theme's latestfeature/native-palettecommit (the crate split).Verified:
cargo build --locked,cargo test --locked(32 passed),cargo clippy --all-targets --locked -- -D warnings,cargo fmt --all -- --check, all clean.Still needed before merge: repin
Cargo.tomlfrom thefeature/native-palettebranch to the release tag once bread-ecosystem's release goes out, and relock again.Third-round review (round-3 commit
f835da5): licence packaging gap plus the repin (not merging)CI is green on
f835da5. Forgejo reports the PR as mergeable, but see the pin item below: it cannot land as it stands.What checks out
set_onordering (src/lib.rsset_on): extract withpalette_from_image(no side effects), thenwallpaper::apply_on, thenwrite_output_theme, then current.json. An awww failure no longer leaves the monitor recoloured. This matchesset(). Good.bread-thememust be on $PATH.features = ["gtk", "extract"]is the only consumer that needsextract, and it is the correct one.lint-pins.shpasses,cargo clippy --all-targets -D warningsis clean,cargo testpasses 32, the release build works,breadpaper noticeprints the NOTICE and both licences, andcargo treeshows bread-palette-extract linked.LICENSE-ImageMagickandLICENSE-libjpeg-turboare byte-identical to bread-palette-extract's copies.Change requests
bakery.tomlhaslicense_file = "LICENSE", and.forgejo/workflows/release.yml:44(and the dev/rc equivalents) copy onlysrc/LICENSE, which is MIT-only. NOTICE, LICENSE-ImageMagick and LICENSE-libjpeg-turbo never reach the user except throughbreadpaper notice. IJG clause 2 requires the accompanying documentation of an executable-only distribution to say "This software is based in part on the work of the Independent JPEG Group". ImageMagick License 4(a) requires giving recipients a copy of the licence, and 4(d) requires the NOTICE text in a NOTICE file, the docs, or a display "wherever such third-party notices normally appear". A hidden subcommand is at best arguable. Do what bread-theme did in #36: make the file thatlicense_filepoints at a combined text (MIT, then NOTICE, then both licences), either committed or concatenated in dev-release.yml, rc-release.yml and release.yml before the copy. Then the bakery package carries the terms, andbreadpaper noticebecomes the belt-and-braces copy.lint-pins.sh, which fails onbranch = "feature/native-palette"(Cargo.toml:20). Once bread-ecosystem#36 is merged and tagged, settag = "<that tag>"(keepfeatures = ["gtk", "extract"]), runcargo update -p bread-theme, and commit Cargo.toml and Cargo.lock. This cannot be done earlier: no existing tag has theextractfeature, so a committed lockfile cannot resolve against an older tag.Nit
bread_palette_extract::{NOTICE, LICENSE_*}underextract, sobreadpaper noticeprints the dependency's own text.Acceptance criteria (my reading)
get()reads current.json: met (resolve_current tests assert the precedence).Rework happens on the existing branch
feature/drop-pywal, and PR #6 stays open. Do not open a second PR for this key.f835da53647872f0bc43Round-4 update, addressing the third-round review (#issuecomment-1382):
bakery.toml'slicense_filealready pointed atLICENSEand the release workflows already copied it verbatim, so the only real gap was the file's content.LICENSEis now combined: breadpaper's own MIT text, thenNOTICE, thenLICENSE-ImageMagickandLICENSE-libjpeg-turboin full (including the IJG "based in part on the work of the Independent JPEG Group" statement), mirroring how bread-theme's ownLICENSEis assembled.breadpaper noticestays as the belt-and-braces copy.tests/license_matches_sources.rs, asserting the combinedLICENSEstill carries the ImageMagick and libjpeg-turbo texts verbatim plus the IJG sentence, so it can't silently drift fromLICENSE-ImageMagick/LICENSE-libjpeg-turbo/NOTICEagain.Not done, as instructed: no repin yet, since bread-ecosystem#36 hasn't tagged a release.
Cargo.tomlstill pointsbread-themeatbranch = "feature/native-palette"; once that PR lands and cuts a tag (targeted v0.8.0), this needstag = "v0.8.0"(keepingfeatures = ["gtk", "extract"]) and acargo update -p bread-theme+ committedCargo.lock. Flagging again here so it isn't missed at merge time, per the round-3 note.Verified:
cargo build --locked,cargo test --locked(36 passed: the existing 32 plus the 4 new licence tests),cargo clippy --all-targets --locked -- -D warnings,cargo fmt --all -- --check, all clean.Follow-up: two more things surfaced after rebasing onto origin/main.
Relocked
Cargo.lock. Rebasing onto main picked up bread-ecosystem#36's own round-4 rebase, which force-pushedfeature/native-paletteand rewrote the commit (c29a829) this branch'sCargo.lockhad pinned out of existence. A fresh clone'scargo build --lockedcould no longer resolve it. Rancargo update -p bread-themeto relock against the branch's current tip (4c51998);Cargo.tomlis untouched, stillbranch = "feature/native-palette". Verified from an actual fresh clone (not this worktree):cargo build --release --lockedandcargo test --release --locked(36 passed), both clean.CI is red, and it's expected, not a regression. The rebase also pulled in bread-ecosystem's ECO-38 dev-track
check.ymlrewrite that landed onorigin/mainsince the round-3 review: it now runslint-pins.sh --root srcbefore anything else, which hard-fails on anybranch = "..."git dependency pin,bread-theme's included. That's exactly the repin blocker the round-3 review already called out ("this cannot be done earlier: no existing tag has theextractfeature"). Reproduced locally:bash lint-pins.sh --root .fails onCargo.toml'sbread-themepin, in well under a second, matching the CI run's actual failure time. Everything downstream of that gate (clippy, build, test) is unaffected and passes, as shown above. This resolves itself the moment bread-ecosystem#36 tags a release and this branch repins to it, per the outstanding note.