From babfafa5e9051696e522b933e5a367beb3da1c24 Mon Sep 17 00:00:00 2001 From: Ryan Hughes Date: Wed, 27 May 2026 16:59:42 -0400 Subject: [PATCH] Split user defaults into skel seed, finalize, and resync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reorganizes Omarchy 4 around three layers for populating $HOME: Seed: omarchy-settings ships defaults to /etc/skel; useradd -m copies them on user creation Finalize: omarchy-finalize-user (renamed from omarchy-setup-user) handles only the runtime tweaks /etc/skel can't do — skill symlinks, xdg-user-dirs, default browser/mailto, vconsole→hypr keyboard sync, and install/user/all.sh Resync: omarchy-reinstall-configs is the explicit, destructive resync of /etc/skel into an existing user's $HOME Package-owned files move out of config/ into default/, where the omarchy-settings PKGBUILD installs them to real system paths: config/environment.d/fcitx.conf -> /usr/lib/environment.d/ config/fontconfig/fonts.conf -> /usr/share/fontconfig/conf.avail/ config/mimeapps.list -> /usr/share/applications/ config/omarchy.ttf -> /usr/share/fonts/omarchy/ config/systemd/user/*.service -> /usr/lib/systemd/user/ config/uwsm/default -> /usr/share/omarchy/default/uwsm/ config/uwsm/env -> /usr/share/uwsm/env.d/10-omarchy config/xdg-terminals.list -> /usr/share/xdg-terminal-exec/ omarchy-upgrade-to-4 grows a 'retire' action (renamed from 'move' to clarify nothing is copied — the system path is owned by the new package once the user's hash-matched ~/.config copy is removed). Mismatched copies are kept as backups so user overrides survive the upgrade. Other simplifications: - Single env bootstrap at default/bash/env-bootstrap sourced by /etc/profile.d/omarchy.sh, /etc/skel/.bashrc, /usr/share/uwsm/env.d/10-omarchy, and default/bash/envs. PATH prepend only in dev-link mode (production uses /usr/bin/omarchy-*). - omarchy-refresh-config reads from /etc/skel/.config so refresh means 'snap to skel'. - omarchy-reinstall-configs collapses to 'cp -af /etc/skel/. ~/' plus limine/plymouth/nvim refresh. - omarchy-font-set uses awk against our own 30-omarchy.conf instead of xmlstarlet; xmlstarlet dropped from omarchy-base.packages. - Defer user systemd enables (bt-agent, sleep-lock, recover-internal-monitor) to first-run via install/user/first-run/enable-user-units.sh; delete omarchy-user-systemctl-enable and the per-hardware install scripts that called it. - Wireplumber bluetooth-a2dp-autoconnect.conf moves to config/ so /etc/skel ships it; install/user/hardware/bluetooth.sh deleted. - Default terminal switched to foot.desktop. - docs/file-layout.md documents the three-layer model and the build-time repo→path map. --- AGENTS.md | 4 +- bin/omarchy | 1 + bin/omarchy-default-terminal | 3 +- ...archy-setup-user => omarchy-finalize-user} | 80 +--- bin/omarchy-first-run | 10 +- bin/omarchy-font-set | 109 +++-- bin/omarchy-refresh-config | 27 +- bin/omarchy-reinstall-configs | 16 +- bin/omarchy-upgrade-to-4 | 408 +++++++++++++++++- .../bt-agent.service | 1 - .../omarchy-sleep-lock.service | 1 - config/uwsm/env | 15 - .../bluetooth-a2dp-autoconnect.conf | 0 config/xournalpp/settings.xml | 4 +- .../applications}/mimeapps.list | 0 default/bash/env-bootstrap | 27 ++ default/bash/envs | 14 +- default/bashrc | 2 +- .../environment.d/10-omarchy-fcitx.conf | 0 .../fontconfig/conf.avail/30-omarchy.conf | 2 +- {config => default/fonts/omarchy}/omarchy.ttf | Bin .../systemd/user/bt-agent.service | 0 .../omarchy-recover-internal-monitor.service | 0 .../systemd/user/omarchy-sleep-lock.service | 0 {config => default}/uwsm/default | 0 default/uwsm/env.d/10-omarchy | 20 + .../hyprland-xdg-terminals.list | 2 +- docs/file-layout.md | 186 ++++++++ etc/profile.d/omarchy.sh | 9 +- install/omarchy-base.packages | 1 - install/user/all.sh | 2 - install/user/first-run/enable-user-units.sh | 15 + install/user/hardware/bluetooth.sh | 13 - .../user/hardware/recover-internal-monitor.sh | 1 - install/user/sleep-lock.sh | 7 - migrations/1779742224.sh | 9 - test/shell.d/bluetooth-test.sh | 2 +- test/shell.d/config-test.sh | 35 ++ test/shell.d/systemd-test.sh | 2 +- 39 files changed, 823 insertions(+), 205 deletions(-) rename bin/{omarchy-setup-user => omarchy-finalize-user} (54%) delete mode 120000 config/systemd/user/graphical-session.target.wants/bt-agent.service delete mode 120000 config/systemd/user/graphical-session.target.wants/omarchy-sleep-lock.service delete mode 100644 config/uwsm/env rename {default => config}/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect.conf (100%) rename {config => default/applications}/mimeapps.list (100%) create mode 100644 default/bash/env-bootstrap rename config/environment.d/fcitx.conf => default/environment.d/10-omarchy-fcitx.conf (100%) rename config/fontconfig/fonts.conf => default/fontconfig/conf.avail/30-omarchy.conf (96%) rename {config => default/fonts/omarchy}/omarchy.ttf (100%) rename {config => default}/systemd/user/bt-agent.service (100%) rename {config => default}/systemd/user/omarchy-recover-internal-monitor.service (100%) rename {config => default}/systemd/user/omarchy-sleep-lock.service (100%) rename {config => default}/uwsm/default (100%) create mode 100644 default/uwsm/env.d/10-omarchy rename config/xdg-terminals.list => default/xdg-terminal-exec/hyprland-xdg-terminals.list (85%) create mode 100644 docs/file-layout.md create mode 100755 install/user/first-run/enable-user-units.sh delete mode 100644 install/user/hardware/bluetooth.sh delete mode 100644 install/user/hardware/recover-internal-monitor.sh delete mode 100644 install/user/sleep-lock.sh delete mode 100644 migrations/1779742224.sh diff --git a/AGENTS.md b/AGENTS.md index 293234c1..bbca0b91 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -78,7 +78,7 @@ The ISO owns installation orchestration. This repo ships target-side setup comma - `bin/omarchy-setup-system` runs root-owned system setup during ISO finalization. - `bin/omarchy-setup-hardware` runs idempotent hardware-specific setup and is called by `omarchy-setup-system`. -- `bin/omarchy-setup-user` runs user setup for the initial user and future users. +- `bin/omarchy-finalize-user` runs the per-user runtime finalization (skill symlinks, xdg-user-dirs, mime defaults, `install/user/all.sh`). Shipped user defaults are seeded by `/etc/skel` from `omarchy-settings`, not by this command. `bin/omarchy-reinstall-configs` is the explicit destructive resync of those defaults into an existing user's `$HOME`. - leaf scripts under `install/` are sourced by `run_logged $OMARCHY_INSTALL/path/to/script.sh` and intentionally do not have shebangs. - avoid `exit` in sourced setup scripts unless intentionally aborting setup. - use `$OMARCHY_INSTALL` and `$OMARCHY_PATH` instead of hard-coded Omarchy paths. @@ -171,7 +171,7 @@ To copy a default config to user config with automatic backup: omarchy-refresh-config hypr/hyprlock.conf ``` -This copies `$OMARCHY_PATH/config/hypr/hyprlock.conf` to `~/.config/hypr/hyprlock.conf`. +This copies `/etc/skel/.config/hypr/hyprlock.conf` to `~/.config/hypr/hyprlock.conf`. # Migrations diff --git a/bin/omarchy b/bin/omarchy index c54fc84c..2c8433f9 100755 --- a/bin/omarchy +++ b/bin/omarchy @@ -39,6 +39,7 @@ GROUP_DESCRIPTIONS[clipboard]="Clipboard helpers" GROUP_DESCRIPTIONS[cmd]="Command and shortcut helpers" GROUP_DESCRIPTIONS[config]="System configuration helpers" GROUP_DESCRIPTIONS[debug]="Diagnostics and support logs" +GROUP_DESCRIPTIONS[finalize]="Finalize user setup" GROUP_DESCRIPTIONS[default]="Default application selection" GROUP_DESCRIPTIONS[dev]="Omarchy development tools" GROUP_DESCRIPTIONS[dns]="DNS resolver configuration" diff --git a/bin/omarchy-default-terminal b/bin/omarchy-default-terminal index af0563ca..ca0ee1d3 100755 --- a/bin/omarchy-default-terminal +++ b/bin/omarchy-default-terminal @@ -5,7 +5,8 @@ # omarchy:examples=omarchy default terminal ghostty | omarchy default terminal kitty if (($# == 0)); then - desktop_id=$(grep -vE '^($|#)' ~/.config/xdg-terminals.list 2>/dev/null | head -n 1) + desktop_id=$(xdg-terminal-exec --print-id 2>/dev/null || true) + desktop_id=${desktop_id%%:*} case "$desktop_id" in Alacritty.desktop) echo "alacritty" ;; foot.desktop) echo "foot" ;; diff --git a/bin/omarchy-setup-user b/bin/omarchy-finalize-user similarity index 54% rename from bin/omarchy-setup-user rename to bin/omarchy-finalize-user index f4651d10..2dc32c3d 100755 --- a/bin/omarchy-setup-user +++ b/bin/omarchy-finalize-user @@ -1,29 +1,31 @@ #!/bin/bash -# omarchy:summary=Set up Omarchy for the current user (~/.config, ~/.local, etc.) -# omarchy:group=setup -# omarchy:examples=omarchy setup user | omarchy setup user --force +# omarchy:summary=Finalize Omarchy user setup (runtime tweaks /etc/skel can't do) +# omarchy:group=finalize +# omarchy:examples=omarchy finalize user | omarchy finalize user --force set -euo pipefail usage() { cat <&2 + echo "Error: run omarchy-finalize-user as the user being configured, not as root." >&2 exit 1 fi @@ -53,11 +55,11 @@ while (($#)); do done state_dir="$HOME/.local/state/omarchy" -marker="$state_dir/setup-user.done" +marker="$state_dir/finalize-user.done" mkdir -p "$state_dir" if [[ -f $marker && $force -eq 0 ]]; then - echo "User setup already complete (rerun with --force to refresh)." + echo "User finalization already complete (rerun with --force to refresh)." exit 0 fi @@ -79,60 +81,14 @@ else } fi -omarchy_user_systemctl_enable() { - local unit="$1" unit_path target - local -a targets=() - - if systemctl --user enable "$unit" >/dev/null 2>&1; then - return 0 - fi - - # ISO chroot setup has no running user systemd manager. Enabling a user unit - # is just creating the [Install] WantedBy symlinks, so do that directly. - unit_path="$HOME/.config/systemd/user/$unit" - if [[ -f $unit_path ]]; then - mapfile -t targets < <(awk -F= ' - /^\[Install\]/ { in_install=1; next } - /^\[/ { in_install=0 } - in_install && $1 == "WantedBy" { - n=split($2, values, /[[:space:]]+/) - for (i = 1; i <= n; i++) if (values[i] != "") print values[i] - } - ' "$unit_path") - fi - ((${#targets[@]})) || targets=(default.target) - - for target in "${targets[@]}"; do - mkdir -p "$HOME/.config/systemd/user/$target.wants" - ln -sfn "../$unit" "$HOME/.config/systemd/user/$target.wants/$unit" - done -} -export -f omarchy_user_systemctl_enable - -mkdir -p ~/.config -cp -R "$OMARCHY_PATH/config/." ~/.config/ -cp "$OMARCHY_PATH/default/bashrc" ~/.bashrc -echo '[[ -f ~/.bashrc ]] && . ~/.bashrc' > ~/.bash_profile - +# Dev-aware skill symlinks. Cannot live in /etc/skel because OMARCHY_PATH may +# point at a dev checkout (omarchy dev link) where the target differs. mkdir -p ~/.agents/skills ~/.claude/skills ~/.codex/skills ~/.pi/agent/skills ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.agents/skills/omarchy ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.claude/skills/omarchy ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.codex/skills/omarchy ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.pi/agent/skills/omarchy -mkdir -p ~/.local/state/omarchy/toggles/hypr -cp "$OMARCHY_PATH/default/hypr/toggles/flags.lua" ~/.local/state/omarchy/toggles/hypr/ - -mkdir -p "$HOME/.local/share/nautilus-python/extensions" -cp "$OMARCHY_PATH/default/nautilus-python/extensions/localsend.py" \ - "$HOME/.local/share/nautilus-python/extensions/" -cp "$OMARCHY_PATH/default/nautilus-python/extensions/transcode.py" \ - "$HOME/.local/share/nautilus-python/extensions/" - -mkdir -p ~/.config/omarchy/branding -cp "$OMARCHY_PATH/icon.txt" ~/.config/omarchy/branding/about.txt -cp "$OMARCHY_PATH/logo.txt" ~/.config/omarchy/branding/screensaver.txt - mkdir -p ~/Downloads ~/Pictures ~/Videos ~/.config/gtk-3.0 xdg-user-dirs-update --set TEMPLATES "$HOME" xdg-user-dirs-update --set PUBLICSHARE "$HOME" @@ -174,4 +130,4 @@ if (( first_install )); then fi touch "$marker" -echo "User setup complete." +echo "User finalization complete." diff --git a/bin/omarchy-first-run b/bin/omarchy-first-run index 7cc4f1c8..924eeda8 100755 --- a/bin/omarchy-first-run +++ b/bin/omarchy-first-run @@ -15,12 +15,12 @@ USAGE } force=0 -setup_user_args=() +finalize_user_args=() while (($#)); do case "$1" in --force) force=1 - setup_user_args+=(--force) + finalize_user_args+=(--force) shift ;; -h|--help) @@ -35,7 +35,7 @@ while (($#)); do esac done -omarchy-setup-user "${setup_user_args[@]}" || true +omarchy-finalize-user "${finalize_user_args[@]}" || true state_dir=~/.local/state/omarchy mkdir -p "$state_dir" @@ -97,8 +97,8 @@ if [[ ! -f $USER_MARKER || $force -eq 1 ]]; then run_first_run_step "install Voxtype post-update hook" \ omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/install-voxtype.hook" - run_first_run_step "recover internal monitor" \ - bash "$OMARCHY_PATH/install/user/hardware/recover-internal-monitor.sh" + run_first_run_step "enable user systemd units" \ + bash "$OMARCHY_PATH/install/user/first-run/enable-user-units.sh" run_first_run_step "set GNOME theme" \ bash "$OMARCHY_PATH/install/user/first-run/gnome-theme.sh" run_first_run_step "set GTK primary paste" \ diff --git a/bin/omarchy-font-set b/bin/omarchy-font-set index 090d9774..c0768f89 100755 --- a/bin/omarchy-font-set +++ b/bin/omarchy-font-set @@ -4,50 +4,87 @@ # omarchy:args= # omarchy:examples=omarchy font list | omarchy font set "CaskaydiaMono Nerd Font" -font_name="$1" +usage() { + echo "Usage: omarchy-font-set " +} -if [[ -n $font_name ]]; then - if fc-list | grep -iq "$font_name"; then - if [[ -f ~/.config/alacritty/alacritty.toml ]]; then - sed -i "s/family = \".*\"/family = \"$font_name\"/g" ~/.config/alacritty/alacritty.toml - fi +font_name="${1:-}" +omarchy_root="${OMARCHY_PATH:-/usr/share/omarchy}" - if [[ -f ~/.config/kitty/kitty.conf ]]; then - sed -i "s/^font_family .*/font_family $font_name/g" ~/.config/kitty/kitty.conf - pkill -USR1 kitty - fi +case "$font_name" in + -h|--help) + usage + exit 0 + ;; + "") + usage >&2 + exit 1 + ;; +esac - if [[ -f ~/.config/ghostty/config ]]; then - sed -i "s/font-family = \".*\"/font-family = \"$font_name\"/g" ~/.config/ghostty/config - pkill -SIGUSR2 ghostty - fi +if ! fc-list | grep -Fqi -- "$font_name"; then + echo "Font '$font_name' not found." + exit 1 +fi - if [[ -f ~/.config/foot/foot.ini ]]; then - sed -i "s/^font=.*/font=$font_name:size=9/g" ~/.config/foot/foot.ini - fi +if [[ -f ~/.config/alacritty/alacritty.toml ]]; then + sed -i "s/family = \".*\"/family = \"$font_name\"/g" ~/.config/alacritty/alacritty.toml +fi - # fontconfig is the canonical source of truth — the omarchy shell, Qt - # apps, and anything else that resolves "monospace" all read from here. - xmlstarlet ed -L \ - -u '//match[@target="pattern"][test/string="monospace"]/edit[@name="family"]/string' \ - -v "$font_name" \ - ~/.config/fontconfig/fonts.conf +if [[ -f ~/.config/kitty/kitty.conf ]]; then + sed -i "s/^font_family .*/font_family $font_name/g" ~/.config/kitty/kitty.conf + pkill -USR1 kitty +fi - omarchy-restart-shell +if [[ -f ~/.config/ghostty/config ]]; then + sed -i "s/font-family = \".*\"/font-family = \"$font_name\"/g" ~/.config/ghostty/config + pkill -SIGUSR2 ghostty +fi - if pgrep -x ghostty; then - omarchy-notification-send -g  "You must restart Ghostty to see font change" - fi +if [[ -f ~/.config/foot/foot.ini ]]; then + sed -i "s/^font=.*/font=$font_name:size=9/g" ~/.config/foot/foot.ini +fi - if pgrep -x foot; then - omarchy-notification-send -g  "You must restart Foot to see font change" - fi - - omarchy-hook font-set "$font_name" - else - echo "Font '$font_name' not found." +# fontconfig is the canonical source of truth — the omarchy shell, Qt apps, +# and anything resolving "monospace" all read from here. The shipped default +# is package-owned; create a user override only when the user changes fonts. +fontconfig_file="$HOME/.config/fontconfig/fonts.conf" +if [[ ! -f $fontconfig_file ]]; then + fontconfig_default="$omarchy_root/default/fontconfig/conf.avail/30-omarchy.conf" + if [[ ! -f $fontconfig_default ]]; then + echo "Default fontconfig file not found: $fontconfig_default" >&2 exit 1 fi -else - echo "Usage: omarchy-font-set " + mkdir -p "$(dirname "$fontconfig_file")" + cp "$fontconfig_default" "$fontconfig_file" fi + +# We own the markup in 30-omarchy.conf, so the monospace block is predictable: +# the FAMILY immediately after monospace is +# the family we're replacing. +tmp=$(mktemp) +if ! awk -v new_font="$font_name" ' + in_mono && /[^<]*<\/string>/ { + sub(/[^<]*<\/string>/, "" new_font "") + in_mono = 0 + } + /monospace<\/string>/ { in_mono = 1 } + { print } +' "$fontconfig_file" >"$tmp"; then + rm -f "$tmp" + echo "Failed to update $fontconfig_file" >&2 + exit 1 +fi +mv "$tmp" "$fontconfig_file" + +omarchy-restart-shell + +if pgrep -x ghostty; then + omarchy-notification-send -g "You must restart Ghostty to see font change" +fi + +if pgrep -x foot; then + omarchy-notification-send -g "You must restart Foot to see font change" +fi + +omarchy-hook font-set "$font_name" diff --git a/bin/omarchy-refresh-config b/bin/omarchy-refresh-config index e4c99411..a4dbe6b3 100755 --- a/bin/omarchy-refresh-config +++ b/bin/omarchy-refresh-config @@ -1,37 +1,37 @@ #!/bin/bash -# omarchy:summary=Copies the named config from $OMARCHY_PATH/config/X/Y/Z -> ~/.config/X/Y/Z. +# omarchy:summary=Copy a shipped user config from /etc/skel/.config into ~/.config (backs up your version). # omarchy:args= -config_file=$1 +config_file=${1:-} if [[ -z $config_file ]]; then cat <&2 + exit 1 +fi + mkdir -p "$(dirname "$user_config_file")" if [[ -f $user_config_file ]]; then - # Create preliminary backup - cp -f "$user_config_file" "$backup_config_file" 2>/dev/null + cp -f "$user_config_file" "$backup_config_file" + cp -f "$default_config_file" "$user_config_file" - # Replace config with new default - cp -f "$default_config_file" "$user_config_file" 2>/dev/null - - # Compare and delete/inform accordingly if cmp -s "$user_config_file" "$backup_config_file"; then rm "$backup_config_file" else @@ -39,6 +39,5 @@ if [[ -f $user_config_file ]]; then diff "$user_config_file" "$backup_config_file" || true fi else - # Config file did not exist already - cp -f "$default_config_file" "$user_config_file" 2>/dev/null + cp -f "$default_config_file" "$user_config_file" fi diff --git a/bin/omarchy-reinstall-configs b/bin/omarchy-reinstall-configs index 212358b4..f89b6531 100755 --- a/bin/omarchy-reinstall-configs +++ b/bin/omarchy-reinstall-configs @@ -1,17 +1,23 @@ #!/bin/bash -# omarchy:summary=Reset all Omarchy user configs to the defaults -# omarchy:requires-sudo=true +# omarchy:summary=Reset Omarchy user configs and shipped defaults in $HOME (destructive) -set -e +set -euo pipefail if (( EUID == 0 )); then echo "Error: This script should not be run as root" exit 1 fi -echo "Resetting all Omarchy configs" -omarchy-setup-user --force +echo "Resetting Omarchy user configs to shipped defaults..." + +# /etc/skel is the same tree useradd -m copies to seed a fresh user's $HOME. +# Replaying it over an existing user resyncs every package-shipped user +# default in one pass: .bashrc, .config/**, .local/share/applications, +# nautilus-python extensions, branding, hypr toggles, and migration markers. +# Trailing dot copies dotfiles; the shell wouldn't glob them with /etc/skel/*. +cp -af /etc/skel/. ~/ + omarchy-refresh-limine omarchy-refresh-plymouth diff --git a/bin/omarchy-upgrade-to-4 b/bin/omarchy-upgrade-to-4 index 739cbc50..1fc689b9 100755 --- a/bin/omarchy-upgrade-to-4 +++ b/bin/omarchy-upgrade-to-4 @@ -1027,14 +1027,390 @@ root=/usr/share/omarchy state_dir="$HOME/.local/state/omarchy" mkdir -p "$state_dir" "$HOME/.config" -if [[ -d $root/config ]]; then - cp -R "$root/config/." "$HOME/.config/" +file_sha256() { + sha256sum "$1" | awk '{print $1}' +} + +known_config_default_hashes() { + cat <<'DEFAULT_HASHES' +# actionrelative ~/.config pathsha256 +# refresh: hash-matched shipped defaults +refresh alacritty/alacritty.toml d43ab27e10ba1fd0505d50fe374b9bd02fa2e1d888fe2252c5208542fe5ddc8f +refresh alacritty/alacritty.toml 4e627909552ceebc80f5839955a09a7f804c501fee9a1fe76e13d95ad6cf5030 +refresh alacritty/alacritty.toml 73dc34be744039613ef522aab84c27468b61ff13d7bc0ed2d57a83904e13f613 +refresh alacritty/alacritty.toml e25fae44db040d97714cf4ca3d77e48f0ae32fed9e02e6b3db9ad4d705bdaed5 +refresh alacritty/alacritty.toml 999562ef35642910bec05c2444c3acdcd6e29bc60ec541529d9c69a20cad5c88 +refresh alacritty/alacritty.toml 8bf6dee79e634949617cd7acdd2756da52f7c3031b8eac98a7948f2fef0cf07e +refresh alacritty/alacritty.toml e4d201b6b9afd2f591d64f98eb50eb19247b8b839c2eaacfe2623628203c486f +refresh autostart/org.fcitx.Fcitx5.desktop a0260e7f35579a73f77e257e9e3795abd8b33119a17b931ca6016a07036e1670 +refresh btop/btop.conf e6b86ddda073e06bf64cfbbde9652f9335171d8ca8c622e617478a3c696a6a3d +refresh btop/btop.conf 7f4122f2ed5f4c95489950cce2c0b192e19ae6fa74b0666d25e0b10040b2cee8 +refresh btop/btop.conf 4e17dd28c43948af48a408ed9b0901c008e57dfe3b8fcf09649ec10f28746137 +refresh chromium/Default/Preferences 67aef8ae3a6e0ee1180057198f47f2ea412ea1f01051d77edce4c465fb83d887 +refresh chromium-flags.conf 3a8fe5b85bc42b27f5a0f36f3b674dc8e22a7d670a6aabbdc4f2d4057b97a1d4 +refresh chromium-flags.conf 3d52925a48ac3704f9427ecec70310d9c89be5442c41ece183122a9246837be4 +refresh chromium-flags.conf 4bc8710615d2151464e9bd6d1123fbfbb8f56dea4cf0568320bc7b50d24ad205 +refresh chromium-flags.conf 1df1a5282f9525bfbb97a697c8169c08c1adb2b5a4de5ae94d84df7b4a78f2fc +refresh chromium-flags.conf 0408c524892830f5cf43e94c389b897cbc093ede312f49a4627bfabf692653c2 +refresh fastfetch/config.jsonc 6adebf87d93902fb4bc68824a8e7c71e482846af23fea199e489c5496f791590 +refresh fastfetch/config.jsonc fe61d9f7cfac800adb7bd21f75f1bfcca266c609b6efa02a6e25303ac192e86e +refresh fastfetch/config.jsonc 62fa26fa5fb8e11d31c5ec9f3a53b9b6b1124b29134b19329a092878ff624581 +refresh fastfetch/config.jsonc 22565532d139ab8c2ddb21dcfe56460dc9f2f8a712b8d29f125c1c8b29beca37 +refresh fastfetch/config.jsonc b65cb9ca36eed45929bfc35443762b14957d3847f6bed361a338224a87450e3a +refresh fastfetch/config.jsonc 3d153225131d3031b99b2e1a07e84d22cd0e51fcae1e701b08f6b6a558bc7a9c +refresh fastfetch/config.jsonc 404d0273c380cfdad4a037fa87202fc1d96be178c867e8a9d27b0a772f6e2fa1 +refresh fastfetch/config.jsonc 4a98ff77ed46109d08ef7301249ea6823d1abba6c39c0871680feebf96620bf2 +refresh fastfetch/config.jsonc c827c3a24f64c418d309244a8a967def0c522d824addf65d8ee0741afbc970bd +refresh fastfetch/config.jsonc c909b43ba000887cd418d9eaf98c1c9c5ba938aa27f9246cf8fa5662946c4e87 +refresh fastfetch/config.jsonc b2e5757851f0703edb8bcfc4b51a00bf5e303c1df26b8c63e6b7df6be4ead4ed +refresh fcitx5/conf/clipboard.conf 2d53b40811ee7ceb71c7db0422a3ed733647f389379a57dbf2915d522dff4193 +refresh fcitx5/conf/xcb.conf f5cf059182c4361fa7b16d5149f20a09eb1e0915f4463ba60dae626b86df7d9c +refresh foot/foot.ini 52e30647172522459b2179af714c19b62a35fe11bc23c49839fda5dca3253e84 +refresh foot/foot.ini ac16453a4b4ebc997ff6732e7e4448dc759c25587fdb8aa1d1a7eee92b518987 +refresh ghostty/config ed589d69296f5aa083e4dba43fc3d40cfbe2f6d10b382f3d0dc2ff76d5ec8fe5 +refresh ghostty/config 2832c9c27cdcd735e913d538c3c61005fd90e909541bdcb746bb454851ae79ca +refresh ghostty/config 8200bc34b7ced8170d512c619f0408ac7dd7d7b4e64021ac66393d8a8bf1d951 +refresh ghostty/config 006fbe4048de02fc040eeefd0974081c6f7df5dae419f8d542fc1adf08b0d6fb +refresh ghostty/config e55a409a490d4f80c19c9242a59db8e00e271e01feddb8fda6a5a7102d39af20 +refresh ghostty/config b65e4903813d442a25540eef5a24313121c640a57114ee3d76d1ec7408d86b27 +refresh ghostty/config 4e6ccba3d0584832cedf22713842f8ce7eca383c2ea3bfe61286d2b8df73f3fe +refresh git/config 3e1bdf77aa65b7bb412cc25c02bac4734e98c10e4a63815b98737bf817b6f682 +refresh hypr/hyprsunset.conf 3ac2e9fe716fb8c612f07ca608ba7eee491921c2386118aae54ff9c8121726f2 +refresh hypr/hyprsunset.conf e6fa7d909a90b64df7f75e8842bc2541e75463a47bbc7213ec79a56364f563f2 +refresh hypr/hyprsunset.conf afe595d9d31574bde0f3ab8f7d370d0710bc188d6e5643f73255ffa7a202b647 +refresh hypr/hyprsunset.conf 3042e4a923030239f4edf7b1943f41f4ed57107550177130c96f3b215b226e22 +refresh hypr/xdph.conf 637899cd3926c4b8c758d3cb812cc1e7ac7643aca83a8e5030208234d064c839 +refresh hypr/xdph.conf 2fded88a27b89f33cbc2b64a1258117df74b591f39a84c78ec3504a7d3b09136 +refresh hyprland-preview-share-picker/config.yaml cb7f8768566ce41f8b09249b504ea8f6dbd6ed830637eef24c4e94e94486d113 +refresh hyprland-preview-share-picker/config.yaml cf88364e497e4af2adaff9a0b7ca12227d29f831bc7e18846dd8f03bf4c618a8 +refresh imv/config 58fd37d4862eb484d50c2c0cc507836e685a776d8da8dd9f20bd894809c31cd6 +refresh imv/config 569b52b9614a78be67ce9f0a828ff1a7a73e4741d4751577ec6b247ab78e29ea +refresh imv/config 832b19821b4c69f9381aea6902b1b80c5682c30091e6d4a59493c8edf827bf72 +refresh kitty/kitty.conf 69d6cbd2f8adcaec09407b5fb71ec7956cd510f6d64c36600ab7f7e7d3812cc6 +refresh kitty/kitty.conf 6c5fe293bb92b1ea5fd955afcec126597ae0a665395db1d38b9beb6461c587d1 +refresh kitty/kitty.conf 68779240358653a03ede95c4c872d94e3ab3742cf64a982b17e94f42aa2b74d4 +refresh kitty/kitty.conf 9599cfd1f1fbd7e14fe1ba48196137be3cf8bcfa95f6c24d15d8053d88f73f0a +refresh kitty/kitty.conf ea3bc5e353f7312d774362310f7c511584efd6076c163b4cad1a9cc05c0f80ab +refresh kitty/kitty.conf 8984216fe0c0d006b969a7494dd4aad79ac78e9d15bd7a82ccbf5f10eac48fa6 +refresh lazygit/config.yml e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 +refresh obsidian/user-flags.conf 6c00f4daeff2b018bda247151a8edee44115273f554cfda00909bc5e56a3ae85 +refresh omarchy/hooks/battery-low.d/play-warning-sound.sample 9623f5534cd52f76a51cfbb4e8a0699a550bf7f0f5f2ff54a1c78534d907fdf1 +refresh omarchy/hooks/font-set.d/show-font-notification.sample d28090fd796b02fa799dcf7160e46ce9fc8d7a17b476ef87639d0b83a347dc37 +refresh omarchy/hooks/post-boot.d/weather.sample fe37567a09046f1e4fcff9a9c74e4a036270cdf6da73dcc5cd3aa617f9a7c2ba +refresh omarchy/hooks/post-update.d/show-update-notification.sample 7995adc93a0ac6cd1afcd7ed9ac6d0ff058751ce4df4594aa78855603a613815 +refresh omarchy/hooks/theme-set.d/show-theme-notification.sample b9d6754d95057bdb2f37595fd2f40055872118cb2f442bdc7b0b900317bac332 +refresh omarchy/themed/alacritty.toml.tpl.sample ea5889bf79e273aa9cf1e7a1b2916dae7751fc0dced2cd53af36a2ebeecb4f1e +refresh omarchy/themed/alacritty.toml.tpl.sample a05d015227a406470b571d9d8f372eb8042df94b32cf746e71fd2f513c9880ac +refresh opencode/opencode.json 3806450805c8661a729c46aea325826e9ee7d158d650c9d750f5d0a763ec2c03 +refresh opencode/opencode.json fb067af039252d48ef5b5c573a5e12c17357af4324b218aca5efa36f882846dd +refresh starship.toml b17c9b5f096fc125e97050e359171c6011d6b3c7d7e9ac28f630e75b4d4bb9db +refresh tmux/tmux.conf 345abaa3f128529abbbe4da3a24c227170c9679fb0af1f3d87eb15959e183219 +refresh tmux/tmux.conf 93088311b8b67eb10ede3040b55e81193ff43fe16c5b2a6e3799300e00f39e3d +refresh tmux/tmux.conf 02d7c3914b73b8fec139316b9e1e88a40764617c6f4f1b6a3c05ad9c4a68b944 +refresh tmux/tmux.conf 6633a3c59441087fdead8c30601e50c39fc7e74a66a32514296657332ff6cde9 +refresh tmux/tmux.conf 473abae53d3aa7da59be65cc6301a15f6cc878045ae3f4c5e180ee013a0a04a7 +refresh tmux/tmux.conf bf881713284aa2cc6722a199e42d57c005ae5922ef4eb6305593ead09b13ca7c +refresh Typora/themes/ia_typora.css 8bb2493c1dc24c8217c35ce9c0d29054b3733316923a0ddd2e63908b11ec073e +refresh Typora/themes/ia_typora_night.css ff3d670351fdaf64aca339fbb94453c4962feae4705be9ed7ff31237e6da5791 +refresh Typora/themes/ia_typora_night.css d3708c850dcedf2ec210454c38bd1fa19b390e51bfce42ebac73d5f469aa1462 +refresh xournalpp/settings.xml 47eafeeb3c246af1a5fb2cd1d87a748ce127d13410c351194c5d89bbaefb623d +refresh xournalpp/settings.xml 1c1a9efbf1b6dc7813bf3440fd5bf8409fc283e8d0192ca297dc36a10e12c846 +# retire: nothing is actually copied. The new package owns the file at the +# system path below (shipped by omarchy-settings / omarchy-limine), so once +# the user's hash-matched copy in ~/.config is removed, the system path takes +# effect via the usual XDG/fontconfig/systemd lookup order. User overrides +# (hash mismatch) are kept active as backups. +# Legacy ~/.config path -> package-owned destination (where the file now lives): +# environment.d/fcitx.conf -> /usr/lib/environment.d/10-omarchy-fcitx.conf +# fontconfig/fonts.conf -> /usr/share/fontconfig/conf.avail/30-omarchy.conf +# mimeapps.list -> /usr/share/applications/mimeapps.list +# omarchy.ttf -> /usr/share/fonts/omarchy/omarchy.ttf +# systemd/user/bt-agent.service -> /usr/lib/systemd/user/bt-agent.service +# systemd/user/omarchy-recover-internal-monitor.service -> /usr/lib/systemd/user/omarchy-recover-internal-monitor.service +# systemd/user/omarchy-sleep-lock.service -> /usr/lib/systemd/user/omarchy-sleep-lock.service +# uwsm/default -> /usr/share/omarchy/default/uwsm/default +# uwsm/env -> /usr/share/uwsm/env.d/10-omarchy +# xdg-terminals.list -> /usr/share/xdg-terminal-exec/hyprland-xdg-terminals.list +retire environment.d/fcitx.conf faacbd703a8f797013968b235fec6289a9c921d3ec7b7f8b4e1cd24392f68b9c +retire environment.d/fcitx.conf 8b077b6ea2594dc1d4b57592a3bc62703df4959e86b93ea0fc488b6686309095 +retire fontconfig/fonts.conf 7db33b0f8673f71f42604255cad222194294cd401315fecde6b83151eecebe91 +retire fontconfig/fonts.conf f35b5b4bd0d8d3926f5d9a49ca791fc66b00793786420508d4a4c41ae9ccbefc +retire fontconfig/fonts.conf 6dec98b539388b95ecfdb3c7ab951001c712820eb0581002832cb7bfdde1a654 +retire fontconfig/fonts.conf 3545f6c5a8c1465df7a4e251b3c2047d4ba03654c86636794f64cb0d8ea8ef63 +retire fontconfig/fonts.conf 0f085b449f1cbe8eda3b59a6235bf2a3ddb6e982ab5d22fa642248916e63bafc +retire mimeapps.list 3b574cef135b5deb7a8a0c7e17139037cf1fe155300e3809f60bed0e04120975 +retire omarchy.ttf e55e67119e82f56f92d90cbf54b7ccc1b2946b32c535a29370439d7ef5215966 +retire systemd/user/bt-agent.service 0406b577a1225dc2a9f86638d3c346eb3635168576f04050be50ebcc0be6be12 +retire systemd/user/omarchy-recover-internal-monitor.service b9b92cedc44cf3cb6216948629be55b53d16746e31896dc6469fd49ba55e82f4 +retire systemd/user/omarchy-recover-internal-monitor.service e1483079b9f2aefcd43b4722c75a31643e5f3bb5a2eada5f52f1d7d201e8c289 +retire systemd/user/omarchy-sleep-lock.service bcd1a76cb5c63514922bc5e11af22ae480fc6d06a99863364e02bdf3c7bdceaf +retire uwsm/default 2e89b03a3710b70cf754ea0c8db4388bb35a7519870036abff5ea8a584eafbc0 +retire uwsm/default 3622ba134d29b639a155424a5226215e213c8508144e98001ffe128a8967c9b5 +retire uwsm/default 73712c5a677532bd4afcee5800ae9b76e3d02a2130659a96a8b7fbe2fd2c3d53 +retire uwsm/default 56f968d461da1b8360bc21d5fb7d5375121b772dd06d9397ebcda55a9097c2a0 +retire uwsm/default f7558795e1f6b89357a780ad4e1c63ffdd56e423f31c9a888738afe894e16623 +retire uwsm/env 60eae2629f2dbc70bb068de7bcb245032a429dd989f98b573eb315c0760b4ea5 +retire uwsm/env daf70280edd80bae94660f8509d294df2aaa242d3428320bf6542341efff5a6d +retire uwsm/env 61a4147404a2b6b920f6f414a8c9bcef69b8bcf2a1251e1ddd2fbc37fe45e04d +retire uwsm/env 32130b0033e1d3229d89e6f73394e272eb3adad07314f740f8df9629c1f89beb +retire uwsm/env 278df755a1679f2735742c61de9789614cdb2021fbbb4e802f056c0403d1a6b8 +retire uwsm/env 7be477d4e734d30ebc2caf9dbad6133dcb4aef38d64eb0979beab46f1c0e2464 +retire uwsm/env 0c2cd9c32bd8aea26c62bc18c4a287a29999d4b2ec2b3216b666fb204ab3c471 +retire uwsm/env 957dc0a95f8e909a378ce82967d7a55eb474e2fe5b2672212272e88530c4d4aa +retire uwsm/env 425036ed11f004f59a5fca324305b13189a6aca4b4dd1582532f075d14413d93 +retire uwsm/env 9eb186609afce36a525e58e0b0858eb586869c5d067a7e5545bb5be606ab8a44 +retire xdg-terminals.list 7303fa8d1d74eda73cf5fb4c90183a8608c191bb80d7fb9d96ab60f9df06022e +retire xdg-terminals.list d035da571a6bfc7d626d4a88846ea86a8adb6f6662f1f8b4abe2330e53ceb71b +DEFAULT_HASHES +} + +declare -A known_config_default_hashes_by_key=() +while IFS=$' ' read -r action rel hash; do + [[ -n ${action:-} && $action != \#* ]] || continue + known_config_default_hashes_by_key["$action:$rel:$hash"]=1 +done < <(known_config_default_hashes) + +default_hash_paths() { + local action_filter="$1" action rel hash + known_config_default_hashes | while IFS=$' ' read -r action rel hash; do + [[ -n ${action:-} && $action != \#* ]] || continue + [[ $action == "$action_filter" ]] || continue + printf '%s\n' "$rel" + done | sort -u +} + +is_known_default_hash() { + local action="$1" rel="$2" file="$3" hash + [[ -f $file ]] || return 1 + hash=$(file_sha256 "$file") + [[ -n ${known_config_default_hashes_by_key["$action:$rel:$hash"]+set} ]] +} + +backup_config_file() { + local file="$1" + [[ -e $file || -L $file ]] || return 0 + cp -af "$file" "$file.omarchy-upgrade-to-4.$BACKUP_SUFFIX.bak" +} + +mapfile -t retired_config_files < <(default_hash_paths retire) + +# These are new Omarchy 4 config entry points. Older installs cannot have an +# Omarchy-shipped legacy copy to hash-match, so always install the v4 default. +always_copy_config_files=( + hypr/.luarc.json + hypr/autostart.lua + hypr/bindings.lua + hypr/hyprland.lua + hypr/input.lua + hypr/looknfeel.lua + hypr/monitors.lua + omarchy/bar.json + omarchy/extensions/omarchy-menu.jsonc + omarchy/hooks/pre-refresh-pacman.d/add-custom-repo.sample + omarchy/shell.json +) + +migrate_uwsm_env_customizations() { + local source="$1" dest="$HOME/.config/uwsm/env.d/99-omarchy-upgrade-env" tmp + [[ -f $source ]] || return 0 + is_known_default_hash retire uwsm/env "$source" && return 0 + + tmp=$(mktemp) + awk ' + function omitted(reason) { print ": # omarchy-upgrade omitted legacy Omarchy " reason; next } + + /^[[:space:]]*export[[:space:]]+OMARCHY_PATH=\$HOME\/\.local\/share\/omarchy[[:space:]]*$/ { omitted("OMARCHY_PATH") } + /^[[:space:]]*export[[:space:]]+OMARCHY_PATH="\$\{OMARCHY_PATH:-\/usr\/share\/omarchy\}"[[:space:]]*$/ { omitted("OMARCHY_PATH") } + /^[[:space:]]*\[ -f \/etc\/omarchy\.conf \] && \. \/etc\/omarchy\.conf[[:space:]]*$/ { omitted("/etc/omarchy.conf source") } + /^[[:space:]]*export[[:space:]]+PATH=\$OMARCHY_PATH\/bin:\$PATH:\$HOME\/\.local\/bin[[:space:]]*$/ { omitted("PATH setup") } + /^[[:space:]]*export[[:space:]]+PATH="\$OMARCHY_PATH\/bin:\$PATH:\$HOME\/\.local\/bin"[[:space:]]*$/ { omitted("PATH setup") } + /^[[:space:]]*source[[:space:]]+~\/\.config\/uwsm\/default[[:space:]]*$/ { omitted("uwsm/default source") } + /^[[:space:]]*\[ -f "\$HOME\/\.config\/uwsm\/default" \] && \. "\$HOME\/\.config\/uwsm\/default"[[:space:]]*$/ { omitted("uwsm/default source") } + /^[[:space:]]*omarchy-cmd-present[[:space:]]+mise && eval "\$\(mise activate bash --shims\)"[[:space:]]*$/ { omitted("mise activation") } + + { print } + ' "$source" >"$tmp" + + if [[ -s $tmp ]]; then + if ! sh -n "$tmp" >/dev/null 2>&1; then + cp -f "$source" "$tmp" + fi + + mkdir -p "$(dirname "$dest")" + { + echo '# Preserved custom ~/.config/uwsm/env content during Omarchy 4 upgrade.' + echo '# Exact legacy Omarchy-managed setup lines were replaced with no-op markers where safe.' + cat "$tmp" + } >"$dest" + fi + + rm -f "$tmp" +} + +is_retired_config_file() { + local rel="$1" retired + [[ $rel == systemd/user/* ]] && return 0 + + for retired in "${retired_config_files[@]}"; do + [[ $rel == "$retired" ]] && return 0 + done + + return 1 +} + +copy_config_default() { + local rel="$1" source="$root/config/$1" target="$HOME/.config/$1" + [[ -e $source || -L $source ]] || return 0 + + if [[ -e $target || -L $target ]]; then + if [[ -f $source && -f $target ]] && cmp -s "$source" "$target"; then + return 0 + fi + backup_config_file "$target" + rm -f "$target" + fi + + mkdir -p "$(dirname "$target")" + cp -P "$source" "$target" +} + +copy_missing_config_defaults() { + local source_dir="$1" target_dir="$2" source_path rel target_path + [[ -d $source_dir ]] || return 0 + + while IFS= read -r -d '' source_path; do + rel="${source_path#$source_dir/}" + is_retired_config_file "$rel" && continue + + target_path="$target_dir/$rel" + [[ -e $target_path || -L $target_path ]] && continue + + mkdir -p "$(dirname "$target_path")" + cp -P "$source_path" "$target_path" + done < <(find "$source_dir" \( -type f -o -type l \) -print0) +} + +refresh_known_config_defaults() { + local rel file default + + while IFS= read -r rel; do + file="$HOME/.config/$rel" + default="$root/config/$rel" + [[ -f $file && -f $default ]] || continue + is_known_default_hash refresh "$rel" "$file" || continue + copy_config_default "$rel" + done < <(default_hash_paths refresh) +} + +copy_always_config_defaults() { + local rel + for rel in "${always_copy_config_files[@]}"; do + copy_config_default "$rel" + done +} + +is_known_bashrc_default() { + local file="$1" hash + [[ -f $file ]] || return 1 + hash=$(file_sha256 "$file") + + case "$hash" in + 06ef4dcaa0530d7410513b65b82eea45f147d386a7689dcf1f5636fdad7561ff|\ + 907d367c7589361788a2b0456003f6ef0a2e049548b77b9acf5b0f8cecc2ab0f|\ + 7f46fdc7e3016ab2309d49607a9dddc907b06066cebcf23a63e0110f5d962d73|\ + 322f495563435da1dc70e16968ee33f6a9d81ab361b79ebfd97814b83a89e011|\ + 56009cd83e46e0715911877f173bf1dab966f3e22b6995c530937f2feb18b667|\ + 1a8c98df85360a85acde31effa33c419ce9d27bc17e3a0d5900d4a6cb1743bcc) + return 0 + ;; + esac + + return 1 +} + +install_bash_startup() { + local bashrc="$HOME/.bashrc" bash_profile="$HOME/.bash_profile" + [[ -f $root/default/bashrc ]] || return 0 + + backup_config_file "$bashrc" + + if [[ ! -e $bashrc && ! -L $bashrc ]] || is_known_bashrc_default "$bashrc"; then + cp "$root/default/bashrc" "$bashrc" + elif grep -qxF 'source ~/.local/share/omarchy/default/bash/rc' "$bashrc" || grep -qxF 'source "$OMARCHY_PATH/default/bash/rc"' "$bashrc"; then + python3 - "$bashrc" <<'BASHRC_PATCH_PY' +import sys +from pathlib import Path + +path = Path(sys.argv[1]) +text = path.read_text() +new_block = '''# /etc/omarchy.conf is written by omarchy-dev-link. When absent, force the +# package default instead of preserving a stale inherited dev-link value before +# we decide which rc file to source. +if [[ -f /etc/omarchy.conf ]]; then + source /etc/omarchy.conf + export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}" +else + export OMARCHY_PATH=/usr/share/omarchy fi -if [[ -f $root/default/bashrc ]]; then - cp "$root/default/bashrc" "$HOME/.bashrc" - echo '[[ -f ~/.bashrc ]] && . ~/.bashrc' >"$HOME/.bash_profile" +source "$OMARCHY_PATH/default/bash/rc" +''' +text = text.replace('source ~/.local/share/omarchy/default/bash/rc\n', new_block) +text = text.replace(': "${OMARCHY_PATH:=/usr/share/omarchy}"\nsource "$OMARCHY_PATH/default/bash/rc"\n', new_block) +path.write_text(text) +BASHRC_PATCH_PY + fi + + if [[ ! -e $bash_profile && ! -L $bash_profile ]]; then + echo '[[ -f ~/.bashrc ]] && . ~/.bashrc' >"$bash_profile" + fi +} + +# Some former ~/.config defaults are now package-owned elsewhere so future +# updates can change defaults without rewriting user files. Back them up before +# cleanup, then keep only real user customizations active. +uwsm_env="$HOME/.config/uwsm/env" +if [[ -f $uwsm_env ]]; then + cp -f "$uwsm_env" "$uwsm_env.omarchy-upgrade-to-4.$BACKUP_SUFFIX.bak" + migrate_uwsm_env_customizations "$uwsm_env" fi +for rel in "${retired_config_files[@]}"; do + file="$HOME/.config/$rel" + backup_config_file "$file" +done + +# Existing user config may be customized. Refresh only files whose hash matches +# a default Omarchy has shipped before, fill in missing defaults for old installs, +# and always write the v4-only entry points that older installs cannot have. +refresh_known_config_defaults +copy_missing_config_defaults "$root/config" "$HOME/.config" +copy_always_config_defaults + +for rel in "${retired_config_files[@]}"; do + file="$HOME/.config/$rel" + backup="$file.omarchy-upgrade-to-4.$BACKUP_SUFFIX.bak" + + # UWSM env was hardcoded to the legacy checkout on older installs. Custom + # non-Omarchy lines were migrated to env.d above; never keep the active file. + if [[ $rel == uwsm/env ]]; then + rm -f "$file" + continue + fi + + if [[ -f $backup ]] && ! is_known_default_hash retire "$rel" "$backup"; then + # Keep intentional user overrides active; package defaults remain lower + # priority under /usr/lib or /usr/share. + mkdir -p "$(dirname "$file")" + cp -af "$backup" "$file" + else + rm -f "$file" + fi +done +install_bash_startup + +unset rel file backup retired_config_files always_copy_config_files uwsm_env known_config_default_hashes_by_key +unset -f file_sha256 known_config_default_hashes default_hash_paths is_known_default_hash backup_config_file migrate_uwsm_env_customizations is_retired_config_file copy_config_default copy_missing_config_defaults refresh_known_config_defaults copy_always_config_defaults is_known_bashrc_default install_bash_startup + mkdir -p "$HOME/.agents/skills" "$HOME/.claude/skills" "$HOME/.codex/skills" "$HOME/.pi/agent/skills" if [[ -d $root/default/omarchy-skill ]]; then ln -sfn "$root/default/omarchy-skill" "$HOME/.agents/skills/omarchy" @@ -1119,9 +1495,22 @@ if [[ -f $root/default/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect fi enable_user_unit() { - local unit="$1" unit_path="$HOME/.config/systemd/user/$1" target + local unit="$1" unit_path link_target target local -a targets=() - [[ -f $unit_path ]] || return 0 + + if [[ -f $HOME/.config/systemd/user/$unit ]]; then + unit_path="$HOME/.config/systemd/user/$unit" + link_target="../$unit" + elif [[ -f /usr/lib/systemd/user/$unit ]]; then + unit_path="/usr/lib/systemd/user/$unit" + link_target="$unit_path" + elif [[ -f $root/default/systemd/user/$unit ]]; then + unit_path="$root/default/systemd/user/$unit" + link_target="$unit_path" + else + return 0 + fi + mapfile -t targets < <(awk -F= ' /^\[Install\]/ { in_install=1; next } /^\[/ { in_install=0 } @@ -1133,11 +1522,12 @@ enable_user_unit() { ((${#targets[@]})) || targets=(default.target) for target in "${targets[@]}"; do mkdir -p "$HOME/.config/systemd/user/$target.wants" - ln -sfn "../$unit" "$HOME/.config/systemd/user/$target.wants/$unit" + ln -sfn "$link_target" "$HOME/.config/systemd/user/$target.wants/$unit" done } enable_user_unit bt-agent.service enable_user_unit omarchy-sleep-lock.service +enable_user_unit omarchy-recover-internal-monitor.service mkdir -p "$HOME/.config/systemd/user/default.target.wants" for unit in pipewire-pulse.service pipewire-pulse.socket; do if [[ -e /usr/lib/systemd/user/$unit ]]; then @@ -1248,7 +1638,7 @@ if command -v xdg-mime >/dev/null 2>&1; then xdg-mime default HEY.desktop x-scheme-handler/mailto || true fi -touch "$state_dir/setup-user.done" +touch "$state_dir/finalize-user.done" USER_SETUP } diff --git a/config/systemd/user/graphical-session.target.wants/bt-agent.service b/config/systemd/user/graphical-session.target.wants/bt-agent.service deleted file mode 120000 index 90bbe80a..00000000 --- a/config/systemd/user/graphical-session.target.wants/bt-agent.service +++ /dev/null @@ -1 +0,0 @@ -../bt-agent.service \ No newline at end of file diff --git a/config/systemd/user/graphical-session.target.wants/omarchy-sleep-lock.service b/config/systemd/user/graphical-session.target.wants/omarchy-sleep-lock.service deleted file mode 120000 index 2a00b842..00000000 --- a/config/systemd/user/graphical-session.target.wants/omarchy-sleep-lock.service +++ /dev/null @@ -1 +0,0 @@ -../omarchy-sleep-lock.service \ No newline at end of file diff --git a/config/uwsm/env b/config/uwsm/env deleted file mode 100644 index 5abd2c7e..00000000 --- a/config/uwsm/env +++ /dev/null @@ -1,15 +0,0 @@ -# Changes require a restart to take effect. - -# Source /etc/omarchy.conf so omarchy-dev-link (which writes -# OMARCHY_PATH= there) wins over the packaged default. UWSM doesn't -# source /etc/profile.d/, so this duplicates that logic for the Hyprland -# session. -[ -f /etc/omarchy.conf ] && . /etc/omarchy.conf -export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}" -export PATH="$OMARCHY_PATH/bin:$PATH:$HOME/.local/bin" - -# Set default terminal and editor -source ~/.config/uwsm/default - -# Activate mise if present on the system -omarchy-cmd-present mise && eval "$(mise activate bash --shims)" diff --git a/default/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect.conf b/config/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect.conf similarity index 100% rename from default/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect.conf rename to config/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect.conf diff --git a/config/xournalpp/settings.xml b/config/xournalpp/settings.xml index 5f98a901..020c8372 100644 --- a/config/xournalpp/settings.xml +++ b/config/xournalpp/settings.xml @@ -6,9 +6,9 @@ - + - + diff --git a/config/mimeapps.list b/default/applications/mimeapps.list similarity index 100% rename from config/mimeapps.list rename to default/applications/mimeapps.list diff --git a/default/bash/env-bootstrap b/default/bash/env-bootstrap new file mode 100644 index 00000000..7f3a7756 --- /dev/null +++ b/default/bash/env-bootstrap @@ -0,0 +1,27 @@ +# Single source of truth for OMARCHY_PATH + PATH adjustments. Sourced by: +# /etc/profile.d/omarchy.sh (system login shells) +# /etc/skel/.bashrc (interactive shells) +# /usr/share/uwsm/env.d/10-omarchy (Hyprland session via uwsm) +# /usr/share/omarchy/default/bash/envs (bash rc chain; SSH/non-login) + +# /etc/omarchy.conf is written by omarchy-dev-link. When absent, force the +# packaged default instead of preserving a stale inherited value. +if [ -f /etc/omarchy.conf ]; then + . /etc/omarchy.conf + : "${OMARCHY_PATH:=/usr/share/omarchy}" +else + OMARCHY_PATH=/usr/share/omarchy +fi +export OMARCHY_PATH + +# Only prepend in dev-link mode. On a production install, the binaries are +# already on PATH as /usr/bin/omarchy-* via the omarchy package — prepending +# /usr/share/omarchy/bin would just be noise. omarchy-dev-unlink strips its +# checkout bin/ from the active PATH explicitly, so we don't dedupe here. +if [ "$OMARCHY_PATH" != /usr/share/omarchy ]; then + case ":$PATH:" in + *":${OMARCHY_PATH%/}/bin:"*) ;; + *) PATH="${OMARCHY_PATH%/}/bin:$PATH" ;; + esac + export PATH +fi diff --git a/default/bash/envs b/default/bash/envs index c202474b..ba36cb33 100644 --- a/default/bash/envs +++ b/default/bash/envs @@ -6,9 +6,11 @@ export BAT_THEME=ansi export MANROFFOPT="-c" export MANPAGER="sh -c 'col -bx | bat -l man -p'" -# Duplicated from .config/uwsm/env so SSH/non-login shells also see the -# override. /etc/omarchy.conf wins (omarchy-dev-link writes it); otherwise -# the packaged runtime under /usr/share/omarchy is used. -[ -f /etc/omarchy.conf ] && . /etc/omarchy.conf -export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}" -export PATH="$OMARCHY_PATH/bin:$PATH:$HOME/.local/bin" +# Idempotent — already sourced by /etc/skel/.bashrc; re-source here so SSH and +# other non-interactive non-login bash sessions still get OMARCHY_PATH. +[ -r /usr/share/omarchy/default/bash/env-bootstrap ] && . /usr/share/omarchy/default/bash/env-bootstrap + +case ":$PATH:" in + *":$HOME/.local/bin:"*) ;; + *) export PATH="$PATH:$HOME/.local/bin" ;; +esac diff --git a/default/bashrc b/default/bashrc index a9978dd5..43810a91 100644 --- a/default/bashrc +++ b/default/bashrc @@ -3,7 +3,7 @@ # All the default Omarchy aliases and functions # (don't mess with these directly, just overwrite them here!) -: "${OMARCHY_PATH:=/usr/share/omarchy}" +[[ -r /usr/share/omarchy/default/bash/env-bootstrap ]] && source /usr/share/omarchy/default/bash/env-bootstrap source "$OMARCHY_PATH/default/bash/rc" # Add your own exports, aliases, and functions here. diff --git a/config/environment.d/fcitx.conf b/default/environment.d/10-omarchy-fcitx.conf similarity index 100% rename from config/environment.d/fcitx.conf rename to default/environment.d/10-omarchy-fcitx.conf diff --git a/config/fontconfig/fonts.conf b/default/fontconfig/conf.avail/30-omarchy.conf similarity index 96% rename from config/fontconfig/fonts.conf rename to default/fontconfig/conf.avail/30-omarchy.conf index e5e6598e..80317901 100644 --- a/config/fontconfig/fonts.conf +++ b/default/fontconfig/conf.avail/30-omarchy.conf @@ -23,7 +23,7 @@ monospace - + JetBrainsMono Nerd Font diff --git a/config/omarchy.ttf b/default/fonts/omarchy/omarchy.ttf similarity index 100% rename from config/omarchy.ttf rename to default/fonts/omarchy/omarchy.ttf diff --git a/config/systemd/user/bt-agent.service b/default/systemd/user/bt-agent.service similarity index 100% rename from config/systemd/user/bt-agent.service rename to default/systemd/user/bt-agent.service diff --git a/config/systemd/user/omarchy-recover-internal-monitor.service b/default/systemd/user/omarchy-recover-internal-monitor.service similarity index 100% rename from config/systemd/user/omarchy-recover-internal-monitor.service rename to default/systemd/user/omarchy-recover-internal-monitor.service diff --git a/config/systemd/user/omarchy-sleep-lock.service b/default/systemd/user/omarchy-sleep-lock.service similarity index 100% rename from config/systemd/user/omarchy-sleep-lock.service rename to default/systemd/user/omarchy-sleep-lock.service diff --git a/config/uwsm/default b/default/uwsm/default similarity index 100% rename from config/uwsm/default rename to default/uwsm/default diff --git a/default/uwsm/env.d/10-omarchy b/default/uwsm/env.d/10-omarchy new file mode 100644 index 00000000..05485643 --- /dev/null +++ b/default/uwsm/env.d/10-omarchy @@ -0,0 +1,20 @@ +# Changes require a restart to take effect. + +# UWSM doesn't source /etc/profile.d, so pull the env bootstrap in directly. +[ -r /usr/share/omarchy/default/bash/env-bootstrap ] && . /usr/share/omarchy/default/bash/env-bootstrap + +# Omarchy session defaults. Users can override these in ~/.config/uwsm/default +# or, preferably, ~/.config/uwsm/env.d/*. +if [ -f "${OMARCHY_PATH%/}/default/uwsm/default" ]; then + . "${OMARCHY_PATH%/}/default/uwsm/default" +else + export TERMINAL=xdg-terminal-exec + export BROWSER=omarchy-launch-browser + export EDITOR="omarchy-launch-editor --inline" +fi + +# Optional user overrides kept for compatibility with older installs. +[ -f "$HOME/.config/uwsm/default" ] && . "$HOME/.config/uwsm/default" + +# Activate mise if present on the system +omarchy-cmd-present mise && eval "$(mise activate bash --shims)" diff --git a/config/xdg-terminals.list b/default/xdg-terminal-exec/hyprland-xdg-terminals.list similarity index 85% rename from config/xdg-terminals.list rename to default/xdg-terminal-exec/hyprland-xdg-terminals.list index 0821cf0d..8e7f5ca6 100644 --- a/config/xdg-terminals.list +++ b/default/xdg-terminal-exec/hyprland-xdg-terminals.list @@ -1,3 +1,3 @@ # Terminal emulator preference order for xdg-terminal-exec # The first found and valid terminal will be used -Alacritty.desktop +foot.desktop diff --git a/docs/file-layout.md b/docs/file-layout.md new file mode 100644 index 00000000..7210aca7 --- /dev/null +++ b/docs/file-layout.md @@ -0,0 +1,186 @@ +# File layout + +How `omarchy/` is organized and where everything ends up on an installed +system. + +## Mental model + +Four Arch packages are built from this one repo (PKGBUILDs live in +`omarchy-pkgs/pkgbuilds/`): + +- **`omarchy`** — runtime binaries (`bin/`), install/finalize scripts + (`install/`), migrations, themes, and the Quickshell desktop (`shell/`). +- **`omarchy-settings`** — user defaults (seeded via `/etc/skel`), `/etc/` + drop-ins, package-owned system files under `/usr/share` and `/usr/lib`, + fonts, plymouth theme, sddm theme, branding. Carves out `default/limine/` + and `default/snapper/` (owned by `omarchy-limine`). +- **`omarchy-dev-tools`** — just `bin/omarchy-dev-*`. Optional dep of + `omarchy`; installed for contributors, not end users. +- **`omarchy-limine`** — `default/limine/` and `default/snapper/` from this + repo, plus mkinitcpio and limine-entry-tool drop-ins that live alongside + the PKGBUILD in `omarchy-pkgs/`. Owns the boot/snapshot story end-to-end. + +Three layers populate `$HOME`: + +1. **Seed** — `omarchy-settings` ships static defaults to `/etc/skel/`. + Arch's `useradd -m` copies that tree into a new user's `$HOME` at user + creation. This is the only mechanism that touches a brand-new user's home + for these files. +2. **Finalize** — `omarchy-finalize-user` runs once per user and handles the + things `/etc/skel` can't do because they need `$HOME` expansion, the live + `$OMARCHY_PATH`, or runtime detection of system state. +3. **Resync** — `omarchy-reinstall-configs` is the explicit, destructive + command for an existing user to clobber their configs back to shipped + defaults. + +`/etc/skel` only fires at user creation. Existing users picking up new +defaults must use the resync command. + +## Build-time map (repo → installed paths) + +``` +omarchy/ built into installed at +───────────────────────── ────────────── ──────────────────────────────────── + +bin/omarchy-* ──► omarchy /usr/bin/omarchy-* + (and symlinks in /usr/share/omarchy/bin/) +bin/omarchy-dev-* ──► omarchy-dev-tools /usr/bin/omarchy-dev-* +bin/omarchy-debug, +bin/omarchy-debug-idle, +bin/omarchy-upload-log ──► omarchy-settings /usr/bin/ (needed before omarchy is installed) + +install/** ──► omarchy /usr/share/omarchy/install/ +migrations/** ──► omarchy /usr/share/omarchy/migrations/ +themes/** ──► omarchy /usr/share/omarchy/themes/ +shell/** ──► omarchy /usr/share/omarchy/shell/ +version ──► omarchy /usr/share/omarchy/version + + /etc/skel/.local/state/omarchy/migrations/* + +config/** ──► omarchy-settings /etc/skel/.config/** (seeds new users) + /usr/share/omarchy/config/** (resync source) + +applications/*.desktop ──► omarchy-settings /etc/skel/.local/share/applications/ + /usr/share/omarchy/applications/ +applications/icons/* ──► omarchy-settings /usr/share/icons/hicolor/{48,256,scalable}/apps/ + +etc/** ──► omarchy-settings /etc/** (drop-ins we own outright) + +default/limine/limine.conf ──► omarchy-limine /usr/share/omarchy/default/limine/limine.conf +default/limine/default.conf ──► omarchy-limine /usr/share/omarchy/default/limine/default.conf + (template; ISO substitutes @@CMDLINE@@ → /etc/default/limine) +default/snapper/root ──► omarchy-limine /etc/snapper/config-templates/omarchy + +default/** ──► omarchy-settings /usr/share/omarchy/default/ (excluding default/{limine,snapper}) + ├─ bashrc /usr/share/omarchy/etc-overrides/dot.bashrc + │ → /etc/skel/.bashrc (post_install cp -f) + ├─ hypr/toggles/flags.lua /etc/skel/.local/state/omarchy/toggles/hypr/ + ├─ nautilus-python/extensions/*.py /etc/skel/.local/share/nautilus-python/extensions/ + ├─ uwsm/env.d/10-omarchy /usr/share/uwsm/env.d/ + ├─ environment.d/*.conf /usr/lib/environment.d/ + ├─ fontconfig/conf.avail/30-omarchy.conf /usr/share/fontconfig/conf.avail/ + │ + symlink /etc/fonts/conf.d/30-omarchy.conf + ├─ xdg-terminal-exec/*.list /usr/share/xdg-terminal-exec/ + ├─ applications/mimeapps.list /usr/share/applications/mimeapps.list + ├─ systemd/user/*.service /usr/lib/systemd/user/ + ├─ systemd/system-sleep/unmount-fuse /usr/lib/systemd/system-sleep/ + ├─ fonts/omarchy/omarchy.ttf /usr/share/fonts/omarchy/ + ├─ sddm/omarchy/ /usr/share/sddm/themes/omarchy/ + ├─ sddm/hyprland.lua /usr/share/sddm/hyprland.lua + ├─ wayland-sessions/omarchy.desktop /usr/local/share/wayland-sessions/ + ├─ plymouth/ /usr/share/plymouth/themes/omarchy/ + └─ security/faillock, nsswitch, cups-browsed, + plymouthd.conf, os-release /usr/share/omarchy/etc-overrides/ + → /etc/* (post_install cp -f, see below) + +logo.{txt,svg}, icon.{txt,png} ──► omarchy-settings /usr/share/omarchy/ (resync source) + /usr/share/pixmaps/omarchy.png + /usr/share/icons/hicolor/256x256/apps/omarchy.png + /etc/skel/.config/omarchy/branding/{about,screensaver}.txt +``` + +### Why `etc-overrides/` exists + +Some files under `/etc/` (`.bashrc` in `/etc/skel`, `nsswitch.conf`, +`security/faillock.conf`, `cups/cups-browsed.conf`, `plymouth/plymouthd.conf`, +`os-release`) are owned by upstream Arch packages, so we can't install over +them via pacman without a file conflict. Instead they ship at +`/usr/share/omarchy/etc-overrides/` and the `omarchy-settings` `post_install` +/ `post_upgrade` scriptlet `cp -f`'s them into place. + +Tradeoff: user edits to those files get clobbered on every `omarchy-settings` +upgrade. This is documented in the PKGBUILD. + +## Runtime finalization (`omarchy-finalize-user`) + +Runs once per user. It does **not** copy `~/.config/**`, `~/.bashrc`, +`flags.lua`, or the nautilus extensions — `/etc/skel` already seeded those. +It only does the things `/etc/skel` can't: + +- Skill symlinks `~/.{agents,claude,codex,pi/agent}/skills/omarchy` → + `$OMARCHY_PATH/default/omarchy-skill`. Symlinks (not copies) so + `omarchy dev link` against a dev checkout repoints them correctly. +- `xdg-user-dirs-update` (Templates/Public/Desktop folded back into `$HOME`) + and `~/.config/gtk-3.0/bookmarks` (needs `$HOME` expansion). +- Sync `XKBLAYOUT` / `XKBVARIANT` from `/etc/vconsole.conf` into + `~/.config/hypr/input.lua`. +- `xdg-settings set default-web-browser chromium.desktop` and + `xdg-mime default HEY.desktop x-scheme-handler/mailto` (XDG-aware paths). +- `omarchy-refresh-applications` (composes generated `.desktop` launchers). +- Sources `install/user/all.sh` — theme, git, mise, keyring, per-user + hardware quirks (bluetooth, asus mic/mixer, framework f13 audio, …). +- On `--first-install`, marks every shipped migration as already applied + for the freshly-created user. + +Idempotency marker: `~/.local/state/omarchy/finalize-user.done`. + +The ISO calls it as `omarchy-finalize-user --force --first-install` in the +target chroot as the install user, after `omarchy-setup-system` has finished +the root-side work. + +## Root-side install orchestration + +`omarchy-setup-system` (root, in chroot) runs target-side setup at ISO +finalization. It sources: + +- `install/config/*.sh` — theme links, lockout limits, lockscreen PAM, + powerprofilesctl shebang fix, docker setup, service enablement, firewall. +- `install/hardware/all.sh` via `omarchy-setup-hardware` — vendor- and + device-specific kernel modules, udev rules, microcode, wireless regdom, + ASUS / Framework / Intel / Apple / Lenovo quirks. +- `install/login/*.sh` — SDDM theme/session config. +- `install/post-install/*.sh` — final pacman/udev/localdb passes. + +Logging goes to `/var/log/omarchy-install.log` via +`install/helpers/logging.sh`. + +## Explicit resync (`omarchy-reinstall-configs`) + +When an existing user wants to reset to shipped defaults: + +``` +~/ ← cp -af /etc/skel/. +``` + +Replaying `/etc/skel` over `$HOME` is exactly what `useradd -m` does for a +brand-new user, so this one copy resyncs `.bashrc`, `.config/**`, +`.local/share/applications/`, the nautilus-python extensions, hypr toggles, +branding files, and the shipped migration markers in a single pass. + +Then it runs `omarchy-refresh-limine`, `omarchy-refresh-plymouth`, and the +nvim refresh. Destructive: existing user files at these paths are clobbered +without backup. + +## Quick reference: where does X live? + +| Goal | Touch | +| --- | --- | +| Default file at `~/.config/foo/` | `config/foo/` | +| `/etc/` drop-in we own outright | `etc/` | +| `/etc/` file owned by an upstream package | `default/`, then add to `etc-overrides` in `omarchy-settings` PKGBUILD + scriptlet | +| Package-owned system file (e.g. systemd user service in `/usr/lib`) | `default/`, document the mapping in `default/package-defaults.tsv`, then add the `install -Dm644` line in `omarchy-settings` PKGBUILD | +| Per-user file that's static but lives outside `~/.config` | `default/`, then add `install -Dm644 ... $pkgdir/etc/skel/...` in `omarchy-settings` PKGBUILD | +| Runtime tweak that needs `$HOME` or live system state | extend `omarchy-finalize-user`, or add a per-user leaf under `install/user/` and wire into `install/user/all.sh` | +| One-time root-side setup step | `install/config/*.sh` or `install/hardware/*.sh`, wire into `omarchy-setup-system` or `install/hardware/all.sh` | +| User-facing `omarchy-*` command | `bin/omarchy--` — see `GROUP_DESCRIPTIONS` in `bin/omarchy` | +| New theme | `themes//` (+ matching templates under `default/themed/` if they need theme colors) | +| One-shot fix for installed systems | `migrations/.sh` (use `omarchy-dev-add-migration --no-edit`) | diff --git a/etc/profile.d/omarchy.sh b/etc/profile.d/omarchy.sh index c002dad8..884ffb05 100644 --- a/etc/profile.d/omarchy.sh +++ b/etc/profile.d/omarchy.sh @@ -1,8 +1 @@ -[ -f /etc/omarchy.conf ] && . /etc/omarchy.conf -export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}" - -# omarchy-dev-link: prepend checkout bin/ so it shadows /usr/bin/omarchy-*. -case ":$PATH:" in - *":$OMARCHY_PATH/bin:"*) ;; - *) [ -d "$OMARCHY_PATH/bin" ] && export PATH="$OMARCHY_PATH/bin:$PATH" ;; -esac +[ -r /usr/share/omarchy/default/bash/env-bootstrap ] && . /usr/share/omarchy/default/bash/env-bootstrap diff --git a/install/omarchy-base.packages b/install/omarchy-base.packages index e3666b63..b82d2067 100644 --- a/install/omarchy-base.packages +++ b/install/omarchy-base.packages @@ -137,7 +137,6 @@ woff2-font-awesome xdg-desktop-portal-gtk xdg-desktop-portal-hyprland xdg-terminal-exec -xmlstarlet xournalpp yaru-icon-theme yay diff --git a/install/user/all.sh b/install/user/all.sh index a17ec5dc..5140bca2 100644 --- a/install/user/all.sh +++ b/install/user/all.sh @@ -2,9 +2,7 @@ run_logged "$OMARCHY_INSTALL/user/theme.sh" run_logged "$OMARCHY_INSTALL/user/git.sh" run_logged "$OMARCHY_INSTALL/user/xcompose.sh" run_logged "$OMARCHY_INSTALL/user/mise-work.sh" -run_logged "$OMARCHY_INSTALL/user/sleep-lock.sh" -run_logged "$OMARCHY_INSTALL/user/hardware/bluetooth.sh" run_logged "$OMARCHY_INSTALL/user/hardware/asus/fix-audio-mixer.sh" run_logged "$OMARCHY_INSTALL/user/hardware/asus/fix-mic.sh" run_logged "$OMARCHY_INSTALL/user/hardware/framework/fix-f13-amd-audio-input.sh" diff --git a/install/user/first-run/enable-user-units.sh b/install/user/first-run/enable-user-units.sh new file mode 100755 index 00000000..6a6a65d2 --- /dev/null +++ b/install/user/first-run/enable-user-units.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +# Enable the user systemd units we ship. Runs at first-run rather than at +# finalize-user time because the user manager isn't live during the ISO +# chroot — by first-run, the Hyprland/uwsm session is up and `systemctl +# --user enable` writes the correct .wants symlinks based on each unit's +# [Install]/WantedBy. ConditionPath* in the unit files keep the enabled +# units inert on hardware they don't apply to. + +set -euo pipefail + +systemctl --user enable \ + bt-agent.service \ + omarchy-recover-internal-monitor.service \ + omarchy-sleep-lock.service diff --git a/install/user/hardware/bluetooth.sh b/install/user/hardware/bluetooth.sh deleted file mode 100644 index 9bf06377..00000000 --- a/install/user/hardware/bluetooth.sh +++ /dev/null @@ -1,13 +0,0 @@ -mkdir -p ~/.config/wireplumber/wireplumber.conf.d/ -cp "$OMARCHY_PATH/default/wireplumber/wireplumber.conf.d/bluetooth-a2dp-autoconnect.conf" ~/.config/wireplumber/wireplumber.conf.d/ - -# Quickshell.Bluetooth has no Agent API, so the omarchy.bluetooth plugin -# can't answer the auth prompts bluez issues during pair(). bt-agent registers -# a NoInputNoOutput agent on the system bus so pair() actually completes. -mkdir -p ~/.config/systemd/user/ -cp "$OMARCHY_PATH/config/systemd/user/bt-agent.service" ~/.config/systemd/user/ -if declare -F omarchy_user_systemctl_enable >/dev/null; then - omarchy_user_systemctl_enable bt-agent.service -else - systemctl --user enable bt-agent.service -fi diff --git a/install/user/hardware/recover-internal-monitor.sh b/install/user/hardware/recover-internal-monitor.sh deleted file mode 100644 index c1e84fc0..00000000 --- a/install/user/hardware/recover-internal-monitor.sh +++ /dev/null @@ -1 +0,0 @@ -systemctl --user enable omarchy-recover-internal-monitor.service diff --git a/install/user/sleep-lock.sh b/install/user/sleep-lock.sh deleted file mode 100644 index 09fc9623..00000000 --- a/install/user/sleep-lock.sh +++ /dev/null @@ -1,7 +0,0 @@ -mkdir -p ~/.config/systemd/user/ -cp "$OMARCHY_PATH/config/systemd/user/omarchy-sleep-lock.service" ~/.config/systemd/user/ -if declare -F omarchy_user_systemctl_enable >/dev/null; then - omarchy_user_systemctl_enable omarchy-sleep-lock.service -else - systemctl --user enable omarchy-sleep-lock.service -fi diff --git a/migrations/1779742224.sh b/migrations/1779742224.sh deleted file mode 100644 index a606ce28..00000000 --- a/migrations/1779742224.sh +++ /dev/null @@ -1,9 +0,0 @@ -echo "Gate bluetooth pairing agent on active bluetooth service" - -mkdir -p "$HOME/.config/systemd/user/" -cp "$OMARCHY_PATH/config/systemd/user/bt-agent.service" "$HOME/.config/systemd/user/" -systemctl --user daemon-reload - -if systemctl --user is-enabled --quiet bt-agent.service; then - systemctl --user reset-failed bt-agent.service 2>/dev/null || true -fi diff --git a/test/shell.d/bluetooth-test.sh b/test/shell.d/bluetooth-test.sh index a0a6d5c8..00848673 100644 --- a/test/shell.d/bluetooth-test.sh +++ b/test/shell.d/bluetooth-test.sh @@ -4,7 +4,7 @@ set -euo pipefail source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh" -grep -q '^ConditionPathIsDirectory=/sys/class/bluetooth$' "$ROOT/config/systemd/user/bt-agent.service" || \ +grep -q '^ConditionPathIsDirectory=/sys/class/bluetooth$' "$ROOT/default/systemd/user/bt-agent.service" || \ fail "bt-agent is skipped on machines without Bluetooth hardware" pass "bt-agent is skipped on machines without Bluetooth hardware" diff --git a/test/shell.d/config-test.sh b/test/shell.d/config-test.sh index 9b62691a..37a239d3 100755 --- a/test/shell.d/config-test.sh +++ b/test/shell.d/config-test.sh @@ -87,6 +87,41 @@ if missing or bad: PY pass "default bar widget ids resolve to manifests and entry points" +ROOT="$ROOT" python3 <<'PY' +import os +import sys +from pathlib import Path + +root = Path(os.environ["ROOT"]) +pkgbuild = (root.parent / "omarchy-pkgs/pkgbuilds/omarchy-settings/PKGBUILD").read_text() +errors = [] +package_defaults = [ + ("default/uwsm/env.d/10-omarchy", "/usr/share/uwsm/env.d/10-omarchy", "uwsm/env"), + ("default/uwsm/default", None, "uwsm/default"), + ("default/environment.d/10-omarchy-fcitx.conf", "/usr/lib/environment.d/10-omarchy-fcitx.conf", "environment.d/fcitx.conf"), + ("default/fontconfig/conf.avail/30-omarchy.conf", "/usr/share/fontconfig/conf.avail/30-omarchy.conf", "fontconfig/fonts.conf"), + ("default/xdg-terminal-exec/hyprland-xdg-terminals.list", "/usr/share/xdg-terminal-exec/hyprland-xdg-terminals.list", "xdg-terminals.list"), + ("default/applications/mimeapps.list", "/usr/share/applications/mimeapps.list", "mimeapps.list"), + ("default/systemd/user/bt-agent.service", "/usr/lib/systemd/user/bt-agent.service", "systemd/user/bt-agent.service"), + ("default/systemd/user/omarchy-sleep-lock.service", "/usr/lib/systemd/user/omarchy-sleep-lock.service", "systemd/user/omarchy-sleep-lock.service"), + ("default/systemd/user/omarchy-recover-internal-monitor.service", "/usr/lib/systemd/user/omarchy-recover-internal-monitor.service", "systemd/user/omarchy-recover-internal-monitor.service"), + ("default/fonts/omarchy/omarchy.ttf", "/usr/share/fonts/omarchy/omarchy.ttf", "omarchy.ttf"), +] + +for source, destination, legacy in package_defaults: + if not (root / source).exists(): + errors.append(f"missing package default source: {source}") + if (root / "config" / legacy).exists(): + errors.append(f"legacy path still in config/: {legacy}") + if destination and (source not in pkgbuild or destination not in pkgbuild): + errors.append(f"PKGBUILD does not explicitly install {source} -> {destination}") + +if errors: + print("\n".join(errors), file=sys.stderr) + sys.exit(1) +PY +pass "package-owned defaults live outside config" + mapfile -t migrations < <(find "$ROOT/migrations" -maxdepth 1 -type f -name '*.sh' -printf '%f\n' | sort) [[ ${#migrations[@]} -eq 0 ]] || fail "4.0 upgrade is not modeled as a migration" pass "4.0 upgrade is handled outside the migration runner" diff --git a/test/shell.d/systemd-test.sh b/test/shell.d/systemd-test.sh index d254f512..11801020 100755 --- a/test/shell.d/systemd-test.sh +++ b/test/shell.d/systemd-test.sh @@ -4,7 +4,7 @@ set -euo pipefail source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh" -service="$ROOT/config/systemd/user/bt-agent.service" +service="$ROOT/default/systemd/user/bt-agent.service" grep -Fx 'ExecCondition=/usr/bin/systemctl is-active --quiet bluetooth.service' "$service" >/dev/null pass "bt-agent skips when bluetooth.service is inactive"