diff --git a/sysupdate.sh b/sysupdate.sh index 615a18b..9179bd4 100755 --- a/sysupdate.sh +++ b/sysupdate.sh @@ -616,15 +616,30 @@ sync_configs() { [[ "$skip" == true ]] && continue if [[ "$name" == "hypr" ]]; then - # Copy hypr/ contents but preserve ~/.config/hypr/usr/ + # Copy hypr/ contents but preserve ~/.config/hypr/usr/. + # Stage each item into a temp dir on the same filesystem, then mv it + # into place — for files this is an atomic rename(2), so Hyprland's + # live config watcher never sees hyprland.lua momentarily missing + # (which otherwise makes it emit its fallback hyprland.conf stub). mkdir -p "$target/hypr" local hypr_ok=true - while IFS= read -r -d '' hitem; do - local hname; hname="$(basename "$hitem")" - [[ "$hname" == "usr" ]] && continue - rm -rf "${target}/hypr/${hname}" && cp -r "$hitem" "$target/hypr/" \ - || hypr_ok=false - done < <(find "$item" -maxdepth 1 -mindepth 1 -print0 | sort -z) + local stage; stage="$(mktemp -d "${target}/hypr/.sync.XXXXXX")" || hypr_ok=false + if $hypr_ok; then + while IFS= read -r -d '' hitem; do + local hname; hname="$(basename "$hitem")" + [[ "$hname" == "usr" ]] && continue + if cp -r "$hitem" "$stage/"; then + # mv can't atomically replace a non-empty dir, so clear + # an existing directory target first; files swap atomically. + [[ -d "$stage/$hname" && -d "${target}/hypr/${hname}" ]] \ + && rm -rf "${target}/hypr/${hname}" + mv -f "$stage/$hname" "${target}/hypr/${hname}" || hypr_ok=false + else + hypr_ok=false + fi + done < <(find "$item" -maxdepth 1 -mindepth 1 -print0 | sort -z) + rm -rf "$stage" + fi if $hypr_ok; then ok "synced hypr ${DI}(usr/ preserved)${RS}" (( synced++ )) || true