forked from pisilinux-rs/yali-rs
fix(partition): mount edilmemiş fiziksel bölüm düzeni geçersiz kılıyordu
Kullanıcı raporu: "sdc ise tamamen boş disk bağlama noktası boş olamaz uyarısı veriyor." Kurulum: sda'da Windows (sda1 boot sağlam, mount değil), sdb'de Linux (EFI+swap+kök), sdc tamamen boş. ## Neden oluyordu `read_existing_partitions` mountpoint'i lsblk'in MOUNTPOINT sütunundan okur ve mount edilmemiş bölümlerde bu sütun BOŞTUR. Çift önyüklemeli bir makinede Windows'un boot bölümü her zaman bu durumdadır. Ama `validate_manual_on` boş mountpoint'i TÜM tanımlarda reddediyordu (LVM PV dışında) — kullanıcının hiç dokunmadığı sda1 yüzünden düzen geçersiz oluyordu. Hata hangi bölümden geldiğini de söylemiyordu. ## Düzeltmeler ### 1. Boş mountpoint zorunluluğu yalnızca kullanıcı tanımlarında Boş mountpoint'li FİZİKSEL bölüm "henüz atanmadı" demektir ve iş zincirinde zaten güvenli: mount edilmez (jobs/partition.rs:1111), fstab'a girmez (:1171), `skip_format: true` geldiği için formatlanmaz da. Doğrulama bir şey engellemiyor, sadece kullanıcıyı yanlış yönlendiriyordu. Kural: `orig_device` boş (kullanıcı tanımı) ve LVM PV değilse zorunlu. ### 2. Mükerrer bağlama noktası kontrolü boş değerleri dışlar İki atanmamış bölüm aynı "" değerini taşıdığı için kullanıcı var olmayan bir "mükerrer" hatası görüyor, asıl sorun maskeleniyordu. ### 3. suggest_mountpoint: öneri tüm düzeni görmeli `/`, `/boot/efi` ve `swap` TEKİLDİR. Öneri aktif diske bakıyordu; boş bir ikinci diske geçince o diskte tanım olmadığı için `/boot/efi` öneriyordu — sdb1'de zaten var olan mountpoint'i ikinci kez. Kaydetmeye çalışınca "mükerrer", alanı temizleyince "boş olamaz": iki hata da kullanıcıya hiçbir şey söylemiyordu. Saf ve test edilebilir bir fonksiyona çıkarıldı. Sıra: `/boot/efi` (UEFI) → `/` → `swap` → `/home` → boş. Son adım ikincil (veri) diskler için; sdc'de artık `/home` önerilir. Silinmek işaretli tanımlar sayılmaz. ## Testler (92 → 98) 6 yeni test, kullanıcının senaryosu dahil: - mount edilmemiş fiziksel bölüm düzeni geçersiz kılmaz - birden çok atanmamış bölüm mükerrer sayılmaz - boş ikinci disk /home önerir, mükerrer /boot/efi önermez - öneri aktif diske değil tüm düzene bakar - öneri sırası kök → swap - silinen tanım "alınmış" sayılmaz Mevcut `lvm_pv_may_have_no_mountpoint_but_others_may_not` testi yeni semantiğe göre güncellendi: "normal bölüm" yerine "kullanıcı tanımı" (orig_device boş) reddediliyor. cargo check --all-targets : 0 hata, 0 uyarı cargo test : 98/98 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -239,6 +239,49 @@ sda1 ile sdb1 çakışmaz.
|
|||||||
PV'lerinden toplanır — önceden tüm disklerin PV'leri birleştiriliyordu
|
PV'lerinden toplanır — önceden tüm disklerin PV'leri birleştiriliyordu
|
||||||
ve boyut toplamı yanlış çıkıyordu (AGENTS.md'deki açık maddeydi).
|
ve boyut toplamı yanlış çıkıyordu (AGENTS.md'deki açık maddeydi).
|
||||||
|
|
||||||
|
### ⭐ Mountpoint boşluğu mount EDİLMEMİŞ bölüm demek değil
|
||||||
|
|
||||||
|
`read_existing_partitions` mountpoint'i **`lsblk` MOUNTPOINT sütunundan**
|
||||||
|
okur (satır ~67: `tokens.next().unwrap_or("")`). Canlı ISO'da mount
|
||||||
|
edilmemiş her bölümde bu sütun **boştur**.
|
||||||
|
|
||||||
|
**Çift önyüklemeli makinede Windows'un boot bölümü neredeyse her zaman
|
||||||
|
bu durumdadır** ve kullanıcı ona dokunmamıştır. Buna rağmen
|
||||||
|
`validate_manual_on` tüm tanımları kapsayan bir "boş mountpoint"
|
||||||
|
kontrolü içeriyordu → düzen reddediliyordu, hata hangi bölümden
|
||||||
|
geldiğini söylemeden.
|
||||||
|
|
||||||
|
Kural artık: **boş mountpoint zorunluluğu yalnızca `orig_device` BOŞ
|
||||||
|
olan (kullanıcı tanımı) bölümlerde geçerli.** Fiziksel taranmış
|
||||||
|
bölümde boş mountpoint "henüz atanmadı" demektir ve iş zincirinde
|
||||||
|
zaten güvenli:
|
||||||
|
|
||||||
|
| Aşama | Davranış |
|
||||||
|
|---|---|
|
||||||
|
| mount | atlanır (`jobs/partition.rs:1111`) |
|
||||||
|
| fstab | atlanır (`:1171`) |
|
||||||
|
| mkfs | atlanır (`skip_format: true`) |
|
||||||
|
|
||||||
|
Aynı sebeple **mükerrer bağlama noktası kontrolü de boş değerleri
|
||||||
|
dışlar** — aksi hâlde "N atanmamış bölüm" kendi kendine mükerrer
|
||||||
|
sayılır ve asıl sorun maskelenir.
|
||||||
|
|
||||||
|
### `suggest_mountpoint` — öneri TÜM düzeni görmeli
|
||||||
|
|
||||||
|
`/`, `/boot/efi` ve `swap` bir kurulumda **TEKİLDİR**. Öneri bu
|
||||||
|
yüzden aktif diske değil **tüm düzene** bakar.
|
||||||
|
|
||||||
|
Aktif diske bakıyordu: kullanıcı boş bir ikinci diske geçip "Yeni
|
||||||
|
Bölüm" dediğinde o diskte tanım olmadığı için `/boot/efi` öneriliyordu
|
||||||
|
— sdb1'de zaten var olan mountpoint'i ikinci kez. Kullanıcı
|
||||||
|
kaydetmeye çalışınca "mükerrer" alıyor, alanı temizleyince "boş
|
||||||
|
olamaz" alıyordu. İkisi de hiçbir şey söylemiyordu.
|
||||||
|
|
||||||
|
Sıra: `/boot/efi` (UEFI) → `/` → `swap` → `/home` → boş. Son adım
|
||||||
|
ikincil (veri) diskler içindir: boş diske bölüm eklemek için alanı
|
||||||
|
elle doldurmak zorunda kalmamak. Silinmek işaretli tanımlar
|
||||||
|
sayılmaz.
|
||||||
|
|
||||||
### `selected_disk` hâlâ 3 yerde kullanılıyor
|
### `selected_disk` hâlâ 3 yerde kullanılıyor
|
||||||
1. Tablo hangi diski gösteriyor + `manual_dual_bars`
|
1. Tablo hangi diski gösteriyor + `manual_dual_bars`
|
||||||
2. Diyaloğun varsayılan hedefi
|
2. Diyaloğun varsayılan hedefi
|
||||||
|
|||||||
+212
-46
@@ -409,10 +409,21 @@ fn validate_manual_on(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Aynı mountpoint'ta iki bölüm tanımlı mı kontrolü
|
// Aynı mountpoint'ta iki bölüm tanımlı mı kontrolü.
|
||||||
let mountpoints: std::collections::HashSet<&str> =
|
//
|
||||||
live_parts.iter().map(|p| p.mountpoint.as_str()).collect();
|
// BOŞ mountpoint'ler ÇİKARILIR: `read_existing_partitions` mountpoint'i
|
||||||
if mountpoints.len() != live_parts.len() {
|
// lsblk'in MOUNTPOINT sütunundan alır ve canlı ISO'da mount EDILMEMİŞ
|
||||||
|
// bölümlerde bu sütun boştur. Çift önyüklemeli bir makinede Windows'un
|
||||||
|
// sda1'i neredeyse her zaman boş gelir. Boş değerler karşılaştırılırsa
|
||||||
|
// "N tane atanmamış bölüm" kendi kendine mükerrer sayılır ve kullanıcı
|
||||||
|
// var olmayan bir çakışma hatası görürdü.
|
||||||
|
let mountpoints: std::collections::HashSet<&str> = live_parts
|
||||||
|
.iter()
|
||||||
|
.map(|p| p.mountpoint.as_str())
|
||||||
|
.filter(|m| !m.is_empty())
|
||||||
|
.collect();
|
||||||
|
let assigned = live_parts.iter().filter(|p| !p.mountpoint.is_empty()).count();
|
||||||
|
if mountpoints.len() != assigned {
|
||||||
return Some(t!("mp_duplicate_mountpoint").to_string());
|
return Some(t!("mp_duplicate_mountpoint").to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,10 +437,26 @@ fn validate_manual_on(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mountpoint boş olmamalı — TEK istisna LVM PV'dir (üzerinde
|
// Mountpoint boş olmamalı — ama YALNIZCA KULLANICI TANIMLARI için.
|
||||||
// mantıksal hacimler yaşar, kendisi bağlanmaz).
|
//
|
||||||
|
// REGRESYON: bu kontrol tüm tanımları kapsıyordu. Taranmış fiziksel
|
||||||
|
// bir bölümün mountpoint'i canlı ISO'da mount edilmediği için BOŞTUR
|
||||||
|
// (lsblk MOUNTPOINT sütunu). Çift önyüklemeli bir makinede Windows'un
|
||||||
|
// sda1'i her zaman bu durumdadır ve kullanıcı ona hiç dokunmamıştı —
|
||||||
|
// yine de düzen reddediliyordu:
|
||||||
|
//
|
||||||
|
// "sda: sda1 bozuk değil, sadece mount değil" → hata ✗
|
||||||
|
//
|
||||||
|
// Boş mountpointli bir FİZİKSEL bölüm "henüz atanmadı" demektir ve
|
||||||
|
// iş zincirinde zaten güvenli: mount edilmez (jobs/partition.rs:1111),
|
||||||
|
// fstab'a girmez (:1171) ve `skip_format: true` geldiği için
|
||||||
|
// formatlanmaz da. Yani doğrulama bir şey engellemiyor, sadece
|
||||||
|
// kullanıcıyı yanlış yönlendiriyordu.
|
||||||
|
//
|
||||||
|
// Zorunluluk yeni tanımlarda (orig_device boş) ve LVM PV dışında
|
||||||
|
// geçerlidir: kullanıcı "ne işe yarayacak" diye sormadan kaydedemez.
|
||||||
for p in &live_parts {
|
for p in &live_parts {
|
||||||
if p.mountpoint.is_empty() && p.fstype != FsType::Lvm {
|
if p.orig_device.is_empty() && p.mountpoint.is_empty() && p.fstype != FsType::Lvm {
|
||||||
return Some(t!("mp_error_empty_mountpoint").to_string());
|
return Some(t!("mp_error_empty_mountpoint").to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -441,6 +468,41 @@ fn validate_manual_on(
|
|||||||
// Çoklu disk yardımcıları
|
// Çoklu disk yardımcıları
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// "Yeni Bölüm" diyaloğu için varsayılan bağlama noktası önerisi.
|
||||||
|
///
|
||||||
|
/// `/`, `/boot/efi` ve `swap` bir kurulumda **TEKİLDİR** — birdir. Bu
|
||||||
|
/// yüzden sayım aktif disk DEĞİL, TÜM düzen üzerinden yapılır.
|
||||||
|
///
|
||||||
|
/// REGRESYON: sayım aktif diske bakıyordu. Kullanıcı boş bir ikinci
|
||||||
|
/// diske geçip "Yeni Bölüm" dediğinde o diskte hiçbir tanım olmadığı
|
||||||
|
/// için öneri `/boot/efi` çıkıyordu — sdb1'de zaten var olan bir
|
||||||
|
/// mountpoint'i ikinci kez öneriyordu. Kullanıcı kaydetmeye
|
||||||
|
/// çalışınca "mükerrer bağlama noktası" hatası alıyor, alanı
|
||||||
|
/// temizleyince de "boş olamaz" hatası. İkisi de kullanıcıya hiçbir
|
||||||
|
/// şey söylemiyordu.
|
||||||
|
///
|
||||||
|
/// `/home` adımı ikincil (veri) diskler içindir: kök, EFI ve swap
|
||||||
|
/// başka yerdeyse sıra ona gelir, böylece boş bir diske bölüm
|
||||||
|
/// eklemek için alanı elle doldurmak zorunda kalmazsınız.
|
||||||
|
fn suggest_mountpoint(parts: &[CustomPartition], is_uefi: bool) -> &'static str {
|
||||||
|
let live: Vec<&CustomPartition> = parts.iter().filter(|p| !p.delete).collect();
|
||||||
|
let has_mp = |mp: &str| live.iter().any(|p| p.mountpoint == mp);
|
||||||
|
let has_fs = |fs: FsType| live.iter().any(|p| p.fstype == fs);
|
||||||
|
|
||||||
|
if is_uefi && !has_mp("/boot/efi") && !has_fs(FsType::Fat32) {
|
||||||
|
"/boot/efi"
|
||||||
|
} else if !has_mp("/") {
|
||||||
|
"/"
|
||||||
|
} else if !has_fs(FsType::Swap) {
|
||||||
|
"swap"
|
||||||
|
} else if !has_mp("/home") {
|
||||||
|
"/home"
|
||||||
|
} else {
|
||||||
|
// Her şey atanmış — kullanıcı elle seçer.
|
||||||
|
""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Verilen diskin toplam boyutunu MB cinsinden döndürür.
|
/// Verilen diskin toplam boyutunu MB cinsinden döndürür.
|
||||||
/// Disk listede yoksa 0 döner.
|
/// Disk listede yoksa 0 döner.
|
||||||
fn disk_size_mb(state: &GlobalState, disk: &str) -> u64 {
|
fn disk_size_mb(state: &GlobalState, disk: &str) -> u64 {
|
||||||
@@ -1453,49 +1515,24 @@ impl PartitionStep {
|
|||||||
self.manual.adding = true;
|
self.manual.adding = true;
|
||||||
self.manual.editing = false;
|
self.manual.editing = false;
|
||||||
self.manual.edit_idx = None;
|
self.manual.edit_idx = None;
|
||||||
|
self.manual.add_encrypt = false;
|
||||||
|
self.manual.add_luks_password.clear();
|
||||||
|
|
||||||
// Yeni tanım SEÇİLİ diske eklenir. Diyalogda ayrı bir
|
// Yeni tanım SEÇİLİ diske eklenir. Diyalogda ayrı bir
|
||||||
// hedef disk seçicisi yok; hedefi değiştirmek için
|
// hedef disk seçicisi yok; hedefi değiştirmek için
|
||||||
// disk şeridinden önce o diske geçilir.
|
// disk şeridinden önce o diske geçilir.
|
||||||
let active_disk = state.selected_disk.clone().unwrap_or_default();
|
let suggested = suggest_mountpoint(&state.custom_partitions, self.is_uefi);
|
||||||
// Öneriler bu diskin DURUMUNA göre yapılır:
|
self.manual.add_mountpoint = suggested.to_string();
|
||||||
// - UEFI'de ve henüz EFI yoksa → /boot/efi
|
|
||||||
// - kök yoksa → /
|
|
||||||
// - kök varsa ve swap yoksa → swap
|
|
||||||
// Böylece kullanıcı sdb'ye geçtiğinde öneri de sdb'ye göre
|
|
||||||
// değişir; daha önce her zaman aktif diskin sayımı
|
|
||||||
// kullanılıyordu ve yeni diske geçince "/boot/efi" gibi
|
|
||||||
// alakasız bir öneri çıkıyordu.
|
|
||||||
let defs: Vec<&CustomPartition> = state
|
|
||||||
.custom_partitions
|
|
||||||
.iter()
|
|
||||||
.filter(|p| p.disk == active_disk && !p.delete)
|
|
||||||
.collect();
|
|
||||||
let has_root = defs.iter().any(|p| p.mountpoint == "/");
|
|
||||||
let has_efi = defs.iter().any(|p| {
|
|
||||||
p.mountpoint == "/boot/efi" || p.fstype == FsType::Fat32
|
|
||||||
});
|
|
||||||
let has_swap = defs.iter().any(|p| p.fstype == FsType::Swap);
|
|
||||||
|
|
||||||
self.manual.add_mountpoint.clear();
|
|
||||||
self.manual.add_encrypt = false;
|
|
||||||
self.manual.add_luks_password.clear();
|
|
||||||
self.manual.add_mountpoint = if self.is_uefi && !has_efi {
|
|
||||||
"/boot/efi".to_string()
|
|
||||||
} else if !has_root {
|
|
||||||
"/".to_string()
|
|
||||||
} else if !has_swap {
|
|
||||||
"swap".to_string()
|
|
||||||
} else {
|
|
||||||
String::new()
|
|
||||||
};
|
|
||||||
// Mountpoint'e göre otomatik boyut ata
|
// Mountpoint'e göre otomatik boyut ata
|
||||||
self.manual.add_size_str = match self.manual.add_mountpoint.as_str() {
|
self.manual.add_size_str = match suggested {
|
||||||
"/boot/efi" => "1024".to_string(), // 1GB
|
"/boot/efi" => "1024".to_string(), // 1GB
|
||||||
"swap" => "1024".to_string(), // Sabit 1GB
|
"swap" => "1024".to_string(), // Sabit 1GB
|
||||||
"/" => "remaining".to_string(), // Geri kalan alan
|
// "/" ve "/home" → diskin kalanının tamamı. Veri diski
|
||||||
|
// olan ikinci bir diskte de bu çoğu zaman istenendir.
|
||||||
|
"/" | "/home" => "remaining".to_string(),
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
};
|
};
|
||||||
self.manual.add_fstype = match self.manual.add_mountpoint.as_str() {
|
self.manual.add_fstype = match suggested {
|
||||||
"swap" => FS_OPTIONS.iter().position(|(_, t)| *t == FsType::Swap).unwrap_or(0),
|
"swap" => FS_OPTIONS.iter().position(|(_, t)| *t == FsType::Swap).unwrap_or(0),
|
||||||
"/boot/efi" => FS_OPTIONS.iter().position(|(_, t)| *t == FsType::Fat32).unwrap_or(0),
|
"/boot/efi" => FS_OPTIONS.iter().position(|(_, t)| *t == FsType::Fat32).unwrap_or(0),
|
||||||
_ => 0,
|
_ => 0,
|
||||||
@@ -2997,14 +3034,143 @@ mod multidisk_tests {
|
|||||||
validate_manual_on(&with_pv, &[], true, &disks)
|
validate_manual_on(&with_pv, &[], true, &disks)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Normal bölüm: mountpoint yok → geçersiz
|
// KULLANICI TANIMI: mountpoint yok → geçersiz.
|
||||||
|
//
|
||||||
|
// `orig_device` boş olan bir tanım kullanıcının kendi eklediği
|
||||||
|
// yeni bölümdür; ne işe yarayacağını söylemeden kaydedilmesine
|
||||||
|
// izin verilmez. (Fiziksel taranmış bölümlerde mountpoint'in
|
||||||
|
// boş olması normaldir — aşağıdaki regression test'ine bakın.)
|
||||||
|
let mut new_def = p("/dev/sda", "/dev/sda2", 5_000, FsType::Ext4, "");
|
||||||
|
new_def.orig_device = String::new();
|
||||||
let no_mp = vec![
|
let no_mp = vec![
|
||||||
p("/dev/sda", "/dev/sda1", 20_000, FsType::Ext4, "/"),
|
p("/dev/sda", "/dev/sda1", 20_000, FsType::Ext4, "/"),
|
||||||
p("/dev/sda", "/dev/sda2", 5_000, FsType::Ext4, ""),
|
new_def,
|
||||||
];
|
];
|
||||||
assert!(
|
assert!(
|
||||||
validate_manual_on(&no_mp, &[], true, &disks).is_some(),
|
validate_manual_on(&no_mp, &[], true, &disks).is_some(),
|
||||||
"mountpointsiz normal bölüm reddedilmeli"
|
"mountpointsiz kullanıcı tanımı reddedilmeli"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── REGRESYON: mount EDİLMEMİŞ fiziksel bölüm ──────────────
|
||||||
|
|
||||||
|
/// Canlı ISO'da mount edilmemiş fiziksel bölüm (mountpoint boş)
|
||||||
|
/// düzeni GEÇERSİZ kılmamalı.
|
||||||
|
///
|
||||||
|
/// REGRESYON: `read_existing_partitions` mountpoint'i lsblk'in
|
||||||
|
/// MOUNTPOINT sütunundan okur; mount edilmemiş bölümlerde bu sütun
|
||||||
|
/// boştur. Çift önyüklemeli bir makinede Windows'un boot bölümü
|
||||||
|
/// neredeyse her zaman bu durumdadır ve kullanıcı ona dokunmamıştır.
|
||||||
|
/// Yine de düzen "bağlama noktası boş olamaz" ile reddediliyordu —
|
||||||
|
/// hata, ekrandaki 5 bölümün hangisinden geldiğini söylemeden.
|
||||||
|
#[test]
|
||||||
|
fn unmounted_physical_partition_does_not_invalidate_layout() {
|
||||||
|
let disks = vec![disk("/dev/sda", 250), disk("/dev/sdb", 500)];
|
||||||
|
|
||||||
|
// sda1 = Windows boot (FAT32, mount edilmemiş) → mountpoint BOŞ
|
||||||
|
let parts = vec![
|
||||||
|
p("/dev/sda", "/dev/sda1", 512, FsType::Fat32, ""),
|
||||||
|
p("/dev/sdb", "/dev/sdb1", 1_024, FsType::Fat32, "/boot/efi"),
|
||||||
|
p("/dev/sdb", "/dev/sdb2", 8_192, FsType::Swap, "swap"),
|
||||||
|
p("/dev/sdb", "/dev/sdb3", 400_000, FsType::Ext4, "/"),
|
||||||
|
];
|
||||||
|
assert_eq!(
|
||||||
|
validate_manual_on(&parts, &[], true, &disks),
|
||||||
|
None,
|
||||||
|
"mount edilmemiş sda1 düzeni bozmamalı: {:?}",
|
||||||
|
validate_manual_on(&parts, &[], true, &disks)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Birden çok atanmamış fiziksel bölüm "mükerrer bağlama noktası"
|
||||||
|
/// hatası üretmemeli.
|
||||||
|
///
|
||||||
|
/// REGRESYON: mükerrer kontrolü boş mountpoint'leri de karşılaştırıyordu.
|
||||||
|
/// İki atanmamış bölüm aynı "" değerini taşıdığı için kullanıcı var
|
||||||
|
/// olmayan bir çakışma hatası görüyordu — asıl sorun (mountpoint
|
||||||
|
/// eksikliği) maskeleniyordu.
|
||||||
|
#[test]
|
||||||
|
fn several_unassigned_partitions_are_not_duplicate_mountpoints() {
|
||||||
|
let disks = vec![disk("/dev/sda", 250)];
|
||||||
|
let parts = vec![
|
||||||
|
p("/dev/sda", "/dev/sda1", 512, FsType::Ntfs, ""),
|
||||||
|
p("/dev/sda", "/dev/sda2", 8_000, FsType::Ntfs, ""),
|
||||||
|
p("/dev/sda", "/dev/sda3", 200_000, FsType::Ext4, "/"),
|
||||||
|
];
|
||||||
|
assert_eq!(
|
||||||
|
validate_manual_on(&parts, &[], false, &disks),
|
||||||
|
None,
|
||||||
|
"iki atanmamış bölüm mükerrer sayılmamalı: {:?}",
|
||||||
|
validate_manual_on(&parts, &[], false, &disks)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── REGRESYON: ikinci diske öneri ──────────────────────────
|
||||||
|
|
||||||
|
/// Kullanıcının gerçek senaryosu: sdb'de kurulum tamam (EFI+swap+kök),
|
||||||
|
/// sdc tamamen boş. sdc'de "Yeni Bölüm" → öneri `/boot/efi` OLMAZ
|
||||||
|
/// (sdb1'de zaten var) ve BOŞ DA OLMAZ (kullanıcı ne yapacağını
|
||||||
|
/// bilemez). `/home` önerilir.
|
||||||
|
#[test]
|
||||||
|
fn empty_secondary_disk_suggests_home_not_a_duplicate_efi() {
|
||||||
|
let parts = vec![
|
||||||
|
p("/dev/sdb", "/dev/sdb1", 1_024, FsType::Fat32, "/boot/efi"),
|
||||||
|
p("/dev/sdb", "/dev/sdb2", 8_192, FsType::Swap, "swap"),
|
||||||
|
p("/dev/sdb", "/dev/sdb3", 400_000, FsType::Ext4, "/"),
|
||||||
|
];
|
||||||
|
assert_eq!(
|
||||||
|
suggest_mountpoint(&parts, true),
|
||||||
|
"/home",
|
||||||
|
"boş ikinci diskte /home önerilmeli, mükerrer /boot/efi değil"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Öneri TÜM düzeni görmeli — aktif disk değil.
|
||||||
|
///
|
||||||
|
/// REGRESYON: sayım aktif diske bakıyordu; boş bir diske geçince
|
||||||
|
/// o diskte "EFI yok" sanıp `/boot/efi` öneriyordu.
|
||||||
|
#[test]
|
||||||
|
fn suggestion_counts_whole_layout_not_the_active_disk() {
|
||||||
|
// Aktif disk sdc (hiç tanım yok), ama kurulum sdb'de tamam.
|
||||||
|
let sdb: Vec<CustomPartition> = vec![
|
||||||
|
p("/dev/sdb", "/dev/sdb1", 1_024, FsType::Fat32, "/boot/efi"),
|
||||||
|
p("/dev/sdb", "/dev/sdb2", 8_192, FsType::Swap, "swap"),
|
||||||
|
p("/dev/sdb", "/dev/sdb3", 400_000, FsType::Ext4, "/"),
|
||||||
|
];
|
||||||
|
let suggested = suggest_mountpoint(&sdb, true);
|
||||||
|
assert_ne!(
|
||||||
|
suggested, "/boot/efi",
|
||||||
|
"başka diskte EFI varken ikinci bir EFI önerilmemeli"
|
||||||
|
);
|
||||||
|
assert!(!suggested.is_empty(), "öneri boş olmamalı, kullanıcı yönlendirilmeli");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sıralama korunur: kurulum tamamen boşsa kök önerilir.
|
||||||
|
#[test]
|
||||||
|
fn suggestion_order_root_before_home() {
|
||||||
|
assert_eq!(suggest_mountpoint(&[], false), "/");
|
||||||
|
assert_eq!(suggest_mountpoint(&[], true), "/boot/efi");
|
||||||
|
let mut root = p("/dev/sda", "/dev/sda1", 100_000, FsType::Ext4, "/");
|
||||||
|
root.fstype = FsType::Ext4;
|
||||||
|
assert_eq!(suggest_mountpoint(&[root], false), "swap");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Silinmek işaretli bölümler sayılmamalı — kullanıcı /home'u
|
||||||
|
/// silip yeniden tanımlamak istiyor, öneri yine `/home` olmalı.
|
||||||
|
#[test]
|
||||||
|
fn deleted_definitions_do_not_count_as_taken() {
|
||||||
|
let mut dead = p("/dev/sdb", "/dev/sdb3", 400_000, FsType::Ext4, "/home");
|
||||||
|
dead.delete = true;
|
||||||
|
let parts = vec![
|
||||||
|
p("/dev/sdb", "/dev/sdb1", 1_024, FsType::Fat32, "/boot/efi"),
|
||||||
|
p("/dev/sdb", "/dev/sdb2", 8_192, FsType::Swap, "swap"),
|
||||||
|
p("/dev/sdb", "/dev/sdb3", 400_000, FsType::Ext4, "/"),
|
||||||
|
dead,
|
||||||
|
];
|
||||||
|
assert_eq!(
|
||||||
|
suggest_mountpoint(&parts, true),
|
||||||
|
"/home",
|
||||||
|
"silinen /home yeniden kullanılabilir olmalı"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user