forked from pisilinux-rs/yali-rs
refactor: squashfs akışına uygun sihirbazı daralt, DM tespitini çalışma zamanına al
YALI kurulu sistemi ISO'nun squashfs'inden kopyalar (CopyFilesJob rsync).
Bu yüzden ISO'da hangi paketler, ekran yöneticisi ve masaüstü ortamı
varsa kurulum onları ZATEN içerir. Sihirbazın bunları seçmesi
anlamsızdı: kullanıcının seçimi kopyalama sırasında ezilecekti.
## 1. Sihirbaz 13 → 10 adım
LicenseStep, DisplayManagerStep ve NetinstallStep listeden çıkarıldı.
Silinmedi: steps/mod.rs'te tanımlı, derleniyor, hazır. Her biri için
etkinleştirme koşulu mod.rs'te yazılı (netinstall için ayrıca
selected_package_groups doldurulmalı ve InstallExtraPackagesJob
kuyruğa alınmalı). İzin, 22de7d5'in yaptığının tersine SADECE bu üç
modüle ve SADECE belgelenmiş kasıtlı uyku için kondu — modül
dışındaki taze ölü kod yine uyarı üretir.
## 2. ConfigureAutologinJob ISO'nun DM'ini eziyordu
Alanın doc yorumu "yapılandırma ISO'da hazır olduğu için burada
değiştirilmez" diyordu; kod tam tersini yapıyordu. state.display_manager
GlobalState'in SABİT "sddm" varsayılanı (kullanıcı seçemiyor), ona
göre dallanılıyordu. ISO lightdm kullanıyorsa lightdm.conf'a hiç
dokunulmaz, sddm.conf yazılır ve otomatik giriş sessizce çalışmazdı.
- detect_display_manager(): hedefte hangi DM'in kurulu olduğunu
çalışma zamanında arar (/usr/bin/<dm>, yoksa yapılandırma dizini).
Bu iş CopyFilesJob'dan sonra çalıştığı için mount doludur.
- sddm config dizini: /usr/lib/sddm/sddm.conf.d yoksa
/etc/sddm.conf.d deniyor; ikisi de yoksa hata (sessizce yanlış
yere yazmak yerine).
- lightdm'de autologin-session ham DE adıyla ("plasma") yazılıyordu;
sddm/gdm'nin kullandığı .desktop eşlemesi (session_desktop_file)
kullanılıyor. lightdm oturumu dosya adıyla arar, "plasma" ile
oturum açılmazdı.
- DM bulunamazsa hata veriyor (kullanıcıya "elle yapılandırın"
diyebilmeli), eskiden sadece uyarıp geçiyordu.
## 3. Özet ekranı doğru bilgiyi gösteriyor
state.display_manager sabitini olduğu gibi gösteriyordu → ISO
lightdm iken "sddm" yazıyordu. Artık yalnızca kullanıcının gerçekten
belirlediği şey (otomatik giriş açık/kapalı) gösteriliyor ve DM'in
görüntüden geldiği belirtiliyor. Yanındaki hardcoded İngilizce
parçalar ("password protected", "manual login") de t!() altına alındı.
## 4. Cevap dosyasında (auto-install) sabit değerler
JobQueueConfig alanları answer file'dan hiç okunmuyordu; hepsi
main.rs'te yazılmıştı: display_manager "sddm", desktop_environment
"plasma", autologin TRUE, root_password boş, bootloader_timeout 5.
- İsteğe bağlı [system] bölümü eklendi: autologin, bootloader_*
ve kernel_options. [user]'a root_password.
- autologin varsayılanı true → false. Gözetimsiz kurulumda açık
olması, kurulan sistemde konsola erişebilen herkesin kullanıcı adını
görmesini ve oturumu açmasını kolaylaştırıyordu.
- desktop_environment artık SABİT "plasma" değil, GlobalState'in
canlı ortam tespiti. XFCE ISO'sunda Plasma oturumu açılmaya
çalışılıyordu.
- answer-example.toml güncellendi, iki dilde açıklama eklendi.
### Bulunan ve düzeltilen tuzak
SystemConfig #[derive(Default)] ile 0 döndürüyordu. [system] bloğu
dosyada HİÇ YOKSA serde alan bazlı `#[serde(default = "...")]`
anotasyonlarına uğramaz, doğrudan Default::default() çağırır — yani
GRUB bekleme süresi 0 saniye olurdu ve kurulumda bootloader menüsü
hiç görünmezdi. Default elle uygulandı; regresyon testi eklendi.
## 5. Testler
+7: autologin (2), answer file ayrıştırma (4, biri depodaki gerçek
dosyayı ayrıştırıyor, biri varsayılan tuzağını kilitliyor),
wizard (zaten 4'tü).
cargo check --all-targets : 0 hata, 0 uyarı
cargo test : 55/55 geçti (47 → 55)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,8 @@ Rust ve egui ile yeniden yazılmış **Pisi GNU/Linux** kurulum aracı. YALI, ca
|
|||||||
|
|
||||||
## Özellikler
|
## Özellikler
|
||||||
|
|
||||||
- **13 adımlı kurulum sihirbazı**: Hoş Geldiniz → Lisans → Konum → Klavye → Ağ → Disk Bölümleme → Kullanıcılar → Ekran Yöneticisi → Bootloader → Ek Paketler → Özet → Kurulum → Bitir
|
- **10 adımlı kurulum sihirbazı**: Hoş Geldiniz → Konum → Klavye → Ağ → Disk Bölümleme → Kullanıcılar → Bootloader → Özet → Kurulum → Bitir
|
||||||
|
- **Squashfs tabanlı**: kurulu sistem ISO'nun squashfs'inden kopyanır, paketler ağdan kurulmaz. Ekran yöneticisi, masaüstü ortamı ve paketler ISO'da geldiği için sihirbaz bunları **seçmez** (seçseydi kopyalama zaten ezdiği için yanıltıcı olurdu)
|
||||||
- **İki mod**: Grafik arayüz (varsayılan) ve cevap dosyasıyla otomatik kurulum (`--auto-install answer.toml`)
|
- **İki mod**: Grafik arayüz (varsayılan) ve cevap dosyasıyla otomatik kurulum (`--auto-install answer.toml`)
|
||||||
- **Demo modu**: Sistem kontrollerini atlar, kurulumu simüle eder (`--demo`)
|
- **Demo modu**: Sistem kontrollerini atlar, kurulumu simüle eder (`--demo`)
|
||||||
- **Disk bölümleme**: Otomatik (GPT/MBR) veya manuel, LVM ve LUKS şifreleme desteği
|
- **Disk bölümleme**: Otomatik (GPT/MBR) veya manuel, LVM ve LUKS şifreleme desteği
|
||||||
@@ -94,18 +95,15 @@ cargo run --bin slides_test [desktop] [lang]
|
|||||||
## Kurulum İş Akışı
|
## Kurulum İş Akışı
|
||||||
|
|
||||||
1. **Hoş Geldiniz** — Dil seçimi, sistem kontrolleri, kurtarma modu
|
1. **Hoş Geldiniz** — Dil seçimi, sistem kontrolleri, kurtarma modu
|
||||||
2. **Lisans** — GPL metni ve kabul onayı
|
2. **Konum / Zaman** — Saat dilimi seçimi (bölge/alan çift ComboBox), GeoIP, NTP veya manuel tarih/saat
|
||||||
3. **Konum / Zaman** — Saat dilimi seçimi (bölge/alan çift ComboBox), GeoIP, NTP veya manuel tarih/saat
|
3. **Klavye** — Düzen/varyant seçimi, arama, canlı önizleme (setxkbmap)
|
||||||
4. **Klavye** — Düzen/varyant seçimi, arama, canlı önizleme (setxkbmap)
|
4. **Ağ** — WiFi tarama, bağlantı, proxy
|
||||||
5. **Ağ** — WiFi tarama, bağlantı, proxy
|
5. **Disk Bölümleme** — Otomatik (rehberli) veya manuel, LVM, LUKS
|
||||||
6. **Disk Bölümleme** — Otomatik (rehberli) veya manuel, LVM, LUKS
|
6. **Kullanıcılar** — Hesap oluşturma, parola gücü göstergesi, root parolası, otomatik oturum açma
|
||||||
7. **Kullanıcılar** — Hesap oluşturma, parola gücü göstergesi, root parolası, otomatik oturum açma
|
7. **Bootloader** — GRUB aygıtı, zaman aşımı, parola, çekirdek parametreleri
|
||||||
8. **Ekran Yöneticisi** — DM ve masaüstü ortamı seçimi
|
8. **Özet** — Tüm seçimlerin gözden geçirilmesi
|
||||||
9. **Bootloader** — GRUB aygıtı, zaman aşımı, parola, çekirdek parametreleri
|
9. **Kurulum** — Slayt + ilerleme çubuğu + canlı log
|
||||||
10. **Ek Paketler** — Paket grubu seçimi (ofis, multimedya, geliştirme, …)
|
10. **Bitir** — Başarılı kurulum, yeniden başlat veya canlı masaüstüne dön
|
||||||
11. **Özet** — Tüm seçimlerin gözden geçirilmesi
|
|
||||||
12. **Kurulum** — Slayt + ilerleme çubuğu + canlı log
|
|
||||||
13. **Bitir** — Başarılı kurulum, yeniden başlat veya canlı masaüstüne dön
|
|
||||||
|
|
||||||
## Bağımlılıklar
|
## Bağımlılıklar
|
||||||
|
|
||||||
|
|||||||
+11
-13
@@ -4,7 +4,8 @@ A rewritten **Pisi GNU/Linux** installation tool in Rust and egui. YALI installs
|
|||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **13-step installation wizard**: Welcome → License → Location → Keyboard → Network → Disk Partitioning → Users → Display Manager → Bootloader → Extra Packages → Summary → Installation → Finish
|
- **10-step installation wizard**: Welcome → Location → Keyboard → Network → Disk Partitioning → Users → Bootloader → Summary → Installation → Finish
|
||||||
|
- **Squashfs-based**: the installed system is copied from the ISO's squashfs, packages are not fetched over the network. The display manager, desktop environment and packages come from the ISO, so the wizard does **not** offer them (offering them would be misleading, since the copy would overwrite the choice)
|
||||||
- **Two modes**: Graphical interface (default) and automatic installation with answer file (`--auto-install answer.toml`)
|
- **Two modes**: Graphical interface (default) and automatic installation with answer file (`--auto-install answer.toml`)
|
||||||
- **Demo mode**: Skips system checks, simulates installation (`--demo`)
|
- **Demo mode**: Skips system checks, simulates installation (`--demo`)
|
||||||
- **Disk partitioning**: Automatic (GPT/MBR) or manual, LVM and LUKS encryption support
|
- **Disk partitioning**: Automatic (GPT/MBR) or manual, LVM and LUKS encryption support
|
||||||
@@ -92,18 +93,15 @@ cargo run --bin slides_test [desktop] [lang]
|
|||||||
## Installation Workflow
|
## Installation Workflow
|
||||||
|
|
||||||
1. **Welcome** — Language selection, system checks, rescue mode
|
1. **Welcome** — Language selection, system checks, rescue mode
|
||||||
2. **License** — GPL text and acceptance
|
2. **Location / Time** — Timezone selection (region/area dual ComboBox), GeoIP, NTP or manual date/time
|
||||||
3. **Location / Time** — Timezone selection (region/area dual ComboBox), GeoIP, NTP or manual date/time
|
3. **Keyboard** — Layout/variant selection, search, live preview (setxkbmap)
|
||||||
4. **Keyboard** — Layout/variant selection, search, live preview (setxkbmap)
|
4. **Network** — WiFi scanning, connection, proxy
|
||||||
5. **Network** — WiFi scanning, connection, proxy
|
5. **Disk Partitioning** — Automatic (guided) or manual, LVM, LUKS
|
||||||
6. **Disk Partitioning** — Automatic (guided) or manual, LVM, LUKS
|
6. **Users** — Account creation, password strength indicator, root password, autologin
|
||||||
7. **Users** — Account creation, password strength indicator, root password, autologin
|
7. **Bootloader** — GRUB device, timeout, password, kernel parameters
|
||||||
8. **Display Manager** — DM and desktop environment selection
|
8. **Summary** — Review all selections
|
||||||
9. **Bootloader** — GRUB device, timeout, password, kernel parameters
|
9. **Installation** — Slideshow + progress bar + live log
|
||||||
10. **Extra Packages** — Package group selection (office, multimedia, development, …)
|
10. **Finish** — Successful installation, reboot or return to live desktop
|
||||||
11. **Summary** — Review all selections
|
|
||||||
12. **Installation** — Slideshow + progress bar + live log
|
|
||||||
13. **Finish** — Successful installation, reboot or return to live desktop
|
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
|
|||||||
@@ -36,3 +36,36 @@ password = "changeme123"
|
|||||||
|
|
||||||
# Bilgisayar adı: harf, rakam ve - ; tire ile başlayamaz/bitemez
|
# Bilgisayar adı: harf, rakam ve - ; tire ile başlayamaz/bitemez
|
||||||
hostname = "pisilinux"
|
hostname = "pisilinux"
|
||||||
|
|
||||||
|
# Kök parolası (isteğe bağlı).
|
||||||
|
# Boş bırakılırsa kök hesap KİLİTLENİR (passwd -l root).
|
||||||
|
root_password = ""
|
||||||
|
|
||||||
|
|
||||||
|
# ─────────────────────────────────────────────
|
||||||
|
# [system] — tamamen isteğe bağlı.
|
||||||
|
# Bu bölümü hiç yazmazsanız tüm ayarlar güvenli varsayılanlarda kalır.
|
||||||
|
# ─────────────────────────────────────────────
|
||||||
|
[system]
|
||||||
|
# Otomatik oturum açma (varsayılan: false).
|
||||||
|
#
|
||||||
|
# Gözetimsiz kurulumda açık bırakmayın: kurulan sistemde konsola
|
||||||
|
# erişebilen herkes giriş ekranında kullanıcı adını görür ve
|
||||||
|
# oturumu açabilir. Ekran yöneticisi ISO'dan gelir; bu ayar yalnızca
|
||||||
|
# mevcut oturum yöneticisine "bu kullanıcıyı otomatik aç" yazar.
|
||||||
|
autologin = false
|
||||||
|
|
||||||
|
# GRUB menü bekleme süresi, saniye (varsayılan: 5)
|
||||||
|
bootloader_timeout = 5
|
||||||
|
|
||||||
|
# GRUB parolası (isteğe bağlı). Hedefte PBKDF2 ile hashlenir.
|
||||||
|
# UYARI: Bu dosyayı güvenli tutun; düz metin olarak saklanır.
|
||||||
|
bootloader_password = ""
|
||||||
|
|
||||||
|
# Ek çekirdek parametreleri (ör. "quiet splash nomodeset")
|
||||||
|
kernel_options = ""
|
||||||
|
|
||||||
|
# NOT: Ekran yöneticisi ve masaüstü ortamı BU DOSYADA AYARLANMAZ.
|
||||||
|
# YALI kurulu sistemi ISO'nun squashfs'inden kopyar, dolayısıyla
|
||||||
|
# bunlar zaten görüntüde bulunurlar; kurulum anında otomatik tespit
|
||||||
|
# edilirler. Ek paket kurma (netinstall) da bu akışın parçası değildir.
|
||||||
|
|||||||
@@ -128,6 +128,10 @@ summary_software = "Software"
|
|||||||
summary_display_manager = "Display Manager"
|
summary_display_manager = "Display Manager"
|
||||||
summary_autologin = "Autologin"
|
summary_autologin = "Autologin"
|
||||||
summary_autologin_user = "Autologin User"
|
summary_autologin_user = "Autologin User"
|
||||||
|
summary_autologin_on = "On"
|
||||||
|
summary_autologin_off = "Off (password login)"
|
||||||
|
summary_bootloader_password = "password protected"
|
||||||
|
summary_desktop_from_image = "Comes from the ISO image; detected automatically during install"
|
||||||
summary_desktop = "Desktop"
|
summary_desktop = "Desktop"
|
||||||
|
|
||||||
# ── Display Manager ───────────────────────────────
|
# ── Display Manager ───────────────────────────────
|
||||||
|
|||||||
@@ -285,6 +285,10 @@ summary_software = "Yazılım"
|
|||||||
summary_display_manager = "Görüntü Yöneticisi"
|
summary_display_manager = "Görüntü Yöneticisi"
|
||||||
summary_autologin = "Otomatik oturum açma"
|
summary_autologin = "Otomatik oturum açma"
|
||||||
summary_autologin_user = "Otomatik oturum açılacak kullanıcı"
|
summary_autologin_user = "Otomatik oturum açılacak kullanıcı"
|
||||||
|
summary_autologin_on = "Açık"
|
||||||
|
summary_autologin_off = "Kapalı (parola ile giriş)"
|
||||||
|
summary_bootloader_password = "parola korumalı"
|
||||||
|
summary_desktop_from_image = "ISO görüntüsünden gelir; kurulumda otomatik tespit edilir"
|
||||||
summary_desktop = "Masaüstü"
|
summary_desktop = "Masaüstü"
|
||||||
|
|
||||||
# ── Görüntü Yöneticisi ───────────────────────────────────────
|
# ── Görüntü Yöneticisi ───────────────────────────────────────
|
||||||
|
|||||||
@@ -33,6 +33,53 @@ pub struct UserConfig {
|
|||||||
pub password: String,
|
pub password: String,
|
||||||
#[serde(default = "default_hostname")]
|
#[serde(default = "default_hostname")]
|
||||||
pub hostname: String,
|
pub hostname: String,
|
||||||
|
/// Kök hesabın parolası. Boş bırakılırsa root kilitlenir
|
||||||
|
/// (`CreateUserJob` → `passwd -l root`).
|
||||||
|
#[serde(default)]
|
||||||
|
pub root_password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `[system]` bölümü — isteğe bağlı davranış ayarları.
|
||||||
|
///
|
||||||
|
/// Tümü `#[serde(default)]`: answer dosyası yalnızca zorunlu alanları
|
||||||
|
/// içerebilir. Bu bölümü tanımlamak zorunlu değil.
|
||||||
|
#[derive(Debug, serde::Deserialize)]
|
||||||
|
pub struct SystemConfig {
|
||||||
|
/// Otomatik oturum açma.
|
||||||
|
///
|
||||||
|
/// Varsayılan KAPALI. Gözetimsiz kurulumda açık olması, kurulmuş
|
||||||
|
/// sistemde herhangi birinin fiziksel olarak konsola oturup
|
||||||
|
/// kullanıcı adını görmesini kolaylaştırır.
|
||||||
|
#[serde(default)]
|
||||||
|
pub autologin: bool,
|
||||||
|
/// GRUB bekleme süresi (saniye).
|
||||||
|
#[serde(default = "default_grub_timeout")]
|
||||||
|
pub bootloader_timeout: u32,
|
||||||
|
/// GRUB parolası (düz metin; hedefte PBKDF2 ile hashlenir).
|
||||||
|
#[serde(default)]
|
||||||
|
pub bootloader_password: String,
|
||||||
|
/// Ek çekirdek parametreleri.
|
||||||
|
#[serde(default)]
|
||||||
|
pub kernel_options: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
// DİKKAT: burada `#[derive(Default)]` KULLANILMAZ.
|
||||||
|
//
|
||||||
|
// `[system]` bloğu answer dosyasında HİÇ YOKSA serde, AnswerFile'daki
|
||||||
|
// `#[serde(default)]` sayesinde bu tipin Default'ını çağırır. Alan
|
||||||
|
// bazlı `#[serde(default = "...")]` anotasyonları yalnızca blok
|
||||||
|
// KATILDIĞINDA, ilgili alan eksik olduğunda devreye girer. Yani
|
||||||
|
// türetilmiş Default, bootloader_timeout'ı 0 yapardı → kurulumda GRUB
|
||||||
|
// menüsü hiç görünmez. Elle uyguluyoruz.
|
||||||
|
impl Default for SystemConfig {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
autologin: false,
|
||||||
|
bootloader_timeout: default_grub_timeout(),
|
||||||
|
bootloader_password: String::new(),
|
||||||
|
kernel_options: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Answer file'ın tamamı (`--auto-install <dosya.toml>`).
|
/// Answer file'ın tamamı (`--auto-install <dosya.toml>`).
|
||||||
@@ -40,6 +87,9 @@ pub struct UserConfig {
|
|||||||
pub struct AnswerFile {
|
pub struct AnswerFile {
|
||||||
pub install: InstallConfig,
|
pub install: InstallConfig,
|
||||||
pub user: UserConfig,
|
pub user: UserConfig,
|
||||||
|
/// İsteğe bağlı. Verilmezse tüm ayarlar güvenli varsayılanlarda kalır.
|
||||||
|
#[serde(default)]
|
||||||
|
pub system: SystemConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_timezone() -> String { "Europe/Istanbul".to_string() }
|
fn default_timezone() -> String { "Europe/Istanbul".to_string() }
|
||||||
@@ -48,6 +98,7 @@ fn default_keyboard() -> String { "tr".to_string() }
|
|||||||
fn default_source() -> String { "/run/livecd/squashfs-root/".to_string() }
|
fn default_source() -> String { "/run/livecd/squashfs-root/".to_string() }
|
||||||
fn default_mount() -> String { "/mnt".to_string() }
|
fn default_mount() -> String { "/mnt".to_string() }
|
||||||
fn default_hostname() -> String { "pisilinux".to_string() }
|
fn default_hostname() -> String { "pisilinux".to_string() }
|
||||||
|
fn default_grub_timeout() -> u32 { 5 }
|
||||||
|
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
// ANSWER FILE: YÜKLE ve UYGULA
|
// ANSWER FILE: YÜKLE ve UYGULA
|
||||||
@@ -105,11 +156,28 @@ pub fn apply_to_state(af: &AnswerFile, state: &mut crate::installer::GlobalState
|
|||||||
state.username = af.user.username.clone();
|
state.username = af.user.username.clone();
|
||||||
state.password = af.user.password.clone();
|
state.password = af.user.password.clone();
|
||||||
state.password_confirm = af.user.password.clone();
|
state.password_confirm = af.user.password.clone();
|
||||||
|
state.root_password = af.user.root_password.clone();
|
||||||
|
state.root_password_confirm = af.user.root_password.clone();
|
||||||
state.hostname = af.user.hostname.clone();
|
state.hostname = af.user.hostname.clone();
|
||||||
state.selected_disk = Some(af.install.disk.clone());
|
state.selected_disk = Some(af.install.disk.clone());
|
||||||
state.erase_disk = true;
|
state.erase_disk = true;
|
||||||
state.language = if af.install.locale.starts_with("tr") { "tr" } else { "en" }.to_string();
|
state.language = if af.install.locale.starts_with("tr") { "tr" } else { "en" }.to_string();
|
||||||
|
|
||||||
|
// [system] — isteğe bağlı davranış ayarları
|
||||||
|
state.autologin = af.system.autologin;
|
||||||
|
state.bootloader_timeout = af.system.bootloader_timeout;
|
||||||
|
state.bootloader_password = af.system.bootloader_password.clone();
|
||||||
|
state.kernel_options = af.system.kernel_options.clone();
|
||||||
|
// GRUB aygıtı: bölümleme yapılmadan önce bilinmez, kuruluma
|
||||||
|
// InstallGrubJob içinde atanır.
|
||||||
|
state.bootloader_device = String::new();
|
||||||
|
|
||||||
|
// Masaüstü ortamı ve ekran yöneticisi answer file'dan GELMEZ.
|
||||||
|
// Sistem squashfs'ten kopyalandığı için bunlar ISO'nun kendisidir;
|
||||||
|
// GlobalState::default() zaten canlı ortamı tespit ediyor
|
||||||
|
// (detect_desktop_environment). Burada sabit bir değer yazmak,
|
||||||
|
// XFCE ISO'sunda Plasma oturumu açmaya çalışırdı.
|
||||||
|
|
||||||
// Disk boyutunu lsblk ile sorgula
|
// Disk boyutunu lsblk ile sorgula
|
||||||
let disk_info: Option<DiskInfo> = (|| {
|
let disk_info: Option<DiskInfo> = (|| {
|
||||||
let out = std::process::Command::new("lsblk")
|
let out = std::process::Command::new("lsblk")
|
||||||
@@ -165,3 +233,99 @@ pub fn apply_to_state(af: &AnswerFile, state: &mut crate::installer::GlobalState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
const MINIMAL: &str = r#"
|
||||||
|
[install]
|
||||||
|
disk = "/dev/sda"
|
||||||
|
|
||||||
|
[user]
|
||||||
|
username = "pisi"
|
||||||
|
password = "gizli123"
|
||||||
|
hostname = "pisi-pc"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
const WITH_SYSTEM: &str = r#"
|
||||||
|
[install]
|
||||||
|
disk = "/dev/nvme0n1"
|
||||||
|
|
||||||
|
[user]
|
||||||
|
username = "pisi"
|
||||||
|
password = "gizli123"
|
||||||
|
root_password = "rootgizli"
|
||||||
|
|
||||||
|
[system]
|
||||||
|
autologin = true
|
||||||
|
bootloader_timeout = 10
|
||||||
|
bootloader_password = "grubparola"
|
||||||
|
kernel_options = "quiet splash"
|
||||||
|
"#;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn minimal_answer_file_parses() {
|
||||||
|
// [system] tamamen isteğe bağlı — yoksa ayrıştırma patlamamalı.
|
||||||
|
let af = toml::from_str::<AnswerFile>(MINIMAL).expect("ayrıştırılmalı");
|
||||||
|
assert_eq!(af.install.disk, "/dev/sda");
|
||||||
|
assert_eq!(af.user.username, "pisi");
|
||||||
|
assert_eq!(af.user.root_password, "", "varsayılan boş olmalı");
|
||||||
|
assert!(!af.system.autologin, "autologin güvenli varsayılanı kapalı");
|
||||||
|
assert_eq!(af.system.bootloader_timeout, 5);
|
||||||
|
assert!(af.system.bootloader_password.is_empty());
|
||||||
|
assert!(af.system.kernel_options.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn system_section_is_honoured() {
|
||||||
|
let af = toml::from_str::<AnswerFile>(WITH_SYSTEM).expect("ayrıştırılmalı");
|
||||||
|
assert_eq!(af.install.disk, "/dev/nvme0n1");
|
||||||
|
assert_eq!(af.user.root_password, "rootgizli");
|
||||||
|
assert!(af.system.autologin, "autologin açık olmalı");
|
||||||
|
assert_eq!(af.system.bootloader_timeout, 10);
|
||||||
|
assert_eq!(af.system.bootloader_password, "grubparola");
|
||||||
|
assert_eq!(af.system.kernel_options, "quiet splash");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn example_file_on_disk_is_valid() {
|
||||||
|
// Depodaki örnek dosya gerçekten ayrıştırılabiliyor mu?
|
||||||
|
let p = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("answer-example.toml");
|
||||||
|
let content = std::fs::read_to_string(&p)
|
||||||
|
.expect("answer-example.toml okunmalı");
|
||||||
|
toml::from_str::<AnswerFile>(&content)
|
||||||
|
.expect("answer-example.toml ayrıştırılabilmeli");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn bootloader_timeout_default_survives_missing_system_block() {
|
||||||
|
// Regresyon: SystemConfig türetilmiş Default'a sahipti ve 0
|
||||||
|
// veriyordu. `[system]` bloğu dosyada HİÇ YOKSA serde alan
|
||||||
|
// bazlı `#[serde(default = "...")]` anotasyonlarına UĞRAMAZ;
|
||||||
|
// doğrudan Default::default() çağırır. Sonuç: GRUB bekleme
|
||||||
|
// süresi 0 saniye → kurulumda bootloader menüsü hiç görünmez.
|
||||||
|
let af = toml::from_str::<AnswerFile>(MINIMAL).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
af.system.bootloader_timeout, 5,
|
||||||
|
"[system] yokken de varsayılan geçerli olmalı"
|
||||||
|
);
|
||||||
|
assert_eq!(SystemConfig::default().bootloader_timeout, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn default_impl_matches_serde_field_defaults() {
|
||||||
|
// İki yol da aynı sonucu vermeli.
|
||||||
|
let d = SystemConfig::default();
|
||||||
|
assert!(!d.autologin);
|
||||||
|
assert!(d.bootloader_password.is_empty());
|
||||||
|
assert!(d.kernel_options.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn missing_required_section_is_rejected() {
|
||||||
|
// [user] olmadan kabul edilmemeli.
|
||||||
|
let bad = "[install]\ndisk = \"/dev/sda\"\n";
|
||||||
|
assert!(toml::from_str::<AnswerFile>(bad).is_err());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+144
-23
@@ -24,31 +24,64 @@ impl Job for ConfigureAutologinJob {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ekran yöneticisini SEÇMEK yerine TESPİT ediyoruz.
|
||||||
|
//
|
||||||
|
// YALI kurulu sistemi squashfs'ten kopyalar; ekran yöneticisi ISO'da
|
||||||
|
// hazırdır. `state.display_manager` ise GlobalState'in "sddm"
|
||||||
|
// varsayılanıdır ve kullanıcı tarafından değiştirilemez. Önceden
|
||||||
|
// bu sabite göre dallanılıyordu: ISO lightdm kullanıyorsa
|
||||||
|
// lightdm.conf'a hiç dokunulmaz, sddm.conf yazılır ve otomatik
|
||||||
|
// giriş sessizce çalışmazdı.
|
||||||
|
let dm = detect_display_manager(&self.mount).await;
|
||||||
|
match &dm {
|
||||||
|
Some(found) if found != &self.display_manager => {
|
||||||
|
ui.log(format!(
|
||||||
|
"Ekran yöneticisi tespit edildi: {} (varsayılan: {} kullanılmayacak)",
|
||||||
|
found, self.display_manager
|
||||||
|
));
|
||||||
|
}
|
||||||
|
Some(found) => {
|
||||||
|
ui.log(format!("Ekran yöneticisi: {}", found));
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Err(
|
||||||
|
"Hedef sistemde sddm/lightdm/gdm bulunamadı. \
|
||||||
|
Otomatik oturum açma uygulanamadı; kurulumda seçilen \
|
||||||
|
oturum yöneticisini elle yapılandırın."
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ui.log(format!(
|
ui.log(format!(
|
||||||
"Otomatik oturum açma uygulanıyor: {} ({})",
|
"Otomatik oturum açma uygulanıyor: {} ({})",
|
||||||
self.username, self.display_manager
|
self.username, self.username
|
||||||
));
|
));
|
||||||
|
|
||||||
let session = match self.desktop_environment.as_str() {
|
let session = session_desktop_file(&self.desktop_environment);
|
||||||
"plasma" => "plasmax11.desktop",
|
|
||||||
"xfce" => "xfce.desktop",
|
|
||||||
"gnome" => "gnome.desktop",
|
|
||||||
"cinnamon" => "cinnamon.desktop",
|
|
||||||
"budgie" => "budgie-desktop.desktop",
|
|
||||||
"lxde" => "LXDE.desktop",
|
|
||||||
"lxqt" => "lxqt.desktop",
|
|
||||||
"mate" => "mate.desktop",
|
|
||||||
"lumina" => "lumina-desktop.desktop",
|
|
||||||
_ => "plasmax11.desktop",
|
|
||||||
};
|
|
||||||
|
|
||||||
match self.display_manager.as_str() {
|
match dm.as_deref() {
|
||||||
"sddm" => {
|
Some("sddm") => {
|
||||||
// ISO'nun /usr/lib/sddm/sddm.conf.d içeriğine dokunmadan
|
// ISO'nun /usr/lib/sddm/sddm.conf.d içeriğine dokunmadan
|
||||||
// ayrı bir drop-in dosyası ile autologin eklenir.
|
// ayrı bir drop-in dosyası ile autologin eklenir.
|
||||||
let dir = format!("{}/usr/lib/sddm/sddm.conf.d", self.mount);
|
let dir = format!("{}/usr/lib/sddm/sddm.conf.d", self.mount);
|
||||||
|
// Bu dizin yoksa ISO sddm kullanmıyordur demektir; sddm
|
||||||
|
// genelde /etc/sddm.conf.d kullanır. İkisini de dene.
|
||||||
|
let dir = if std::path::Path::new(&dir).is_dir() {
|
||||||
|
dir
|
||||||
|
} else {
|
||||||
|
let alt = format!("{}/etc/sddm.conf.d", self.mount);
|
||||||
|
if std::path::Path::new(&alt).is_dir() {
|
||||||
|
alt
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"sddm yapılandırma dizini bulunamadı ({}/usr/lib/sddm/sddm.conf.d, {}/etc/sddm.conf.d)",
|
||||||
|
self.mount, self.mount
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
tokio::fs::create_dir_all(&dir).await
|
tokio::fs::create_dir_all(&dir).await
|
||||||
.map_err(|e| format!("sddm.conf.d oluşturulamadı: {}", e))?;
|
.map_err(|e| format!("{} oluşturulamadı: {}", dir, e))?;
|
||||||
let content = format!(
|
let content = format!(
|
||||||
"[Autologin]\nUser={}\nSession={}\n",
|
"[Autologin]\nUser={}\nSession={}\n",
|
||||||
self.username, session
|
self.username, session
|
||||||
@@ -57,7 +90,7 @@ impl Job for ConfigureAutologinJob {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| format!("autologin.conf yazılamadı: {}", e))?;
|
.map_err(|e| format!("autologin.conf yazılamadı: {}", e))?;
|
||||||
}
|
}
|
||||||
"lightdm" => {
|
Some("lightdm") => {
|
||||||
let dir = format!("{}/etc/lightdm", self.mount);
|
let dir = format!("{}/etc/lightdm", self.mount);
|
||||||
let _ = tokio::fs::create_dir_all(&dir).await;
|
let _ = tokio::fs::create_dir_all(&dir).await;
|
||||||
let conf = format!("{}/lightdm.conf", dir);
|
let conf = format!("{}/lightdm.conf", dir);
|
||||||
@@ -68,14 +101,17 @@ impl Job for ConfigureAutologinJob {
|
|||||||
content.push_str("[Seat:*]\n");
|
content.push_str("[Seat:*]\n");
|
||||||
}
|
}
|
||||||
if !content.contains("autologin-user=") {
|
if !content.contains("autologin-user=") {
|
||||||
|
// lightdm oturumu .desktop dosyası adı olarak bekler.
|
||||||
|
// Ham DE adını ("plasma") yazmak, sddm/gdm'nin kullandığı
|
||||||
|
// eşlemenin aynısı değildi ve oturumu bulamazdı.
|
||||||
content.push_str(&format!("autologin-user={}\n", self.username));
|
content.push_str(&format!("autologin-user={}\n", self.username));
|
||||||
content.push_str(&format!("autologin-session={}\n", self.desktop_environment));
|
content.push_str(&format!("autologin-session={}\n", session));
|
||||||
}
|
}
|
||||||
tokio::fs::write(&conf, content)
|
tokio::fs::write(&conf, content)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| format!("lightdm.conf yazılamadı: {}", e))?;
|
.map_err(|e| format!("lightdm.conf yazılamadı: {}", e))?;
|
||||||
}
|
}
|
||||||
"gdm" => {
|
Some("gdm") => {
|
||||||
let dir = format!("{}/etc/gdm", self.mount);
|
let dir = format!("{}/etc/gdm", self.mount);
|
||||||
let _ = tokio::fs::create_dir_all(&dir).await;
|
let _ = tokio::fs::create_dir_all(&dir).await;
|
||||||
let conf = format!("{}/custom.conf", dir);
|
let conf = format!("{}/custom.conf", dir);
|
||||||
@@ -87,10 +123,11 @@ impl Job for ConfigureAutologinJob {
|
|||||||
.await
|
.await
|
||||||
.map_err(|e| format!("gdm/custom.conf yazılamadı: {}", e))?;
|
.map_err(|e| format!("gdm/custom.conf yazılamadı: {}", e))?;
|
||||||
}
|
}
|
||||||
_ => {
|
other => {
|
||||||
ui.log(format!(
|
return Err(format!(
|
||||||
"⚠ Bilinmeyen ekran yöneticisi: {} — autologin uygulanmadı",
|
"Desteklenmeyen ekran yöneticisi tespit edildi: {} — \
|
||||||
self.display_manager
|
otomatik oturum açma uygulanmadı",
|
||||||
|
other.unwrap_or("bilinmiyor")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,3 +136,87 @@ impl Job for ConfigureAutologinJob {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Masaüstü ortamı adını, oturum yöneticilerinin beklediği `.desktop`
|
||||||
|
/// dosyası adına eşler.
|
||||||
|
///
|
||||||
|
/// lightdm, sddm ve gdm oturumu `plasmax11.desktop` gibi bir dosya adıyla
|
||||||
|
/// arar; ham DE adıyla ("plasma") yazmak oturumu bulamaz.
|
||||||
|
fn session_desktop_file(de: &str) -> &'static str {
|
||||||
|
match de {
|
||||||
|
"plasma" => "plasmax11.desktop",
|
||||||
|
"xfce" => "xfce.desktop",
|
||||||
|
"gnome" => "gnome.desktop",
|
||||||
|
"cinnamon" => "cinnamon.desktop",
|
||||||
|
"budgie" => "budgie-desktop.desktop",
|
||||||
|
"lxde" => "LXDE.desktop",
|
||||||
|
"lxqt" => "lxqt.desktop",
|
||||||
|
"mate" => "mate.desktop",
|
||||||
|
"lumina" => "lumina-desktop.desktop",
|
||||||
|
// Bilinmeyen DE'de plasma varsayılır. Önemli olan, ham adı
|
||||||
|
// yazıp oturumu bulamamaktır.
|
||||||
|
_ => "plasmax11.desktop",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hedef sistemde hangi ekran yöneticisinin KURULU olduğunu tespit eder.
|
||||||
|
///
|
||||||
|
/// YALI squashfs'ten kopyaladığı için ekran yöneticisi ISO'nun kendisidir;
|
||||||
|
/// kullanıcı seçmez. Tespit çalışma zamanında yapılır çünkü `mount`
|
||||||
|
/// dizini rsync'ten sonra tamdır (bu iş `CopyFilesJob`'dan sonra çalışır).
|
||||||
|
///
|
||||||
|
/// İki kaynak kontrol edilir: çalıştırılabilir (`/usr/bin/sddm`) ve
|
||||||
|
/// yapılandırma dosyası. Çoğu dağıtımda ikisi de vardır ama paket
|
||||||
|
/// yöneticisine göre değişebilir.
|
||||||
|
async fn detect_display_manager(mount: &str) -> Option<String> {
|
||||||
|
for (bin, name) in [
|
||||||
|
("sddm", "sddm"),
|
||||||
|
("lightdm", "lightdm"),
|
||||||
|
("gdm", "gdm"),
|
||||||
|
] {
|
||||||
|
let exe = format!("{}/usr/bin/{}", mount, bin);
|
||||||
|
if std::path::Path::new(&exe).exists() {
|
||||||
|
return Some(name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Yedek: yapılandırma dizini
|
||||||
|
for (dir, name) in [
|
||||||
|
("etc/sddm.conf.d", "sddm"),
|
||||||
|
("usr/lib/sddm", "sddm"),
|
||||||
|
("etc/lightdm", "lightdm"),
|
||||||
|
("etc/gdm", "gdm"),
|
||||||
|
] {
|
||||||
|
if std::path::Path::new(&format!("{}/{}", mount, dir)).is_dir() {
|
||||||
|
return Some(name.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn every_de_maps_to_a_desktop_file() {
|
||||||
|
// lightdm/sddm/gdm oturumu .desktop dosyası arar; ham ad
|
||||||
|
// yazılırsa oturum açılmaz.
|
||||||
|
for de in [
|
||||||
|
"plasma", "xfce", "gnome", "cinnamon", "budgie",
|
||||||
|
"lxde", "lxqt", "mate", "lumina",
|
||||||
|
] {
|
||||||
|
let f = session_desktop_file(de);
|
||||||
|
assert!(f.ends_with(".desktop"), "{} → {} uzantısız", de, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_de_falls_back_to_a_valid_desktop_file() {
|
||||||
|
for de in ["", "kde5", "deepin", "TOTALLY-UNKNOWN"] {
|
||||||
|
assert!(
|
||||||
|
session_desktop_file(de).ends_with(".desktop"),
|
||||||
|
"{} geçersiz dosya adı veriyor", de
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+39
-18
@@ -7,7 +7,7 @@ mod branding;
|
|||||||
mod funct;
|
mod funct;
|
||||||
|
|
||||||
use installer::{GlobalState, InstallerStep, WelcomeStep};
|
use installer::{GlobalState, InstallerStep, WelcomeStep};
|
||||||
use steps::{LocationStep, KeyboardStep, UsersStep, SummaryStep, ExecutionStep, FinishStep, PartitionStep, BootloaderStep, NetworkStep, DisplayManagerStep, NetinstallStep, LicenseStep};
|
use steps::{LocationStep, KeyboardStep, UsersStep, SummaryStep, ExecutionStep, FinishStep, PartitionStep, BootloaderStep, NetworkStep};
|
||||||
use eframe::egui;
|
use eframe::egui;
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
|
|
||||||
@@ -128,6 +128,7 @@ fn run_auto_install(path: &str, demo_mode: bool) -> eframe::Result<()> {
|
|||||||
let timezone = af.install.timezone.clone();
|
let timezone = af.install.timezone.clone();
|
||||||
let username = af.user.username.clone();
|
let username = af.user.username.clone();
|
||||||
let password = af.user.password.clone();
|
let password = af.user.password.clone();
|
||||||
|
let root_password = af.user.root_password.clone();
|
||||||
let hostname = af.user.hostname.clone();
|
let hostname = af.user.hostname.clone();
|
||||||
let kb_layout = af.install.keyboard.clone();
|
let kb_layout = af.install.keyboard.clone();
|
||||||
let kb_variant = af.install.keyboard_variant.clone();
|
let kb_variant = af.install.keyboard_variant.clone();
|
||||||
@@ -135,6 +136,16 @@ fn run_auto_install(path: &str, demo_mode: bool) -> eframe::Result<()> {
|
|||||||
let mount = af.install.mount.clone();
|
let mount = af.install.mount.clone();
|
||||||
let plan = state.partition_plan.unwrap();
|
let plan = state.partition_plan.unwrap();
|
||||||
|
|
||||||
|
// Squashfs kurulumu: oturum yöneticisi ve masaüstü ortamı ISO'dan
|
||||||
|
// gelir. `apply_to_state` bunları GlobalState'in canlı ortam
|
||||||
|
// tespitine bırakıyor; burada sabit yazmıyoruz.
|
||||||
|
let display_manager = state.display_manager.clone();
|
||||||
|
let desktop_environment = state.desktop_environment.clone();
|
||||||
|
let autologin = af.system.autologin;
|
||||||
|
let boot_timeout = af.system.bootloader_timeout;
|
||||||
|
let boot_password = af.system.bootloader_password.clone();
|
||||||
|
let kernel_options = af.system.kernel_options.clone();
|
||||||
|
|
||||||
let rt = tokio::runtime::Runtime::new().expect("tokio runtime");
|
let rt = tokio::runtime::Runtime::new().expect("tokio runtime");
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
@@ -176,14 +187,16 @@ fn run_auto_install(path: &str, demo_mode: bool) -> eframe::Result<()> {
|
|||||||
kb_variant: kb_variant_c,
|
kb_variant: kb_variant_c,
|
||||||
demo_mode,
|
demo_mode,
|
||||||
boot_device: String::new(),
|
boot_device: String::new(),
|
||||||
bootloader_timeout: 5,
|
bootloader_timeout: boot_timeout,
|
||||||
bootloader_password: String::new(),
|
bootloader_password: boot_password,
|
||||||
kernel_options: String::new(),
|
kernel_options: kernel_options,
|
||||||
use_ntp: true,
|
use_ntp: true,
|
||||||
root_password: String::new(),
|
root_password: root_password,
|
||||||
display_manager: "sddm".to_string(),
|
// Tespit edilmiş değerler (ISO'nun kendisi) — sabit
|
||||||
autologin: true,
|
// yazılmıyor.
|
||||||
desktop_environment: "plasma".to_string(),
|
display_manager,
|
||||||
|
autologin,
|
||||||
|
desktop_environment,
|
||||||
selected_package_groups: Vec::new(),
|
selected_package_groups: Vec::new(),
|
||||||
manual_year: 2026,
|
manual_year: 2026,
|
||||||
manual_month: 5,
|
manual_month: 5,
|
||||||
@@ -245,20 +258,27 @@ impl Default for YaliApp {
|
|||||||
let branding = branding::BrandingConfig::load_for_lang(&default_lang);
|
let branding = branding::BrandingConfig::load_for_lang(&default_lang);
|
||||||
let mut app = Self {
|
let mut app = Self {
|
||||||
state: GlobalState::default(),
|
state: GlobalState::default(),
|
||||||
|
// Sihirbaz akışı: yalı KURULU SİSTEMİ squashfs'ten diske
|
||||||
|
// kopyalar (CopyFilesJob rsync). Bu yüzden ISO'da hangi
|
||||||
|
// paketler, ekran yöneticisi ve masaüstü ortamı varsa
|
||||||
|
// kurulum BUNLARI ZATEN İÇERİR.
|
||||||
|
//
|
||||||
|
// Bu yüzden LicenseStep, DisplayManagerStep ve NetinstallStep
|
||||||
|
// bilinçli olarak listede DEĞİL:
|
||||||
|
// - lisans kabulü bu akışta anlam taşımıyor
|
||||||
|
// - ekran yöneticisi ISO'da pişmiş geliyor
|
||||||
|
// - ağdan ek paket kurmak, diski squashfs'ten kopyalamayla
|
||||||
|
// çelişir; netinstall ayrı bir proje olarak ileride
|
||||||
|
// devreye alınacak
|
||||||
|
// Adımlar silinmedi — mod.rs'te tanımlı ve hazır duruyor.
|
||||||
steps: vec![
|
steps: vec![
|
||||||
Box::new(WelcomeStep::default()),
|
Box::new(WelcomeStep::default()),
|
||||||
// Orijinal Python Yali'de sıra: info → license → mediaCheck
|
|
||||||
// → keyboardSetup. Rust yeniden yazımında LicenseStep yazıldı
|
|
||||||
// ama hiç bağlanmadı (mod.rs'te tanımsızdı).
|
|
||||||
Box::new(LicenseStep),
|
|
||||||
Box::new(LocationStep::default()),
|
Box::new(LocationStep::default()),
|
||||||
Box::new(KeyboardStep::default()),
|
Box::new(KeyboardStep::default()),
|
||||||
Box::new(NetworkStep::default()),
|
Box::new(NetworkStep::default()),
|
||||||
Box::new(PartitionStep::default()),
|
Box::new(PartitionStep::default()),
|
||||||
Box::new(UsersStep::default()),
|
Box::new(UsersStep::default()),
|
||||||
Box::new(DisplayManagerStep),
|
|
||||||
Box::new(BootloaderStep::default()),
|
Box::new(BootloaderStep::default()),
|
||||||
Box::new(NetinstallStep),
|
|
||||||
Box::new(SummaryStep),
|
Box::new(SummaryStep),
|
||||||
Box::new(ExecutionStep::default()),
|
Box::new(ExecutionStep::default()),
|
||||||
Box::new(FinishStep),
|
Box::new(FinishStep),
|
||||||
@@ -540,15 +560,12 @@ mod tests {
|
|||||||
fn wizard() -> Vec<Box<dyn InstallerStep>> {
|
fn wizard() -> Vec<Box<dyn InstallerStep>> {
|
||||||
vec![
|
vec![
|
||||||
Box::new(WelcomeStep::default()),
|
Box::new(WelcomeStep::default()),
|
||||||
Box::new(LicenseStep),
|
|
||||||
Box::new(LocationStep::default()),
|
Box::new(LocationStep::default()),
|
||||||
Box::new(KeyboardStep::default()),
|
Box::new(KeyboardStep::default()),
|
||||||
Box::new(NetworkStep::default()),
|
Box::new(NetworkStep::default()),
|
||||||
Box::new(PartitionStep::default()),
|
Box::new(PartitionStep::default()),
|
||||||
Box::new(UsersStep::default()),
|
Box::new(UsersStep::default()),
|
||||||
Box::new(DisplayManagerStep),
|
|
||||||
Box::new(BootloaderStep::default()),
|
Box::new(BootloaderStep::default()),
|
||||||
Box::new(NetinstallStep),
|
|
||||||
Box::new(SummaryStep),
|
Box::new(SummaryStep),
|
||||||
Box::new(ExecutionStep::default()),
|
Box::new(ExecutionStep::default()),
|
||||||
Box::new(FinishStep),
|
Box::new(FinishStep),
|
||||||
@@ -597,13 +614,17 @@ mod tests {
|
|||||||
/// sonrası yaşanan regresyon sınıfının tersidir: orada liste
|
/// sonrası yaşanan regresyon sınıfının tersidir: orada liste
|
||||||
/// değişti ve konumsal `cur == n_steps - 2` tespiti sessizce
|
/// değişti ve konumsal `cur == n_steps - 2` tespiti sessizce
|
||||||
/// kaydı.
|
/// kaydı.
|
||||||
|
///
|
||||||
|
/// Örnek olarak `NetinstallStep` kullanıldı: bu adım squashfs
|
||||||
|
/// kurulumunda bilinçli olarak listede değil, ama netinstall
|
||||||
|
/// projesi başladığında aynen buraya eklenebilmeli.
|
||||||
#[test]
|
#[test]
|
||||||
fn roles_survive_inserting_a_step_before_execution() {
|
fn roles_survive_inserting_a_step_before_execution() {
|
||||||
let mut steps = wizard();
|
let mut steps = wizard();
|
||||||
let exec_at = steps.iter().position(|s| s.role() == StepRole::Execution).unwrap();
|
let exec_at = steps.iter().position(|s| s.role() == StepRole::Execution).unwrap();
|
||||||
|
|
||||||
// Yeni bir Normal adım ekle
|
// Yeni bir Normal adım ekle
|
||||||
steps.insert(exec_at, Box::new(NetinstallStep));
|
steps.insert(exec_at, Box::new(steps::netinstall::NetinstallStep));
|
||||||
let n = steps.len();
|
let n = steps.len();
|
||||||
|
|
||||||
// Hâlâ doğru adımlar son ikide mi?
|
// Hâlâ doğru adımlar son ikide mi?
|
||||||
|
|||||||
+54
-6
@@ -1,3 +1,17 @@
|
|||||||
|
//! Sihirbaz adımları.
|
||||||
|
//!
|
||||||
|
//! ## Aktif akış
|
||||||
|
//!
|
||||||
|
//! YALI, **KURULU SİSTEMİ squashfs'ten diske kopyalar** (`jobs::CopyFilesJob`
|
||||||
|
//! rsync). Bunun temel sonucu: ISO'da hangi paketler, ekran yöneticisi ve
|
||||||
|
//! masaüstü ortamı varsa, kurulum onları ZATEN içerir. Bu yüzden sihirbaz
|
||||||
|
//! paket seçimi, ekran yöneticisi seçimi veya lisans kabulü sunmaz —
|
||||||
|
//! sunduğu ayarları kopyalama zaten ezdiği için yanıltıcı olurdu.
|
||||||
|
//!
|
||||||
|
//! Aktif sıra (`main.rs::YaliApp::default`):
|
||||||
|
//! Welcome → Location → Keyboard → Network → Partition → Users →
|
||||||
|
//! Bootloader → Summary → Execution → Finish
|
||||||
|
|
||||||
pub mod keyboard;
|
pub mod keyboard;
|
||||||
pub mod users;
|
pub mod users;
|
||||||
pub mod summary;
|
pub mod summary;
|
||||||
@@ -7,9 +21,6 @@ pub mod partition;
|
|||||||
pub mod bootloader;
|
pub mod bootloader;
|
||||||
pub mod network;
|
pub mod network;
|
||||||
pub mod rescue;
|
pub mod rescue;
|
||||||
pub mod display_manager;
|
|
||||||
pub mod netinstall;
|
|
||||||
pub mod license;
|
|
||||||
pub mod location;
|
pub mod location;
|
||||||
|
|
||||||
pub use keyboard::KeyboardStep;
|
pub use keyboard::KeyboardStep;
|
||||||
@@ -21,7 +32,44 @@ pub use partition::PartitionStep;
|
|||||||
pub use bootloader::BootloaderStep;
|
pub use bootloader::BootloaderStep;
|
||||||
pub use network::NetworkStep;
|
pub use network::NetworkStep;
|
||||||
pub use rescue::RescueStep;
|
pub use rescue::RescueStep;
|
||||||
pub use display_manager::DisplayManagerStep;
|
|
||||||
pub use netinstall::NetinstallStep;
|
|
||||||
pub use license::LicenseStep;
|
|
||||||
pub use location::LocationStep;
|
pub use location::LocationStep;
|
||||||
|
|
||||||
|
// ─────────────────────────────────────────────
|
||||||
|
// DORMANT ADIMLAR — squashfs akışının parçası DEĞİL
|
||||||
|
//
|
||||||
|
// Derleniyorlar ve hazırlar, ama sihirbaza BAĞLI DEĞİLLER. main.rs'deki
|
||||||
|
// `steps` vektörüne eklenmedikleri için kullanıcıya hiç gösterilmezler.
|
||||||
|
// Eklenmeleri gerektiğinde tek satır yeterlidir: `InstallerStep::role()`
|
||||||
|
// varsayılan `Normal` döndüğü için konumsal bir güncelleme gerekmez.
|
||||||
|
//
|
||||||
|
// NOT — `#[allow(dead_code)]` yalnızca bu üç modüle, yalnızca aşağıdaki
|
||||||
|
// kasıtlı uyku için konmuştur. 22de7d5 bu gerekçeyi vermeden genel
|
||||||
|
// `#[allow(dead_code)]` serpiştirmiş ve 1804 satırlık bir silmeyi
|
||||||
|
// "dead code temizliği" diye gizlemişti. Buradaki izin yalnızca bu
|
||||||
|
// modüllere ve yalnızca aşağıdaki nedenle sınırlıdır; modül dışında
|
||||||
|
// taze bir ölü kod yine uyarı üretir.
|
||||||
|
// ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Ekran yöneticisi / masaüstü ortamı seçimi.
|
||||||
|
/// ISO'nun ekran yöneticisi squashfs'ten geldiği için seçim anlamsız —
|
||||||
|
/// seçilen değer `ConfigureAutologinJob` tarafından ISO'dakini ezerdi.
|
||||||
|
/// Etkinleştirmek için: main.rs'de Users ile Bootloader arasına
|
||||||
|
/// `steps::display_manager::DisplayManagerStep` ekle.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod display_manager;
|
||||||
|
|
||||||
|
/// Ağdan ek paket kurma (netinstall).
|
||||||
|
/// Squashfs kurulumuyla çelişir: paketler zaten görüntüde. Netinstall
|
||||||
|
/// ayrı bir proje olarak başlatıldığında bu adım `main.rs`'de
|
||||||
|
/// Bootloader ile Summary arasına
|
||||||
|
/// `steps::netinstall::NetinstallStep` olarak eklenmeli,
|
||||||
|
/// `JobQueueConfig::selected_package_groups` doldurulmalı ve
|
||||||
|
/// `InstallExtraPackagesJob` kuyruğa alınmalı. `src/jobs/netinstall.rs`
|
||||||
|
/// bu iş için hazır.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod netinstall;
|
||||||
|
|
||||||
|
/// GPL lisans metni ve kabul onayı.
|
||||||
|
/// Bu kurulum akışında lisans kabulü bir koşul değil.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub mod license;
|
||||||
|
|||||||
+21
-9
@@ -137,18 +137,30 @@ impl InstallerStep for SummaryStep {
|
|||||||
summary_row(ui, t!("summary_datetime"), &dt_str);
|
summary_row(ui, t!("summary_datetime"), &dt_str);
|
||||||
|
|
||||||
// Bootloader
|
// Bootloader
|
||||||
let bl_str = format!("{} ({}s timeout{})",
|
let pw_suffix = if state.bootloader_password.is_empty() {
|
||||||
state.bootloader_device,
|
String::new()
|
||||||
state.bootloader_timeout,
|
} else {
|
||||||
if state.bootloader_password.is_empty() { "" } else { ", password protected" }
|
format!(", {}", t!("summary_bootloader_password"))
|
||||||
|
};
|
||||||
|
let bl_str = format!(
|
||||||
|
"{} ({}s timeout{})",
|
||||||
|
state.bootloader_device, state.bootloader_timeout, pw_suffix
|
||||||
);
|
);
|
||||||
summary_row(ui, t!("summary_bootloader"), &bl_str);
|
summary_row(ui, t!("summary_bootloader"), &bl_str);
|
||||||
|
|
||||||
// Display Manager
|
// Oturum yöneticisi ve masaüstü ortamı
|
||||||
let dm_str = format!("{} / {} ({})",
|
//
|
||||||
state.display_manager,
|
// Kullanıcı bunları SEÇEMEZ: sistem squashfs'ten
|
||||||
state.desktop_environment,
|
// kopyalandığı için ISO'nun kendi DM'i gelir ve
|
||||||
if state.autologin { t!("summary_autologin") } else { std::borrow::Cow::Borrowed("manual login") }
|
// ConfigureAutologinJob kurulum anında tespit eder.
|
||||||
|
// `state.display_manager` GlobalState'in sabit "sddm"
|
||||||
|
// varsayılanıdır; burada göstermek yanlış bilgi olurdu.
|
||||||
|
// Gösterilebilen tek şey, kullanıcının belirlediği
|
||||||
|
// otomatik giriş tercihi.
|
||||||
|
let dm_str = format!(
|
||||||
|
"{} — {}",
|
||||||
|
if state.autologin { t!("summary_autologin_on") } else { t!("summary_autologin_off") },
|
||||||
|
t!("summary_desktop_from_image")
|
||||||
);
|
);
|
||||||
summary_row(ui, t!("summary_display_manager"), &dm_str);
|
summary_row(ui, t!("summary_display_manager"), &dm_str);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user