diff --git a/.github/workflows/hyprcosmic.yml b/.github/workflows/hyprcosmic.yml index b5b3720..8f56c31 100644 --- a/.github/workflows/hyprcosmic.yml +++ b/.github/workflows/hyprcosmic.yml @@ -131,24 +131,40 @@ jobs: - name: Install into a staging root run: just rootdir="$PWD/stage" install - # These assertions are the "three files, not seven" commit as something - # executable. Upstream's recipe wrote /usr/bin/cosmic-session and - # cosmic.desktop, which replaced the stock COSMIC session and left nothing - # to log into when the fork failed to start. The negative tests are the - # important half: it is the files that must NOT appear that made the old - # recipe dangerous. - - name: Assert it installs beside COSMIC, not over it + # Eight files: upstream's six, at upstream's paths, plus this fork's two. + # HyprCosmic replaces COSMIC rather than installing beside it, so nothing + # else on the machine provides the systemd target, the mimeapps list or + # the dconf profile -- a session that omits them starts, and then has no + # user target for the portals to attach to, which surfaces much later and + # much less clearly than a missing file would. + # + # Both session entries are asserted. Dropping cosmic.desktop would leave a + # machine whose only way in is the HyDE shell, and the last two lines are + # what stop the private libexec layout from creeping back. + - name: Assert it installs as the session, at upstream's paths run: | set -eux - test -x stage/usr/libexec/hyprcosmic/cosmic-session + test -x stage/usr/bin/cosmic-session test -x stage/usr/bin/start-hyprcosmic + test -x stage/usr/bin/start-cosmic test -f stage/usr/share/wayland-sessions/hyprcosmic.desktop - test ! -e stage/usr/bin/cosmic-session - test ! -e stage/usr/bin/start-cosmic - test ! -e stage/usr/share/wayland-sessions/cosmic.desktop - test ! -e stage/usr/share/applications/cosmic-mimeapps.list + test -f stage/usr/share/wayland-sessions/cosmic.desktop + test -f stage/usr/lib/systemd/user/cosmic-session.target + test -f stage/usr/share/applications/cosmic-mimeapps.list + test -f stage/usr/share/dconf/profile/cosmic + test ! -e stage/usr/libexec/hyprcosmic/cosmic-session find stage -type f -printf '%M %10s %P\n' + # Upstream rewrites DCONF_PROFILE to an absolute path in its own start + # script; this fork's searches for the profile at runtime instead. Both + # behaviours are deliberate, and the pair is easy to get backwards in a + # recipe that now installs both scripts. + - name: Assert the dconf rewrite hit start-cosmic and only start-cosmic + run: | + set -eux + grep -q 'DCONF_PROFILE=/usr/share/dconf/profile/cosmic' stage/usr/bin/start-cosmic + grep -q 'DCONF_PROFILE=cosmic$' stage/usr/bin/start-hyprcosmic + - uses: actions/upload-artifact@v4 with: name: cosmic-session-${{ matrix.distro }} diff --git a/Justfile b/Justfile index 8d9d32e..f4d0c6d 100644 --- a/Justfile +++ b/Justfile @@ -9,12 +9,6 @@ systemddir := usrdir / 'lib' / 'systemd' / 'user' sessiondir := usrdir / 'share' / 'wayland-sessions' applicationdir := usrdir / 'share' / 'applications' -# The fork's own binary directory. It stays out of bindir for the same reason -# the compositor does: the distro's cosmic-session owns /usr/bin/cosmic-session, -# and overwriting it would break the stock session -- the one you need to log -# into when this one will not start. -privdir := usrdir / 'libexec' / 'hyprcosmic' - default: build-release build-debug *args: @@ -36,39 +30,55 @@ clean-dist: clean # Installs files into the system # -# Three files, where upstream installs seven. The four that are gone are not -# oversights -- each is owned by the distro's own cosmic-session package, and -# writing them from here would make a HyprCosmic package conflict with it: +# All six of upstream's, at upstream's paths, plus this fork's two. HyprCosmic +# is a fork of COSMIC rather than something installed next to it, so a machine +# that installs this gets its cosmic-session from here and there is nothing else +# on disk to provide the target, the mimeapps list or the dconf profile. # -# data/start-cosmic -> /usr/bin/start-cosmic -# data/cosmic-session.target -> systemd user target -# data/cosmic-mimeapps.list -> the default-applications list -# data/dconf/profile/cosmic -> the dconf profile +# The two extra files are what make it a HyprCosmic install rather than a rebuilt +# COSMIC one: # -# None of them are things this fork changes, and a HyprCosmic session needs -# stock COSMIC installed regardless, for the greeter, the portals and the -# settings daemon. So it reads that package's copies rather than shipping rival -# ones. `data/cosmic.desktop` is dropped for the same reason and replaced by -# hyprcosmic.desktop, which is what puts the second entry on the greeter's menu -# instead of overwriting the first. +# data/start-hyprcosmic -> /usr/bin/start-hyprcosmic +# data/hyprcosmic.desktop -> a second entry on the greeter's menu # -# Upstream's `sed` over DCONF_PROFILE is deliberately not carried across. -# start-hyprcosmic searches /etc/dconf/profile and then XDG_DATA_DIRS for the -# profile and exports the bare name only if it finds one; rewriting a prefix -# into it would pin one location and break an administrator's /etc override. -# The script says so at the point where it does the search. +# Both session entries are installed, and both are served by these same +# binaries. That is deliberate. Replacing COSMIC does not have to mean removing +# its shell, and keeping cosmic.desktop costs one file while preserving the one +# property worth keeping from the old beside-install layout: if the HyDE shell +# will not start, there is still something on the greeter's menu that will. install: # main binary - install -Dm0755 {{ cargo-target-dir }}/release/cosmic-session {{ privdir }}/cosmic-session + install -Dm0755 {{ cargo-target-dir }}/release/cosmic-session {{ bindir }}/cosmic-session - # session start script + # session start scripts, this fork's and upstream's install -Dm0755 data/start-hyprcosmic {{ bindir }}/start-hyprcosmic + install -Dm0755 data/start-cosmic {{ bindir }}/start-cosmic - # session entry. Note that hyprcosmic.desktop names /usr/bin/start-hyprcosmic - # as an absolute Exec: a .desktop file has no way to interpolate a prefix, - # so building with prefix != /usr installs an entry that points at a path - # this recipe did not write. + # Upstream rewrites DCONF_PROFILE in its own start script to an absolute + # path under the build prefix. That is carried across for start-cosmic, + # because it is upstream's file and diverging from it here would be a change + # this fork has no reason to make. + # + # start-hyprcosmic is deliberately NOT sed'd. It searches /etc/dconf/profile + # and then XDG_DATA_DIRS and exports the bare profile name only if it finds + # one, which keeps an administrator's /etc override working; pinning a build + # prefix into it would break that. The script says so where it searches. + sed -i "s|DCONF_PROFILE=cosmic|DCONF_PROFILE={{ cosmic_dconf_profile }}|" {{ bindir }}/start-cosmic + + # systemd user target + install -Dm0644 data/cosmic-session.target {{ systemddir }}/cosmic-session.target + + # session entries. Note that both .desktop files name an absolute Exec under + # /usr/bin: a .desktop has no way to interpolate a prefix, so building with + # prefix != /usr installs entries pointing at paths this recipe did not write. install -Dm0644 data/hyprcosmic.desktop {{ sessiondir }}/hyprcosmic.desktop + install -Dm0644 data/cosmic.desktop {{ sessiondir }}/cosmic.desktop + + # default applications + install -Dm0644 data/cosmic-mimeapps.list {{ applicationdir }}/cosmic-mimeapps.list + + # dconf profile + install -Dm0644 data/dconf/profile/cosmic {{ rootdir }}/{{ cosmic_dconf_profile }} # Vendor Cargo dependencies locally vendor: diff --git a/data/start-hyprcosmic b/data/start-hyprcosmic index 5f4ebf6..3359093 100755 --- a/data/start-hyprcosmic +++ b/data/start-hyprcosmic @@ -56,15 +56,16 @@ if [[ -z "${HYPRCOSMIC_LOGIN_SHELL:-}" && -n "${SHELL:-}" && -x "${SHELL}" ]]; t esac fi -# The forked binaries, installed alongside rather than over the stock ones. +# The binaries. HyprCosmic replaces COSMIC rather than installing beside it, so +# these are the ordinary paths -- this fork's cosmic-session *is* the machine's +# cosmic-session, and there is no second copy under a private prefix. # -# Pointing at /usr/bin/cosmic-session here would be a silent no-op: the system -# binary has no profile module, so the session would come up as ordinary COSMIC -# and the gating would look broken. Installing to a private prefix instead of -# replacing /usr/bin also means `dnf update cosmic-session` cannot clobber the -# fork, and the stock session entry keeps working as the escape hatch. -HYPRCOSMIC_SESSION_BIN="${HYPRCOSMIC_SESSION_BIN:-/usr/libexec/hyprcosmic/cosmic-session}" -HYPRCOSMIC_COMP_BIN="${HYPRCOSMIC_COMP_BIN:-/usr/libexec/hyprcosmic/cosmic-comp}" +# Still named in variables rather than called bare. Two reasons: the check below +# can then say which path was missing, and both stay overridable from the +# environment, which is how the session is run out of a build tree without +# installing it. +HYPRCOSMIC_SESSION_BIN="${HYPRCOSMIC_SESSION_BIN:-/usr/bin/cosmic-session}" +HYPRCOSMIC_COMP_BIN="${HYPRCOSMIC_COMP_BIN:-/usr/bin/cosmic-comp}" if [[ ! -x "$HYPRCOSMIC_SESSION_BIN" ]]; then echo "start-hyprcosmic: $HYPRCOSMIC_SESSION_BIN is missing or not executable" >&2