# 由 scripts/flatten-kickstart.sh 自动生成，请勿手改。
# 源入口: /ssd/desktop-image-bot/workspace/oc-live-compose/kickstarts/desktop-live.ks
# 生成时间: 2026-09-18T19:36:18+08:00

# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/kickstarts/desktop-live.ks

# =============================================================================
# OpenCloudOS Live Desktop — Kickstart 主入口
# =============================================================================
# livemedia-creator / Koji spin-livemedia。
# GNOME 扩展、Orchis 主题与桌面整合由软件源 RPM 安装（EPOL）；
# post/35 只做 RPM 产物断言与 dconf 收尾。
# 不含：自定义内核；非 Live 安装 ISO。
# livemedia 请 flatten（compose-livemedia.sh 会做）。在仓库根执行。
#version=RHEL9


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/00-session-defaults.ks

# =============================================================================
# 【模块】00 — Live 会话默认项
# =============================================================================
# 说明：
#   这些值只影响 Live 试用会话的默认环境。
#   安装到硬盘后的语言/时区等，由 GNOME 首启向导（gnome-initial-setup）处理。
#
# 注意：不要写 graphical / text / cmdline —— livemedia-creator 会拒绝。
#
# lang 在 compose 阶段用 en_US：Anaconda 进度走英文 ASCII，避免本机 pylorax
# 按管道块严格 UTF-8 解码时截断中文多字节而崩溃（无需改宿主 /usr）。
# Live 默认中文在 post/35 的所有 compose 命令完成后写 /etc/locale.conf
#（避免 Anaconda 42 严格解码 chroot 内的本地化输出）。
# =============================================================================

lang en_US.UTF-8
keyboard us
timezone Asia/Shanghai --utc

network --bootproto=dhcp --device=link --activate

# ---- livemedia-creator / Anaconda 组装磁盘镜像时需要 ----
# （装到用户硬盘仍由桌面 liveinst 完成；这里只服务 compose。）
shutdown
bootloader --location=none
clearpart --all --initlabel
reqpart
# 根文件系统镜像大小（MB）。不写时过小，桌面+firmware 装不下。
part / --fstype=ext4 --size=10240

firewall --enabled
selinux --enforcing
services --enabled=NetworkManager,gdm --disabled=sshd

# 关闭首启向导对 Live 用户的干扰；安装后的系统会由清理钩子重新打开
firstboot --disable

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/00-session-defaults.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/10-repos-noepol.ks

# =============================================================================
# 【模块】10 — Desktop 基础软件源（EPOL/noepol 共用）
# =============================================================================
# 安装树与基础仓指向 dist-oc9-desktop-build（Koji target dist-oc9-desktop）。
# webui-build/latest 已无 active repo，不能再当 url。
# EPOL 入口会另行叠加 10-repos-epol.ks。
# =============================================================================

url --url=https://build.opencloudos.tech/kojifiles/repos/dist-oc9-desktop-build/latest/$basearch/
repo --name=koji --baseurl=https://build.opencloudos.tech/kojifiles/repos/dist-oc9-desktop-build/latest/$basearch/

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/10-repos-noepol.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/10-repos-epol.ks

# =============================================================================
# 【模块】10 — EPOL 增量软件源
# =============================================================================
# 基础系统与 Anaconda 统一使用 modules/10-repos-noepol.ks 的 desktop-build 仓。
# 本模块只叠加 EPOL，提供 ungoogled-chromium、ibus-libpinyin、flatpak，
# 以及桌面扩展 / Orchis 主题 / 桌面整合 RPM。
# =============================================================================

repo --name=OC9EPOL --baseurl=https://mirrors.opencloudos.tech/epol/9/Everything/x86_64/os/

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/10-repos-epol.ks



# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/20-desktop-groups.ks

# =============================================================================
# 【模块】20-groups — 展开「Server with GUI」环境组（显式包名）
# =============================================================================
# dist-oc9-desktop-build 的 comps 只有 build / livemedia-build / srpm-build，
# 加不了 @Server with GUI。此处按 ts4/webui 组定义把成员写成 RPM 名。
# --ignoremissing：OpenCloudOS 9 没有的包名直接跳过。
# tencentos-release → opencloudos-release。
#
# 本文件只承载组展开，产品增量（浏览器、扩展、主题）仍在 20-desktop-base。
# =============================================================================

%packages --ignoremissing

# ---- group: base-x （Server with GUI → base-x）----
glx-utils
mesa-dri-drivers
plymouth-system-theme
xorg-x11-drv-evdev
xorg-x11-drv-fbdev
xorg-x11-drv-libinput
xorg-x11-drv-vmware
xorg-x11-drv-wacom
xorg-x11-server-Xorg
xorg-x11-xauth
xorg-x11-xinit
xorg-x11-xinit-session

# ---- group: Core ----
NetworkManager
NetworkManager-tui
audit
authselect
basesystem
bash
coreutils
cronie
crypto-policies
crypto-policies-scripts
curl
dnf
dnf-plugins-core
dracut-config-rescue
e2fsprogs
filesystem
firewalld
glibc
grubby
hostname
initscripts
initscripts-rename-device
iproute
iproute-tc
iprutils
iputils
irqbalance
kbd
kernel-tools
kexec-tools
less
libsysfs
linux-firmware
logrotate
lshw
lsscsi
man-db
microcode_ctl
ncurses
opencloudos-release
openssh-clients
openssh-server
p11-kit
parted
passwd
plymouth
policycoreutils
procps-ng
python3-libselinux
rootfiles
rpm
rpm-plugin-audit
rsyslog
selinux-policy-targeted
setup
sg3_utils
sg3_utils-libs
shadow-utils
sssd-common
sssd-kcm
sudo
systemd
tuned
util-linux
vim-minimal
xfsprogs
yum

# ---- group: Fonts ----
dejavu-fonts
abattis-cantarell-fonts
google-noto-emoji-color-fonts
google-noto-sans-cjk-ttc-fonts
google-noto-sans-gurmukhi-fonts
google-noto-sans-sinhala-vf-fonts
google-noto-serif-cjk-ttc-fonts
jomolhari-fonts
julietaula-montserrat-fonts
khmer-os-system-fonts
liberation-mono-fonts
liberation-sans-fonts
liberation-serif-fonts
lohit-assamese-fonts
lohit-bengali-fonts
lohit-devanagari-fonts
lohit-gujarati-fonts
lohit-kannada-fonts
lohit-odia-fonts
lohit-tamil-fonts
lohit-telugu-fonts
paktype-naskh-basic-fonts
pt-sans-fonts
sil-abyssinica-fonts
sil-nuosu-fonts
sil-padauk-fonts
smc-meera-fonts
stix-fonts

# ---- group: GNOME ----
ModemManager
NetworkManager-adsl
adobe-source-code-pro-fonts
at-spi2-atk
at-spi2-core
avahi
baobab
cheese
dconf
dejavu-fonts
eog
evince
fprintd-pam
gdm
gedit
glib-networking
glibc-all-langpacks
gnome-backgrounds
gnome-bluetooth
gnome-calculator
gnome-characters
gnome-classic-session
gnome-color-manager
gnome-control-center
gnome-disk-utility
gnome-font-viewer
gnome-initial-setup
gnome-logs
gnome-remote-desktop
gnome-screenshot
gnome-session-wayland-session
gnome-session-xsession
gnome-settings-daemon
gnome-shell
gnome-system-monitor
gnome-terminal
gnome-terminal-nautilus
gnome-user-docs
gvfs-fuse
gvfs-goa
gvfs-gphoto2
gvfs-mtp
gvfs-smb
libcanberra-gtk3
librsvg2
libsane-hpaio
mesa-dri-drivers
nautilus
orca
polkit
sane-backends-drivers-scanners
sushi
totem
tracker
tracker-miners
xdg-desktop-portal
xdg-desktop-portal-gnome
xdg-desktop-portal-gtk
xdg-user-dirs-gtk
yelp-tools

# ---- group: Standard ----
acl
at
attr
bash-completion
bc
blktrace
bpftool
bzip2
chrony
cpio
crontabs
cryptsetup
cyrus-sasl-plain
dbus
dos2unix
dosfstools
ed
ethtool
file
gnupg2
iptstate
irqbalance
kmod-kvdo
kpatch
kpatch-dnf
ledmon
libstoragemgmt
logrotate
lsof
lvm2
mailcap
man-pages
mcelog
mdadm
microcode_ctl
mlocate
mtr
nano
net-tools
nmap-ncat
nvme-cli
opencloudos-release
pciutils
plymouth
psacct
quota
realmd
rsync
rsyslog-gnutls
rsyslog-gssapi
smartmontools
sos
sssd
strace
sudo
symlinks
systemd-udev
tar
tcpdump
teamd
time
tree
unzip
usbutils
util-linux-user
vdo
vim-enhanced
virt-what
wget
which
words
xfsdump
zip

%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/20-desktop-groups.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/20-desktop-base-noepol.ks

# =============================================================================
# 【模块】20 — 桌面产品包（EPOL/noepol 共用）
# =============================================================================
# @Server with GUI / @core 已无法从 desktop-build comps 展开。
# 组内包名见 modules/packages/20-desktop-groups.ks；本文件只留产品增量。
# =============================================================================

%packages --ignoremissing
gdm
gnome-initial-setup
# 最终桌面应用；不能只依赖 anaconda-webui 间接拉入，否则清理安装器时会被 autoremove。
firefox
ungoogled-chromium
appstore-backend
appstore-frontend
NetworkManager
shadow-utils
glibc-langpack-zh

# 产品所需 GNOME 扩展、GTK 主题与桌面整合由软件源 RPM 安装（当前在 EPOL）。
# 桌面整合新版本仍需 gitee PR 流程入库，入库前勿回退 vendor 方案。
gnome-shell-extension-appindicator
gnome-shell-extension-arcmenu
gnome-shell-extension-blur-my-shell
gnome-shell-extension-clipboard-indicator
gnome-shell-extension-dash-to-panel
gnome-shell-extension-drive-menu
gnome-shell-extension-gtk4-ding
gnome-shell-extension-just-perfection
orchis-oc-gtk-theme
opencloudos-gnome-desktop-integration
# CJK 字体：简体 / 繁体 UI、文档与等宽代码显示。
# 包名沿用 RHEL 9 系命名；%packages 已带 --ignoremissing，构建环境仍应
# 用 repoquery 确认这些包均由当前 OpenCloudOS 源提供。
google-noto-sans-cjk-sc-fonts
google-noto-sans-cjk-tc-fonts
google-noto-serif-cjk-sc-fonts
google-noto-serif-cjk-tc-fonts
google-noto-sans-mono-cjk-sc-fonts

kernel
grub2
grub2-efi-x64
grub2-efi-x64-cdboot
# dist-oc9-webui 源里 Secure Boot 垫片叫 shim（无 shim-x64）；两个名字都列，
# --ignoremissing 会跳过不存在的那个，换源时不至于静默失去 Secure Boot 支持。
shim
shim-x64
efibootmgr
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/20-desktop-base-noepol.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/20-desktop-epol.ks

# =============================================================================
# 【模块】20 — EPOL 桌面增量包
# =============================================================================
# 基础桌面统一使用 modules/packages/20-desktop-base-noepol.ks。
# 本模块只添加 EPOL 应用与输入法；扩展、主题与桌面整合已在基础包清单中。
# =============================================================================

%packages --ignoremissing
ibus-libpinyin
flatpak
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/20-desktop-epol.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/21-hardware.ks

# =============================================================================
# 【模块】21 — 常用硬件支持包
# =============================================================================
# --ignoremissing：源里没有的包跳过，不中断 compose。
# =============================================================================

%packages --ignoremissing
# ---- 网络 / Wi-Fi ----
NetworkManager-wifi
NetworkManager-bluetooth
wpa_supplicant
wireless-regdb
iw
rfkill

# ---- 蓝牙 ----
bluez
bluez-cups
bluez-hid2hci
bluez-libs
bluez-obexd
gnome-bluetooth
gnome-bluetooth-libs
pulseaudio-module-bluetooth

# ---- Firmware（笔记本/台式机常见覆盖）----
linux-firmware
linux-firmware-whence
alsa-firmware
alsa-sof-firmware
alsa-tools-firmware
amd-gpu-firmware
amd-ucode-firmware
atheros-firmware
brcmfmac-firmware
cirrus-audio-firmware
dvb-firmware
intel-audio-firmware
intel-gpu-firmware
intel-vsc-firmware
iwlegacy-firmware
iwlwifi-dvm-firmware
iwlwifi-mld-firmware
iwlwifi-mvm-firmware
libertas-firmware
mt7xxx-firmware
netronome-firmware
nvidia-gpu-firmware
nxpwireless-firmware
qcom-accel-firmware
qcom-firmware
qcom-wwan-firmware
qed-firmware
realtek-firmware
tiwilink-firmware

# ---- 触控板 / 传感器 / 指纹 / 笔记本 I/O ----
libinput
xorg-x11-drv-libinput
libwacom
libwacom-data
iio-sensor-proxy
fprintd
fprintd-pam
bolt
upower
power-profiles-daemon
thermald
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/21-hardware.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/23-live-installer.ks

# =============================================================================
# 【模块】23 — Live 安装器 / Live 启动运行时
# =============================================================================
# 对齐 dist-oc9-webui 产品：anaconda-live（/usr/bin/liveinst + pkexec）
# + livesys-scripts（Live 会话）。装到硬盘后由清理钩子移除（见 post/33）。
# =============================================================================

%packages --ignoremissing
# ---- Anaconda + 官方 liveinst ----
anaconda
anaconda-core
anaconda-gui
anaconda-tui
anaconda-live
anaconda-webui
anaconda-install-env-deps

# ---- 引导工具（原 @anaconda-tools）----
# 该组在 x86_64 源里有 5 个 mandatory 成员不存在（grub2-efi、grub2-efi-aa64、
# grub2-efi-aa64-cdboot、grub2-efi-ia32、grub2-efi-ia32-cdboot），整组会被
# --ignoremissing 静默跳过。改为直接列本架构确实存在的包。
grub2-tools
grub2-tools-minimal
grub2-tools-extra
grub2-pc-modules
grubby
syslinux

# ---- Live 会话（官方 Live 介质常用）----
livesys-scripts

# ---- LiveOS / squashfs 启动 ----
dracut-live
dracut-squash
device-mapper
kpartx

# ---- Anaconda 存储栈插件 ----
libblockdev-dm
libblockdev-lvm
libblockdev-mpath
libblockdev-nvdimm

# ---- 会话辅助 ----
sudo
polkit
passwd
dbus-x11
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/packages/23-live-installer.ks



# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/15-live-user.ks

# =============================================================================
# 【模块】15 — Live 用户账户
# =============================================================================
# 说明：
#   - Live 会话使用无密码 liveuser，并加入 wheel，配合免密 sudo（见 post/30）。
#   - root 锁定，避免 Live 环境留下可用 root 密码。
#   - 安装到目标盘后，清理钩子会删除 liveuser，并打开 gnome-initial-setup。
# =============================================================================

rootpw --lock
user --name=liveuser --gecos="Live User" --groups=wheel --password="" --plaintext

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/15-live-user.ks



# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/30-live-session.ks

# =============================================================================
# 【模块】30 — Live 会话 %post
# =============================================================================
# 确保 liveuser 存在、清空密码、免密 sudo、GDM 自动登录、关 sshd、图形目标。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-30-live-session.log
set -eux
export LC_ALL=C.UTF-8 LANG=C.UTF-8

LIVE_USER="liveuser"

# ---- 账户：kickstart user 若未生效，这里补建 ----
if ! id "${LIVE_USER}" >/dev/null 2>&1; then
  # %post 默认 PATH 往往不含 /usr/sbin
  /usr/sbin/useradd -m -G wheel -c "Live User" "${LIVE_USER}"
fi
/usr/bin/passwd -d "${LIVE_USER}" >/dev/null || true

# ---- 免密 sudo（仅 Live；安装后由清理钩子删除）----
mkdir -p /etc/sudoers.d
cat > /etc/sudoers.d/99-opencloudos-live-user <<EOF
${LIVE_USER} ALL=(ALL) NOPASSWD: ALL
EOF
chmod 0440 /etc/sudoers.d/99-opencloudos-live-user

# ---- GDM：自动登录 liveuser，关闭 Live 上的首启向导 ----
mkdir -p /etc/gdm
cat > /etc/gdm/custom.conf <<EOF
[daemon]
AutomaticLoginEnable=True
AutomaticLogin=${LIVE_USER}
InitialSetupEnable=false
EOF

# ---- 服务策略（不用 systemctl，避免 chroot 里拖住宿主 /sys 挂载）----
mkdir -p /etc/systemd/system
ln -sfn /usr/lib/systemd/system/graphical.target /etc/systemd/system/default.target
rm -f /etc/systemd/system/multi-user.target.wants/sshd.service \
      /etc/systemd/system/sshd.service \
      /etc/systemd/system/sshd-keygen.target \
      /etc/systemd/system/multi-user.target.wants/sshd-keygen.target \
      2>/dev/null || true

# Live 会话中文与 IBus 收尾见本模块末尾；compose 期各 %post 一律
# 显式 LC_ALL=C.UTF-8，避免 Anaconda 42 对 chroot 命令输出做严格 UTF-8 解码时失败。

# ---- 对齐官方 livesys（若已装 livesys-scripts）----
if [[ -f /etc/sysconfig/livesys ]]; then
  sed -i 's/^livesys_session=.*/livesys_session="gnome"/' /etc/sysconfig/livesys || true
fi
if [[ -f /usr/lib/systemd/system/livesys.service ]]; then
  mkdir -p /etc/systemd/system/multi-user.target.wants
  ln -sfn /usr/lib/systemd/system/livesys.service \
    /etc/systemd/system/multi-user.target.wants/livesys.service
fi
if [[ -f /usr/lib/systemd/system/livesys-late.service ]]; then
  mkdir -p /etc/systemd/system/multi-user.target.wants
  ln -sfn /usr/lib/systemd/system/livesys-late.service \
    /etc/systemd/system/multi-user.target.wants/livesys-late.service
fi
# Live：/tmp 用 tmpfs（对齐 dist-oc9-webui 产品 kickstart）
if [[ -f /usr/lib/systemd/system/tmp.mount ]]; then
  mkdir -p /etc/systemd/system/local-fs.target.wants
  ln -sfn /usr/lib/systemd/system/tmp.mount \
    /etc/systemd/system/local-fs.target.wants/tmp.mount
fi
# Live overlay 上少写 /var/tmp（产品 Live / Fedora live 常见做法）
if ! grep -qE '^[[:space:]]*vartmp[[:space:]]+/var/tmp' /etc/fstab 2>/dev/null; then
  printf 'vartmp   /var/tmp    tmpfs   defaults   0  0\n' >> /etc/fstab
fi

# ---- Live 会话中文：在所有 compose 期 chroot 命令结束前不写 locale.conf，
# 避免 Anaconda/lmc 对 chroot 命令输出做严格 UTF-8 解码时失败（模块编号
# 31/34/35 在本模块之后，故放在这里仍安全——它们不再执行本地化命令）。
printf 'LANG=zh_CN.UTF-8\n' > /etc/locale.conf

# 统一 GTK、Qt 与 XIM 客户端的 IBus 发现方式。不设 dconf input-sources：
# Live 安装器对 ibus 输入源不兼容，正式系统由 post/31-epol-input-method 的
# 安装后 hook 配置。
mkdir -p /etc/environment.d
cat > /etc/environment.d/90-ibus.conf <<'EOF'
GTK_IM_MODULE=ibus
QT_IM_MODULE=ibus
XMODIFIERS=@im=ibus
EOF

# Live 镜像去掉固定 machine-id，首启再生成。compose 阶段已不再跑
# opencloudos-gnome-desktop-profile（桌面整合走 RPM，profile 改为首登
# autostart 执行），因此在此处清空是安全的。
rm -f /etc/machine-id
touch /etc/machine-id
rm -f /var/lib/dbus/machine-id
ln -sf /etc/machine-id /var/lib/dbus/machine-id

# 不改动 D-Bus provider：跟随发行版默认（OpenCloudOS 多为 dbus-broker）
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/30-live-session.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/31-gnome-extensions.ks

# =============================================================================
# 【模块】31 — GNOME 扩展：启用软件源 RPM
# =============================================================================
# 所需扩展由 modules/packages/20-desktop-base-noepol.ks 安装。
# Just Perfection 用于首登直接进入桌面而非 Overview。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-31-gnome-extensions.log
set -eux
export LC_ALL=C.UTF-8 LANG=C.UTF-8

JP_UUID="just-perfection-desktop@just-perfection"
[[ -f "/usr/share/gnome-shell/extensions/${JP_UUID}/metadata.json" ]] || {
  echo "ERROR: gnome-shell-extension-just-perfection was not installed" >&2
  exit 1
}

if [[ -d "/usr/share/gnome-shell/extensions/${JP_UUID}/schemas" ]]; then
  /usr/bin/glib-compile-schemas \
    "/usr/share/gnome-shell/extensions/${JP_UUID}/schemas"
fi

mkdir -p /etc/dconf/profile /etc/dconf/db/local.d

cat > /etc/dconf/profile/user <<'EOF'
user-db:user
system-db:local
EOF

cat > /etc/dconf/db/local.d/00-gnome-extensions <<'EOF'
[org/gnome/shell]
enabled-extensions=['dash-to-panel@jderose9.github.com', 'arcmenu@arcmenu.com', 'appindicatorsupport@rgcjonas.gmail.com', 'drive-menu@gnome-shell-extensions.gcampax.github.com', 'blur-my-shell@aunetx', 'just-perfection-desktop@just-perfection', 'gtk4-ding@smedius.gitlab.com', 'clipboard-indicator@tudmotu.com']
welcome-dialog-last-shown-version='9999'

[org/gnome/shell/extensions/just-perfection]
startup-status=0
EOF

if [[ -x /usr/bin/dconf ]]; then
  /usr/bin/dconf update
else
  echo "ERROR: dconf was not found in the image" >&2
  exit 1
fi

echo "GNOME extensions installed from RPM packages and enabled"
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/31-gnome-extensions.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/31-epol-input-method.ks

# =============================================================================
# 【模块】31 — EPOL 输入法（仅装机后生效）
# =============================================================================
# ibus-libpinyin 由 EPOL 包清单安装，本模块只在 EPOL 入口中引用。
#
# 不要在 Live 会话里把 ('ibus','libpinyin') 写进 input-sources：
# Anaconda 42 读 Live 输入源时只认 xkb，遇到 ibus 会直接报
# 「实时系统具有布局 libpinyin，无法用于安装」。
#
# 因此 Live 保持发行版默认（kickstart keyboard us）；装到硬盘后再通过
# Anaconda post-scripts 写入正式系统的 dconf 默认值。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-31-epol-input-method.log
set -eux
export LC_ALL=C.UTF-8 LANG=C.UTF-8

# 确保 Live 镜像里没有残留的 ibus 默认输入源配置。
rm -f /etc/dconf/db/local.d/02-epol-input-method
if [[ -x /usr/bin/dconf ]]; then
  /usr/bin/dconf update
fi

mkdir -p /usr/share/anaconda/post-scripts
HOOK=/usr/share/anaconda/post-scripts/zz-opencloudos-epol-input-method.ks
{
  echo '%post --log=/root/opencloudos-epol-input-method.log --erroronfail'
  cat <<'HOOKBODY'
mkdir -p /etc/dconf/db/local.d
cat > /etc/dconf/db/local.d/02-epol-input-method <<'EOF'
[org/gnome/desktop/input-sources]
sources=[('xkb', 'us'), ('ibus', 'libpinyin')]
EOF

if [ -x /usr/bin/dconf ]; then
  /usr/bin/dconf update
fi

rm -f /usr/share/anaconda/post-scripts/zz-opencloudos-epol-input-method.ks
HOOKBODY
  printf '%s\n' '%end'
} > "${HOOK}"
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/31-epol-input-method.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/34-orchis-oc-gtk-theme.ks

# =============================================================================
# 【模块】34 — orchis-oc-gtk-theme（RPM，在桌面整合之前）
# =============================================================================
# orchis-oc-gtk-theme 安装到 /usr/share/themes/Orchis-OC。
# 本模块设置系统默认 GTK 主题，并为 skel / liveuser 链接 GTK4 css。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-34-orchis-oc-gtk-theme.log
set -eux
export LC_ALL=C.UTF-8 LANG=C.UTF-8

THEME_NAME="Orchis-OC"
DST_THEME="/usr/share/themes/${THEME_NAME}"
LIVE_USER="liveuser"

[[ -s "${DST_THEME}/gtk-3.0/gtk.css" && -s "${DST_THEME}/gtk-4.0/gtk.css" ]] || {
  echo "ERROR: orchis-oc-gtk-theme was not installed: ${DST_THEME}" >&2
  exit 1
}

mkdir -p /etc/dconf/db/local.d
cat > /etc/dconf/db/local.d/01-orchis-oc-gtk-theme <<'EOF'
[org/gnome/desktop/interface]
gtk-theme='Orchis-OC'
EOF

if [[ -x /usr/bin/dconf ]]; then
  /usr/bin/dconf update
fi

link_gtk4() {
  local home="$1"
  local cfg="${home}/.config/gtk-4.0"
  mkdir -p "$cfg"
  ln -sfn "/usr/share/themes/${THEME_NAME}/gtk-4.0/gtk.css" "${cfg}/gtk.css"
  ln -sfn "/usr/share/themes/${THEME_NAME}/gtk-4.0/gtk-dark.css" "${cfg}/gtk-dark.css"
  ln -sfn "/usr/share/themes/${THEME_NAME}/gtk-4.0/assets" "${cfg}/assets"
}

link_gtk4 /etc/skel
if id -u "${LIVE_USER}" >/dev/null 2>&1; then
  link_gtk4 "/home/${LIVE_USER}"
  chown -R "${LIVE_USER}:${LIVE_USER}" "/home/${LIVE_USER}/.config" 2>/dev/null || true
fi

if command -v restorecon >/dev/null 2>&1; then
  restorecon -RF "$DST_THEME" /etc/dconf || true
fi

echo "Orchis-OC theme configured from orchis-oc-gtk-theme RPM"
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/34-orchis-oc-gtk-theme.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/35-oc-desktop-integration.ks

# =============================================================================
# 【模块】35 — opencloudos-gnome-desktop-integration（RPM，桌面侧最后收尾）
# =============================================================================
# 桌面整合由 %packages 从 EPOL 安装。当前 EPOL 是 0.1.0-1：只含扩展目录与
# profile 工具，不含系统 dconf 片段与 autostart（0.1.1 spec 才加入）。
# 本模块对缺失部分按 0.1.1 spec 同等内容补写（0.1.1 入库后 RPM 自带，
# 内容一致、幂等不冲突）；0.1.1 的 profile 支持 --enable-only，0.1.0 忽略
# 该参数且本身幂等，autostart Exec 两种版本通用。
# Live 特有收尾（locale.conf、machine-id、ibus env）在 post/30-live-session。
# orchis-oc-gtk-theme 由 post/34 配置；本模块在其后。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-35-desktop-integration.log
set -eux
export LC_ALL=C.UTF-8 LANG=C.UTF-8

UUID="opencloudos-desktop-integration@opencloudos.org"
EXT_DIR="/usr/share/gnome-shell/extensions/${UUID}"

# ---- 断言：扩展与 profile 工具必须由 RPM 提供 ----
[[ -f "${EXT_DIR}/metadata.json" ]] || {
  echo "ERROR: desktop integration extension is not installed" >&2
  exit 1
}
[[ -x /usr/bin/opencloudos-gnome-desktop-profile ]] || {
  echo "ERROR: opencloudos-gnome-desktop-profile is not installed" >&2
  exit 1
}

# ---- dconf 基础设施与系统默认值（0.1.0 缺，0.1.1 RPM 自带同名文件）----
mkdir -p /etc/dconf/profile /etc/dconf/db/local.d
if [[ ! -f /etc/dconf/profile/user ]]; then
  printf 'user-db:user\nsystem-db:local\n' > /etc/dconf/profile/user
elif ! grep -qx 'system-db:local' /etc/dconf/profile/user; then
  printf '\nsystem-db:local\n' >> /etc/dconf/profile/user
fi

if [[ ! -f /etc/dconf/db/local.d/00-opencloudos-gnome-desktop-integration ]]; then
  cat > /etc/dconf/db/local.d/00-opencloudos-gnome-desktop-integration <<'EOF'
[org/gnome/shell]
enabled-extensions=['dash-to-panel@jderose9.github.com', 'arcmenu@arcmenu.com', 'appindicatorsupport@rgcjonas.gmail.com', 'drive-menu@gnome-shell-extensions.gcampax.github.com', 'blur-my-shell@aunetx', 'just-perfection-desktop@just-perfection', 'gtk4-ding@smedius.gitlab.com', 'clipboard-indicator@tudmotu.com', 'opencloudos-desktop-integration@opencloudos.org']

[org/gnome/shell/extensions/just-perfection]
startup-status=0
EOF
fi

# ---- 每用户首登 autostart（0.1.0 缺，0.1.1 RPM 自带同名文件）----
if [[ ! -f /etc/xdg/autostart/opencloudos-desktop-profile-once.desktop ]]; then
  cat > /etc/xdg/autostart/opencloudos-desktop-profile-once.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=OpenCloudOS Desktop Profile
Comment=Enable the OpenCloudOS desktop extensions and apply defaults
Exec=sh -c '/usr/bin/opencloudos-gnome-desktop-profile --enable-only || exit 0; stamp="$HOME/.config/opencloudos-gnome-desktop-profile.stamp"; [ -f "$stamp" ] && exit 0; /usr/bin/opencloudos-gnome-desktop-profile || exit 0; mkdir -p "$HOME/.config" && touch "$stamp"'
OnlyShowIn=GNOME;
X-GNOME-Autostart-enabled=true
EOF
fi

if [[ -x /usr/bin/dconf ]]; then
  /usr/bin/dconf update
fi

echo "OpenCloudOS GNOME desktop integration verified (RPM + profile wiring)"
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/35-oc-desktop-integration.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/32-live-installer.ks

# =============================================================================
# 【模块】32 — Live 安装器校验
# =============================================================================
# 保留 anaconda-live 自带的“安装到硬盘”启动器，并为它配置 Live 专用 profile。
# 不创建旧的“安装 OpenCloudOS”封装启动器，避免出现两个安装图标。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-32-live-installer.log
set -eux
export LC_ALL=C.UTF-8 LANG=C.UTF-8

LIVE_USER="liveuser"
LIVEINST=""
for candidate in /usr/bin/liveinst /usr/sbin/liveinst; do
  if [[ -x "$candidate" ]]; then
    LIVEINST="$candidate"
    break
  fi
done

# --ignoremissing 是 pykickstart 的全局开关；源中缺少 anaconda-live 时，
# 在 compose 阶段失败，避免产出没有“安装到硬盘”的 Live ISO。
if [[ -z "$LIVEINST" ]]; then
  echo "ERROR: liveinst is missing; anaconda-live was not installed" >&2
  echo "确认软件源提供 anaconda-live（提供 /usr/bin/liveinst）" >&2
  exit 1
fi

mkdir -p /etc/anaconda/profile.d /etc/anaconda/conf.d \
  /etc/xdg/autostart /home/"${LIVE_USER}"/Desktop

# ---- Anaconda UI：Live 安装只暴露存储等必要 spoke ----
cat > /etc/anaconda/profile.d/opencloudos-live-desktop.conf <<'EOF'
# OpenCloudOS Live Desktop 安装器配置
# 语言/键盘/网络/时间在 Live 会话已有默认；用户账户留给安装后首启向导。

[Profile]
profile_id = opencloudos-live-desktop
base_profile = opencloudos

[User Interface]
hidden_spokes =
    NetworkSpoke
    PasswordSpoke
    UserSpoke
    DatetimeSpoke
    KeyboardSpoke
    LangsupportSpoke
    SourceSpoke
    SoftwareSelectionSpoke
    SubscriptionSpoke

hidden_webui_pages =
    anaconda-screen-accounts
EOF

# Anaconda 42 会在 profile 之后加载 conf.d；这里全局隐藏账户页，
# 因此从发行版自带的“安装到硬盘”入口启动时同样生效。
cat > /etc/anaconda/conf.d/99-opencloudos-live-desktop.conf <<'EOF'
[User Interface]
hidden_webui_pages =
    anaconda-screen-accounts
EOF

# 保留上游名称、图标和 desktop 文件，只给它追加 Live profile 参数。
LIVEINST_DESKTOP=/usr/share/applications/liveinst.desktop
[[ -f "$LIVEINST_DESKTOP" ]] || {
  echo "ERROR: liveinst desktop launcher is missing: $LIVEINST_DESKTOP" >&2
  exit 1
}
sed -i -E "s|^Exec=.*|Exec=${LIVEINST} --profile opencloudos-live-desktop|" \
  "$LIVEINST_DESKTOP"

# 不依赖 liveinst-setup 的首登时机，compose 时即投放到 Live 桌面。
install -m 0755 "$LIVEINST_DESKTOP" \
  "/home/${LIVE_USER}/Desktop/liveinst.desktop"
chown "${LIVE_USER}:${LIVE_USER}" "/home/${LIVE_USER}/Desktop/liveinst.desktop"

cat > /etc/xdg/autostart/opencloudos-liveinst-trust.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Trust OpenCloudOS Live Installer Launcher
Exec=sh -c 'gio set "$HOME/Desktop/liveinst.desktop" metadata::trusted true 2>/dev/null || true'
OnlyShowIn=GNOME;
NoDisplay=true
X-GNOME-Autostart-enabled=true
EOF
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/32-live-installer.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/36-desktop-shortcuts.ks

# =============================================================================
# 【模块】36 — Live 与安装后桌面应用快捷方式
# =============================================================================
# DING 只显示 Desktop 目录里的启动器；RPM 的应用菜单条目需要显式投放。
# 同时写入 /etc/skel，保证安装后由 GNOME Initial Setup 创建的新用户也继承它们。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-36-desktop-shortcuts.log
set -eux

LIVE_USER="liveuser"
LIVE_DESKTOP="/home/${LIVE_USER}/Desktop"
SKEL_DESKTOP="/etc/skel/Desktop"
mkdir -p "$LIVE_DESKTOP" "$SKEL_DESKTOP"

for launcher in \
  firefox.desktop \
  ungoogled-chromium.desktop \
  softcenter.desktop
do
  source="/usr/share/applications/${launcher}"
  [[ -f "$source" ]] || continue
  install -m 0755 "$source" "$LIVE_DESKTOP/$launcher"
  install -m 0755 "$source" "$SKEL_DESKTOP/$launcher"
  chown "${LIVE_USER}:${LIVE_USER}" "$LIVE_DESKTOP/$launcher"
done

# GNOME/DING 仅信任带 metadata::trusted 标记的桌面启动器。该 autostart
# 保留到硬盘系统，使从 /etc/skel 继承启动器的新用户也会被自动信任。
mkdir -p /etc/xdg/autostart
cat > /etc/xdg/autostart/opencloudos-desktop-shortcuts-trust.desktop <<'EOF'
[Desktop Entry]
Type=Application
Name=Trust OpenCloudOS Desktop Shortcuts
Exec=sh -c 'for f in "$HOME"/Desktop/firefox.desktop "$HOME"/Desktop/ungoogled-chromium.desktop "$HOME"/Desktop/softcenter.desktop; do [ -f "$f" ] && gio set "$f" metadata::trusted true 2>/dev/null || true; done'
OnlyShowIn=GNOME;
NoDisplay=true
X-GNOME-Autostart-enabled=true
EOF
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/36-desktop-shortcuts.ks


# >>> BEGIN include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/33-install-cleanup-hook.ks

# =============================================================================
# 【模块】33 — 安装后清理（Anaconda 钩子 + 首次硬盘启动兜底）
# =============================================================================
# Anaconda 支持读取 /usr/share/anaconda/post-scripts/*.ks，但部分 OC9
# 版本在把 Kickstart 交给 runtime 模块后才追加这些片段，导致片段看似已读取、
# 实际没有执行。这里保留安装期钩子，同时启用一次性 systemd 服务兜底：
#
#   1. 若安装期钩子正常执行，立即清理目标系统，并顺带删除兜底服务。
#   2. 若钩子未执行，目标系统第一次从硬盘启动时，在 livesys/GDM 之前清理。
#   3. Live 启动通过 rd.live.image、root=live:、/run/initramfs/live 和
#      /dev/mapper/live-* 识别，兜底服务不会误删正在试用的 Live 会话。
#
# 注意：不能在本 %post 里用 heredoc 直接写裸的「%post / %end」行，
# pykickstart 会把它们当成当前 Kickstart 的分段符。因此钩子的头尾仍用
# echo/printf 生成。
# =============================================================================

%post --erroronfail --log=/root/oc-live-compose-33-cleanup-hook.log
set -eux
export LC_ALL=C.UTF-8 LANG=C.UTF-8

CLEANUP=/usr/local/sbin/opencloudos-installed-system-cleanup
SERVICE=/etc/systemd/system/opencloudos-installed-system-cleanup.service

mkdir -p /usr/local/sbin /usr/share/anaconda/post-scripts \
  /etc/systemd/system/multi-user.target.wants

# ---- 唯一清理实现：安装期钩子和首次硬盘启动服务共用，避免两份逻辑漂移 ----
cat > "${CLEANUP}" <<'CLEANUPEOF'
#!/usr/bin/env bash
set -u

LIVE_USER="liveuser"
SERVICE_NAME="opencloudos-installed-system-cleanup.service"
CLEANUP_PATH="/usr/local/sbin/opencloudos-installed-system-cleanup"
FIRST_BOOT=0

is_live_boot() {
  [[ -e /run/initramfs/live ]] && return 0

  if grep -Eq '(^|[[:space:]])(rd\.live\.image(=([^[:space:]]*)?)?|root=live:)' \
      /proc/cmdline 2>/dev/null; then
    return 0
  fi

  local root_source
  root_source="$(findmnt -n -o SOURCE / 2>/dev/null || true)"
  [[ "${root_source}" == /dev/mapper/live-* ]] && return 0

  return 1
}

case "${1:-}" in
  --check-installed)
    # systemd ExecCondition：Live 环境返回 1（跳过），硬盘系统返回 0（执行）。
    is_live_boot && exit 1
    exit 0
    ;;
  --installed)
    # Anaconda 的目标系统 %post 已经在 chroot 中，明确绕过 Live 启动判断。
    ;;
  --installed-first-boot)
    # 只有真实硬盘启动才允许调用 systemctl，避免安装期 chroot 误连 Live systemd。
    FIRST_BOOT=1
    ;;
  *)
    echo "Usage: ${0} --check-installed | --installed | --installed-first-boot" >&2
    exit 2
    ;;
esac

mkdir -p /var/log
exec >>/var/log/opencloudos-installed-system-cleanup.log 2>&1
set -x
echo "Removing temporary Live configuration from the installed system"

# ---- 先阻止 livesys/GDM 使用 Live 配置 ----
# 首次硬盘启动时，livesys 的 start job 可能已经随 multi-user.target 排队；
# stop 会取消该 job，runtime mask 则防止本次启动中被其他单元再次拉起。
if (( FIRST_BOOT )); then
  systemctl stop livesys.service livesys-late.service 2>/dev/null || true
  systemctl mask --runtime livesys.service livesys-late.service 2>/dev/null || true
fi
rm -f /etc/systemd/system/multi-user.target.wants/livesys.service
rm -f /etc/systemd/system/multi-user.target.wants/livesys-late.service
rm -f /etc/systemd/system/livesys.service
rm -f /etc/systemd/system/livesys-late.service
rm -f /etc/sysconfig/livesys

mkdir -p /etc/gdm
cat > /etc/gdm/custom.conf <<'GDMEOF'
[daemon]
InitialSetupEnable=true
GDMEOF

# ---- 删除 Live 专用用户与提权配置 ----
if id "${LIVE_USER}" >/dev/null 2>&1; then
  userdel -r "${LIVE_USER}" 2>/dev/null || userdel "${LIVE_USER}" 2>/dev/null || true
fi
rm -rf -- "/home/${LIVE_USER}"
rm -f "/var/lib/AccountsService/users/${LIVE_USER}"
rm -f /etc/sudoers.d/99-opencloudos-live-user

# ---- 删除自定义与发行版自带的安装入口 ----
rm -f /usr/local/bin/opencloudos-liveinst
rm -f /usr/share/applications/opencloudos-liveinst.desktop
rm -f /etc/xdg/autostart/opencloudos-liveinst-trust.desktop
rm -f /etc/anaconda/profile.d/opencloudos-live-desktop.conf
rm -f /etc/anaconda/conf.d/99-opencloudos-live-desktop.conf
rm -f /home/*/Desktop/opencloudos-liveinst.desktop 2>/dev/null || true
rm -f /home/*/Desktop/liveinst.desktop 2>/dev/null || true
rm -f /tmp/opencloudos-liveinst.log

# Live 专用 /var/tmp tmpfs 不要带到装机系统。
sed -i '/^[[:space:]]*vartmp[[:space:]]\+\/var\/tmp[[:space:]]/d' \
  /etc/fstab 2>/dev/null || true

passwd -l root 2>/dev/null || true
rm -f /etc/skel/.config/gnome-initial-setup-done
find /home -name gnome-initial-setup-done -delete 2>/dev/null || true

# ---- 移除仅 Live 需要的安装器 / Live 启动包 ----
if command -v dnf >/dev/null 2>&1; then
  # anaconda-webui depends on Firefox. Only remove the named Live packages;
  # dependency autoremove would otherwise delete Firefox from the installed desktop.
  dnf -y --setopt=clean_requirements_on_remove=False remove \
    anaconda anaconda-core anaconda-gui anaconda-tui anaconda-widgets \
    anaconda-live anaconda-webui anaconda-install-env-deps livesys-scripts \
    dracut-live dracut-squash gnome-tour || true
fi

# 即使 RPM 事务受依赖关系阻止，也不要在应用菜单里留下安装入口。
rm -f /usr/bin/liveinst /usr/sbin/liveinst
rm -f /usr/share/applications/liveinst.desktop
rm -f /etc/xdg/autostart/liveinst-setup.desktop
rm -f /usr/libexec/liveinst-setup.sh
rm -f /usr/share/polkit-1/actions/org.fedoraproject.pkexec.liveinst.policy

ln -sfn /usr/lib/systemd/system/graphical.target /etc/systemd/system/default.target

# ---- 成功走到末尾后自删除；若中途被杀，下次启动仍可重试 ----
rm -f "/etc/systemd/system/multi-user.target.wants/${SERVICE_NAME}"
rm -f "/etc/systemd/system/${SERVICE_NAME}"
rm -f /usr/share/anaconda/post-scripts/opencloudos-live-cleanup.ks
rm -f /usr/share/anaconda/post-scripts/zz-opencloudos-live-cleanup.ks
rm -f "${CLEANUP_PATH}"
if (( FIRST_BOOT )); then
  systemctl daemon-reload 2>/dev/null || true
fi
echo "Live configuration cleanup completed"
CLEANUPEOF
chmod 0755 "${CLEANUP}"

# ---- 首次从硬盘启动的兜底服务：必须早于 livesys 和显示管理器 ----
cat > "${SERVICE}" <<EOF
[Unit]
Description=Remove OpenCloudOS Live session configuration after installation
After=local-fs.target
Before=livesys.service livesys-late.service display-manager.service gdm.service

[Service]
Type=oneshot
ExecCondition=${CLEANUP} --check-installed
ExecStart=${CLEANUP} --installed-first-boot

[Install]
WantedBy=multi-user.target
EOF

ln -sfn "${SERVICE}" \
  /etc/systemd/system/multi-user.target.wants/opencloudos-installed-system-cleanup.service

# ---- Anaconda 安装期快速路径；zz 前缀确保在内置 post-scripts 之后执行 ----
rm -f /usr/share/anaconda/post-scripts/opencloudos-live-cleanup.ks
HOOK=/usr/share/anaconda/post-scripts/zz-opencloudos-live-cleanup.ks
{
  echo '%post --log=/root/opencloudos-live-cleanup.log --erroronfail'
  cat <<'HOOKBODY'
if [ -x /usr/local/sbin/opencloudos-installed-system-cleanup ]; then
  /usr/local/sbin/opencloudos-installed-system-cleanup --installed
fi
HOOKBODY
  printf '%s\n' '%end'
} > "${HOOK}"
%end

# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/modules/post/33-install-cleanup-hook.ks


# <<< END include: /ssd/desktop-image-bot/workspace/oc-live-compose/kickstarts/desktop-live.ks

