forked from pisilinux-rs/yali-rs
fix(partition): "yalnızca GRUB için" bölüm mountpoint'siz kaydedilemiyordu
Kullanıcı raporu: "sda1 grub eklenecek o yüzden herhangi bir mount olayı yok ve yine bağlama noktası boş olamaz uyarısı alıyorum." Önceki commit yalnızca `validate_manual_on`'i düzeltmişti. Kaydetme DİYALOĞUNDA ikinci bir kural vardı ve koşulu `!is_pv` idi — yani fiziksel bölüm düzenlenirken de mountpoint zorunluydu. Kullanıcı sda1'i "kuruluma ait değil, yalnızca GRUB için" diye işaretlemek istiyordu ve diyalog kabul etmiyordu. Üstelik iki kural birbirinden farklıydı: validate serbest bırakırken diyalog reddediyor ve kullanıcı hangisinin geçerli olduğunu anlayamıyordu. ## mountpoint_required() — tek kural, iki yerde Kural artık saf bir yardımcıda tanımlı ve HER İKİ yerde de aynen kullanılıyor: - LVM PV → serbest - düzenlenen FİZİKSEL bölüm (orig_device dolu) → serbest - yeni tanım → zorunlu ⚠️ İki yerde ayrı yazılırsa birinde geçen diğerinde reddedilir ve kullanıcı "İleri"ye geçemez. Not yorumla sabitlendi. ## Hata mesajı artık bölümü adıyla söylüyor `mp_error_empty_mountpoint_named` eklendi. Genel mesaj ("Bağlama noktası boş olamaz") ekranda beş bölüm varken hangisinin kastedildiğini belli etmiyordu; bu bir hatanın iki tur turmasına yol açmıştı. ## Ölü i18n anahtarları silindi `rescue_button_tooltip` ve `job_display_manager` kodda KULLANILMIYORDU ve `en.toml`'da karşılıkları yoktu. Proje kuralı gereği çeviri yazmak yerine silindi: sessizleştirmek yerine kökten kaldır. tr/en artık tam eşleşiyor (463/463). ## Testler (98 → 102) - GRUB için ayrılmış fiziksel bölüm boş bırakılabilir - yeni tanımda mountpoint hâlâ zorunlu - LVM PV hiçbir koşulda mountpoint istemez - kullanıcının tam senaryosu (sda GRUB-only + sdb Linux + sdc /home) geçerli kabul ediliyor cargo check --all-targets : 0 hata, 0 uyarı cargo test : 102/102 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -296,6 +296,7 @@ job_mount_custom = "Mounting manual partitions"
|
|||||||
# ── Extra Localization / i18n ─────────────────────────────
|
# ── Extra Localization / i18n ─────────────────────────────
|
||||||
mp_delete_confirm_title = "Delete Partition"
|
mp_delete_confirm_title = "Delete Partition"
|
||||||
mp_error_empty_mountpoint = "Mount point cannot be empty."
|
mp_error_empty_mountpoint = "Mount point cannot be empty."
|
||||||
|
mp_error_empty_mountpoint_named = "Mount point cannot be empty: {device}. Pick a mount point from the list, or mark the partition for deletion and continue."
|
||||||
mp_plan_valid = "✓ Partition plan is valid. You can proceed."
|
mp_plan_valid = "✓ Partition plan is valid. You can proceed."
|
||||||
mp_select_disk_first = "← Select a disk first."
|
mp_select_disk_first = "← Select a disk first."
|
||||||
mp_add_dialog_hint = "/ or /home or swap"
|
mp_add_dialog_hint = "/ or /home or swap"
|
||||||
|
|||||||
+1
-2
@@ -151,7 +151,6 @@ check_warn_notice = "Bazı önerilen gereksinimler karşılanmıyor. Kurulum d
|
|||||||
check_all_pass = "Tüm sistem gereksinimleri karşılandı."
|
check_all_pass = "Tüm sistem gereksinimleri karşılandı."
|
||||||
recheck = "🔄 Yeniden Kontrol Et"
|
recheck = "🔄 Yeniden Kontrol Et"
|
||||||
rescue_button = "🆘 Kurtarma Kipi"
|
rescue_button = "🆘 Kurtarma Kipi"
|
||||||
rescue_button_tooltip = "PiSi Linux'u Kurtarma Modunda Yeniden Kur"
|
|
||||||
|
|
||||||
# ── Users (ek) ────────────────────────────────────────────
|
# ── Users (ek) ────────────────────────────────────────────
|
||||||
pwd_very_weak = "Çok zayıf"
|
pwd_very_weak = "Çok zayıf"
|
||||||
@@ -261,6 +260,7 @@ job_mount_custom = "Manuel bölümler bağlanıyor"
|
|||||||
# ── Ek Yerelleştirme / i18n ──────────────────────────────────
|
# ── Ek Yerelleştirme / i18n ──────────────────────────────────
|
||||||
mp_delete_confirm_title = "Bölümü Sil"
|
mp_delete_confirm_title = "Bölümü Sil"
|
||||||
mp_error_empty_mountpoint = "Bağlama noktası boş olamaz."
|
mp_error_empty_mountpoint = "Bağlama noktası boş olamaz."
|
||||||
|
mp_error_empty_mountpoint_named = "Bağlama noktası boş olamaz: {device}. Listeden bir bağlama noktası seçin ya da bölümü \"Sil\" işaretleyip geçin."
|
||||||
mp_plan_valid = "Bölüm planı geçerli. İleri tuşuna basabilirsiniz."
|
mp_plan_valid = "Bölüm planı geçerli. İleri tuşuna basabilirsiniz."
|
||||||
mp_select_disk_first = "← Önce bir disk seçin."
|
mp_select_disk_first = "← Önce bir disk seçin."
|
||||||
mp_add_dialog_hint = "/ veya /home veya swap"
|
mp_add_dialog_hint = "/ veya /home veya swap"
|
||||||
@@ -317,7 +317,6 @@ job_ldconfig = "Paylaşımlı kütüphaneler yapılandırılıyor (ldc
|
|||||||
job_update_env = "Sistem ortamı güncelleniyor"
|
job_update_env = "Sistem ortamı güncelleniyor"
|
||||||
job_cleanup_live = "Canlı ortam izleri temizleniyor"
|
job_cleanup_live = "Canlı ortam izleri temizleniyor"
|
||||||
job_datetime = "Tarih & saat yapılandırılıyor"
|
job_datetime = "Tarih & saat yapılandırılıyor"
|
||||||
job_display_manager = "Görüntü yöneticisi yapılandırılıyor"
|
|
||||||
job_autologin = "Otomatik oturum açma uygulanıyor"
|
job_autologin = "Otomatik oturum açma uygulanıyor"
|
||||||
job_netinstall = "Ek paketler kuruluyor"
|
job_netinstall = "Ek paketler kuruluyor"
|
||||||
job_setup_lvm = "LVM yapılandırılıyor"
|
job_setup_lvm = "LVM yapılandırılıyor"
|
||||||
|
|||||||
+134
-8
@@ -456,8 +456,12 @@ fn validate_manual_on(
|
|||||||
// Zorunluluk yeni tanımlarda (orig_device boş) ve LVM PV dışında
|
// Zorunluluk yeni tanımlarda (orig_device boş) ve LVM PV dışında
|
||||||
// geçerlidir: kullanıcı "ne işe yarayacak" diye sormadan kaydedemez.
|
// geçerlidir: kullanıcı "ne işe yarayacak" diye sormadan kaydedemez.
|
||||||
for p in &live_parts {
|
for p in &live_parts {
|
||||||
if p.orig_device.is_empty() && p.mountpoint.is_empty() && p.fstype != FsType::Lvm {
|
if p.mountpoint.is_empty() && mountpoint_required(Some(p), &p.fstype) {
|
||||||
return Some(t!("mp_error_empty_mountpoint").to_string());
|
// Bölümü ADIYLA söyle. Genel mesaj, ekranda birden fazla
|
||||||
|
// bölüm varken hangisinin kastedildiğini belli etmiyor ve
|
||||||
|
// kullanıcıyı (varsa) hiç ilgisi olmayan bir bölümde
|
||||||
|
// aramaya itiyordu.
|
||||||
|
return Some(t!("mp_error_empty_mountpoint_named", device = p.device).to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -468,6 +472,33 @@ fn validate_manual_on(
|
|||||||
// Çoklu disk yardımcıları
|
// Çoklu disk yardımcıları
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
|
|
||||||
|
/// Bir tanımın bağlama noktası BOŞ olmak zorunda mı?
|
||||||
|
///
|
||||||
|
/// Boş bırakmak "bu bölüm kuruluma ait değil" demektir. İki durumda
|
||||||
|
/// serbesttir:
|
||||||
|
///
|
||||||
|
/// 1. **LVM PV** — üzerinde mantıksal hacimler yaşar, kendisi
|
||||||
|
/// bağlanmaz.
|
||||||
|
/// 2. **Düzenlenen FİZİKSEL bölüm** (`orig_device` dolu) — kullanıcı
|
||||||
|
/// çift önyüklemeli kurulumda Windows'un boot bölümünü "yalnızca
|
||||||
|
/// GRUB için, mount edilmeyecek" diye işaretlemek isteyebilir.
|
||||||
|
///
|
||||||
|
/// Yeni bir tanımda (`None` ya da `orig_device` boş) ZORUNLUDUR: kullanıcı
|
||||||
|
/// "ne işe yarayacak" diye sormadan kaydedemez.
|
||||||
|
///
|
||||||
|
/// ⚠️ Bu kural hem `validate_manual_on`'da hem de kaydetme diyaloğunda
|
||||||
|
/// aynen uygulanmalı — birinde serbest olan diğerinde reddediliyorsa
|
||||||
|
/// kullanıcı "İleri"ye geçemez.
|
||||||
|
fn mountpoint_required(editing: Option<&CustomPartition>, fstype: &FsType) -> bool {
|
||||||
|
if *fstype == FsType::Lvm {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
match editing {
|
||||||
|
None => true,
|
||||||
|
Some(p) => p.orig_device.is_empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// "Yeni Bölüm" diyaloğu için varsayılan bağlama noktası önerisi.
|
/// "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
|
/// `/`, `/boot/efi` ve `swap` bir kurulumda **TEKİLDİR** — birdir. Bu
|
||||||
@@ -1919,12 +1950,25 @@ impl PartitionStep {
|
|||||||
let encrypt = self.manual.add_encrypt;
|
let encrypt = self.manual.add_encrypt;
|
||||||
let luks_password = if encrypt { self.manual.add_luks_password.clone() } else { String::new() };
|
let luks_password = if encrypt { self.manual.add_luks_password.clone() } else { String::new() };
|
||||||
|
|
||||||
// LVM PV'nin bağlama noktası YOKTUR; üzerinde
|
// Aynı kural `validate_manual_on` ile paylaşılır
|
||||||
// mantıksal hacimler yaşar. Diğer her dosya
|
// (`mountpoint_required`): ikisi de "fizikselse
|
||||||
// sistemi için mountpoint zorunludur.
|
// serbest" demeli, yoksa birinde geçen diğerinde
|
||||||
let is_pv = fstype == FsType::Lvm;
|
// reddedilir.
|
||||||
if mp.is_empty() && !is_pv {
|
let editing = if is_edit {
|
||||||
self.manual.error = Some(t!("mp_error_empty_mountpoint").to_string());
|
self.manual.edit_idx.and_then(|i| state.custom_partitions.get(i))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
if mp.is_empty() && mountpoint_required(editing, &fstype) {
|
||||||
|
// Hangi bölüm olduğunu SÖYLE: ekranda beş
|
||||||
|
// bölüm varken genel mesaj kullanıcıyı
|
||||||
|
// yanlış bölümü aramaya yolluyordu.
|
||||||
|
let label = editing
|
||||||
|
.map(|p| p.device.clone())
|
||||||
|
.unwrap_or_else(|| t!("mp_new_partition").to_string());
|
||||||
|
self.manual.error = Some(
|
||||||
|
t!("mp_error_empty_mountpoint_named", device = label).to_string()
|
||||||
|
);
|
||||||
} else if target_disk.is_empty() {
|
} else if target_disk.is_empty() {
|
||||||
self.manual.error = Some(t!("mp_select_disk_first").to_string());
|
self.manual.error = Some(t!("mp_select_disk_first").to_string());
|
||||||
} else if is_edit {
|
} else if is_edit {
|
||||||
@@ -3174,6 +3218,88 @@ mod multidisk_tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── REGRESYON: "yalnızca GRUB için" bölüm ──────────────────
|
||||||
|
|
||||||
|
/// Düzenlenen FİZİKSEL bölümün mountpoint'i boş bırakılabilir.
|
||||||
|
///
|
||||||
|
/// Kullanıcı raporu: "sda1 grub eklenecek o yüzden herhangi bir
|
||||||
|
/// mount olayı yok ve yine bağlama noktası boş olamaz uyarısı
|
||||||
|
/// alıyorum."
|
||||||
|
///
|
||||||
|
/// REGRESYON: kaydetme diyaloğunun koşulu `!is_pv` idi; fiziksel
|
||||||
|
/// bölüm düzenlenirken de mountpoint zorunluydu. Çift önyüklemeli
|
||||||
|
/// kurulumda Windows'un boot bölümünü "kuruluma ait değil, yalnızca
|
||||||
|
/// GRUB için" diye işaretlemek isteyen kullanıcı DİYALOĞU geçemiyordu.
|
||||||
|
#[test]
|
||||||
|
fn grub_only_physical_partition_may_have_no_mountpoint() {
|
||||||
|
let sda1 = p("/dev/sda", "/dev/sda1", 512, FsType::Fat32, "");
|
||||||
|
assert!(
|
||||||
|
!mountpoint_required(Some(&sda1), &FsType::Fat32),
|
||||||
|
"yalnızca GRUB için kullanılacak fiziksel bölüm boş bırakılabilmeli"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Yeni tanımda mountpoint yine de ZORUNLU.
|
||||||
|
///
|
||||||
|
/// Yukarıdaki gevşetme "her şey serbest" olmamalı — kullanıcı
|
||||||
|
/// eklediği yeni bir bölümün ne işe yarayacağını söylemeden
|
||||||
|
/// kaydedemez, yoksa sessizce mount edilmeyen bir tanım kalır.
|
||||||
|
#[test]
|
||||||
|
fn new_definition_still_requires_a_mountpoint() {
|
||||||
|
let mut new_def = p("/dev/sdc", "/dev/sdc1", 100_000, FsType::Ext4, "");
|
||||||
|
new_def.orig_device = String::new();
|
||||||
|
assert!(
|
||||||
|
mountpoint_required(Some(&new_def), &FsType::Ext4),
|
||||||
|
"yeni tanımda mountpoint zorunlu olmalı"
|
||||||
|
);
|
||||||
|
// Ekleme modunda düzenlenen bölüm yoktur → zorunlu
|
||||||
|
assert!(
|
||||||
|
mountpoint_required(None, &FsType::Ext4),
|
||||||
|
"ekleme modunda mountpoint zorunlu olmalı"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// LVM PV serbest — mount edilmez, üzerinde LV'ler yaşar.
|
||||||
|
#[test]
|
||||||
|
fn lvm_pv_never_requires_a_mountpoint() {
|
||||||
|
let physical = p("/dev/sda", "/dev/sda1", 20_000, FsType::Ext4, "");
|
||||||
|
assert!(
|
||||||
|
!mountpoint_required(Some(&physical), &FsType::Lvm),
|
||||||
|
"fiziksel bölüm LVM'ye çevrilse bile PV mountpoint istemez"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!mountpoint_required(None, &FsType::Lvm),
|
||||||
|
"yeni PV de mountpoint istemez"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Kullanıcının tam senaryosu: sda'da Windows (sda1 yalnızca GRUB
|
||||||
|
/// için, mount edilmeyecek), sdb'de Linux, sdc boş. Düzen GEÇERLİ
|
||||||
|
/// olmalı — GRUB için ayrılmış bölüm yüzünden reddedilmemeli.
|
||||||
|
#[test]
|
||||||
|
fn full_user_scenario_with_grub_only_partition_is_valid() {
|
||||||
|
let disks = vec![
|
||||||
|
disk("/dev/sda", 250),
|
||||||
|
disk("/dev/sdb", 500),
|
||||||
|
disk("/dev/sdc", 1_000),
|
||||||
|
];
|
||||||
|
let parts = vec![
|
||||||
|
// Windows boot — yalnızca GRUB, mount yok
|
||||||
|
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, "/"),
|
||||||
|
// sdc'de kullanıcının eklediği /home
|
||||||
|
p("/dev/sdc", "/dev/sdc1", 900_000, FsType::Ext4, "/home"),
|
||||||
|
];
|
||||||
|
assert_eq!(
|
||||||
|
validate_manual_on(&parts, &[], true, &disks),
|
||||||
|
None,
|
||||||
|
"GRUB için ayrılmış bölüm düzeni geçersiz kılmamalı: {:?}",
|
||||||
|
validate_manual_on(&parts, &[], true, &disks)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// numaralandırma: iki diskte bağımsız slot dağıtımı.
|
/// numaralandırma: iki diskte bağımsız slot dağıtımı.
|
||||||
/// ESKİ test (renumber_keeps_disks_independent) yalnızca fiziksel
|
/// ESKİ test (renumber_keeps_disks_independent) yalnızca fiziksel
|
||||||
/// bölümleri kullandığı için TUUTOLOJİK'ydi: global (disk-suz)
|
/// bölümleri kullandığı için TUUTOLOJİK'ydi: global (disk-suz)
|
||||||
|
|||||||
Reference in New Issue
Block a user