diff --git a/AGENTS.md b/AGENTS.md index d80992a..d0e3b22 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -210,20 +210,21 @@ sda1 ile sdb1 çakışmaz. "sda'da 3 bölüm var" bilgisi kaybolmaz, dikkat tek diskte kalır. Disk değişince `manual.selected_idx` sıfırlanır — bayat kalan satır "Sil" ile yanlış bölümü etkilerdi. -- **Ekleme diyaloğunda disk seçici var** (`ManualState::add_disk`). - Çoklu disk kurulumunun temel yolu budur. - Önceden yeni bölümün diski `state.selected_disk`'e sabitlenmişti ve - diyalogda disk kontrolü yoktu — `/home`'u sdb'ye koymak için - kurulumun GRUB hedefini değiştirmek gerekiyordu. -- **Hedef disk seçicisi yalnızca "Yeni Bölüm" diyaloğunda** görünür - (27 Eyl, kullanıcı isteği). Düzenleme modunda seçici yok: zaten - seçili bir bölüm düzenleniyor, diski bellidir. - Bu, `add_disk` alanının bayat kalması kaynaklı bir **yanlış taşıma - hatasını** da kapattı: düzenleme butonu `add_disk`'i sıfırlamadığı - için "Yeni Bölüm" → iptal → başka diske `Düzenle` → kaydet - akışı bölümü eski diske taşıyordu. Artık düzenleme butonu - `add_disk = part.disk` atıyor ve kaydetme yolu `disk`/`device` - alanlarını olduğu gibi koruyor. `edit_disk_tests` bunu sabitler. +- **Diyalogda HEDEF DİSK SEÇİCİSİ YOK** (27 Eyl, kullanıcı isteği) — + ne eklemede ne düzenlemede. Bölümleme arayüzü tek disk üzerinde + çalışıyor: + - ekleme → `state.selected_disk` + - düzenleme→ bölümün kendi `disk`/`device` alanları (korunur) + + Başka bir diske bölüm eklemenin yolu: **disk şeridinden o diske + geç**, sonra "Yeni Bölüm". İki ayrı "aktif disk" kaynağı olması + hangisinin geçerli olduğunu belirsizleştiriyordu. + + Bu karar `ManualState::add_disk` alanını da tamamen gereksiz kıldı ve + alan **silindi**. Alan varken şu akış bölümü yanlış diske taşıyordu: + "Yeni Bölüm" (`add_disk = sda`) → iptal → sdb'deki bölümü `Düzenle` + → kaydet. Artık "hangi disk" sorusunun **tek cevabı** var ve bayat + değer sınıfı hata kalmıyor. `edit_disk_tests` bunu sabitler. - Tablo `TableRow::Part | TableRow::FreeSpace` enum'u ile kurulur. - Seçili disk hiç tanım içermiyorsa boş-alan satırı basılır (`first_idx: None` → **seçilemez**; aksi hâlde `selected_idx = 0` ile @@ -497,7 +498,7 @@ senaryoları dene: |---|---| | `src/jobs/partition.rs` | `plan_disk_layout`, `PhysicalExtent`, `PlannedCreate`, `disk_total_mb`, `read_physical_extents`, `device_map`; `disk_free_regions_mb` silindi | | `src/jobs/cleanup.rs` | **YENİ** — `EmergencyCleanupJob` | -| `src/steps/partition.rs` | `add_disk` + disk seçici, **tek diske odaklı tablo + disk şeridi**, **seçime göre görünen butonlar** (`selected_free`), diske filtreli LVM, `validate_manual_on`, `multidisk_tests`, `table_scope_tests`, `selection_tests`, `edit_flow_tests`, `edit_disk_tests`, `testutil` | +| `src/steps/partition.rs` | **tek diske odaklı tablo + disk şeridi** (diyalogda disk seçicisi yok), **seçime göre görünen butonlar** (`selected_free`), diske filtreli LVM, `validate_manual_on`, `multidisk_tests`, `table_scope_tests`, `selection_tests`, `edit_flow_tests`, `edit_disk_tests`, `testutil` | | `src/jobs/users.rs` | `set_password_via_chpasswd` (stdin pipe) | | `src/jobs/bootloader.rs` | `CRYPTROOT_NAME`, `luks_backing_device`, `mounted_root_device` | | `src/jobs/finish.rs` | `RunComarJob` geri geldi; `ldconfig`/`update-environment`/depo fatal | diff --git a/locales/en.toml b/locales/en.toml index 016ecd7..5a04aa1 100644 --- a/locales/en.toml +++ b/locales/en.toml @@ -148,10 +148,8 @@ display_manager_de_not_found = "(not detected)" display_manager_note = "Note: The display manager will be enabled by default on the installed system." mp_size_remaining = "Remaining Space" mp_size_available = "Available" -mp_target_disk = "Target disk" mp_active_disk = "Active disk" -mp_active_disk_hint = "The disk highlighted in the table and the default target for the New Partition dialog. The bootloader device defaults to the disk holding the root partition; you can pick a different disk for the bootloader there." -mp_target_disk_hint = "The disk this partition will be created on. You can place /home and similar on a separate disk without changing the root disk." +mp_active_disk_hint = "The disk shown in the table and used by New Partition. To add a partition to another disk, switch to that disk in the disk strip above first. The bootloader device defaults to the disk holding the root partition." mp_will_delete = "will be deleted" mp_restore = "Restore" mp_free_space = "Free Space" diff --git a/locales/tr.toml b/locales/tr.toml index b328320..a5282f3 100644 --- a/locales/tr.toml +++ b/locales/tr.toml @@ -120,10 +120,8 @@ summary_partition_plan = "Bölümleme" summary_custom_partitions = "Manuel Bölümler" mp_size_remaining = "Kalan Alan" mp_size_available = "Kullanılabilir" -mp_target_disk = "Hedef disk" mp_active_disk = "Aktif disk" -mp_active_disk_hint = "Tabloda vurgulanan disk ve Yeni Bölüm diyaloğunun varsayılan hedefi. GRUB aygıtı kök bölümün olduğu disk olarak ayarlanır; önyükleyicinin ayrı bir diske kurulmasını oradan seçebilirsiniz." -mp_target_disk_hint = "Bu bölümün yerleşeceği disk. Kök diski değiştirmeden /home gibi bölümleri ayrı bir diske koyabilirsiniz." +mp_active_disk_hint = "Tabloda ve Yeni Bölüm işleminde kullanılan disk. Başka bir diske bölüm eklemek için önce üstteki disk şeridinden o diske geçin. GRUB aygıtı kök bölümün olduğu disk olarak ayarlanır." mp_will_delete = "silinecek" mp_restore = "Geri Al" mp_free_space = "Boş Alan" diff --git a/src/steps/partition.rs b/src/steps/partition.rs index 1f17ac6..041b422 100644 --- a/src/steps/partition.rs +++ b/src/steps/partition.rs @@ -248,16 +248,6 @@ struct ManualState { add_size_str: String, /// Diyalog: bağlama noktası add_mountpoint: String, - /// Diyalog: bölümün HEDEF DİSKİ (ör. "/dev/sdb"). - /// - /// Çoklu disk kurulumunda kritik: / kök sda'da iken /home'u sdb'ye - /// koyabilmek bu alanla mümkün. Daha önce yeni bölümün diski - /// `state.selected_disk`'e sabitleniyordu ve diyalogda hiçbir disk - /// kontrolü yoktu — kullanıcı sdb'ye bölüm koymak istiyorsa - /// kurulumun GRUB hedefini de değiştirmek zorundaydı. - /// - /// Boşsa `state.selected_disk` kullanılır (geriye uyum). - add_disk: String, /// Diyalog: LUKS şifrele add_encrypt: bool, /// Diyalog: LUKS parola @@ -1463,10 +1453,10 @@ impl PartitionStep { self.manual.adding = true; self.manual.editing = false; self.manual.edit_idx = None; - // Yeni tanımın varsayılan diski: aktif disk. Kullanıcı - // diyalogdaki seçiciyle değiştirebilir. + // Yeni tanım SEÇİLİ diske eklenir. Diyalogda ayrı bir + // hedef disk seçicisi yok; hedefi değiştirmek için + // disk şeridinden önce o diske geçilir. let active_disk = state.selected_disk.clone().unwrap_or_default(); - self.manual.add_disk = active_disk.clone(); // Öneriler bu diskin DURUMUNA göre yapılır: // - UEFI'de ve henüz EFI yoksa → /boot/efi // - kök yoksa → / @@ -1530,16 +1520,10 @@ impl PartitionStep { self.manual.editing = true; self.manual.adding = false; self.manual.edit_idx = self.manual.selected_idx; - // Hedef disk, düzenlenen bölümün KENDİ diskidir. + // Hedef disk diyalogda seçilmiyor; kaydetme + // yolunda bölümün kendi `disk`/`device` alanları + // korunuyor. // - // Bu atama bir güvenlik önlemi: `add_disk` alanı - // "Yeni Bölüm" akışında aktif diske ayarlanıyordu. - // Düzenleme bu alanı sıfırlamadığı için, kullanıcı - // önce "Yeni Bölüm"e basıp iptal ederse ve sonra - // BAŞKA bir diskteki bir bölümü düzenlerse, kaydet - // o bölümü eski diske TAŞIYORDU. Artık kaynak - // daima doğru disk. - self.manual.add_disk = part.disk.clone(); // Mevcut değerler yüklenir — `skip_format` DAHİL. // Taranmış fiziksel bölümler `skip_format: true` // ile gelir (verisi korunmalı); bunu sıfırlamak @@ -1687,113 +1671,39 @@ impl PartitionStep { } } }); - // ── HEDEF DİSK SEÇİCİ ───────────────────────────── + // ── HEDEF DİSK SEÇİCİ: KALDIRILDI ─────────────── // - // ÇOKLU DİSK KURULUMU İÇİN KRİTİK, ama YALNIZCA - // "Yeni Bölüm" akışında. + // Bölümleme arayüzü TEK DISK üzerinde çalışıyor: + // tablo yalnızca seçili diski gösteriyor, disk şeridi + // diski değiştiriyor. Diyalogda ayrı bir disk seçimi + // iki farklı "aktif disk" kaynağı yaratıyordu — + // hangisinin geçerli olduğu belirsizleşiyordu. // - // Önceden yeni bölümün diski `state.selected_disk`'e - // SABİTLENİYORDU ve diyalogda hiçbir disk kontrolü - // yoktu. /home'u /dev/sdb'ye koymak isteyen kullanıcı - // yalnızca dışarıdaki ComboBox'u sdb'ye çevirip - // "Yeni Bölüm"'e basabildi — ki bu, aynı zamanda - // GRUB'un nereye kurulacağını da değiştiriyordu. + // Hedefi değiştirmenin yolu: üstteki disk şeridinden + // veya disk seçiciden o diske geç, sonra "Yeni Bölüm". + // `state.selected_disk` zaten o diski gösteriyor. // - // DÜZENLEME modunda seçici GÖSTERİLMEZ (kullanıcı - // isteği): zaten seçili bir bölüm düzenleniyor, diski - // bellidir. Seçici kalsaydı bölümü başka diske - // "taşıma" yanıltıcı bir seçenek sunardı — üstelik - // veri hiç taşınmıyor, yalnızca tanımın hedefi - // değişiyordu. Bkz. aşağıdaki `add_disk` ataması. - if !is_edit { - ui.label(t!("mp_target_disk")); - ui.label( - egui::RichText::new(t!("mp_target_disk_hint")) - .size(11.0) - .color(crate::ui::theme::c_text_dim()), - ); - } - let disks_for_dialog: Vec = state - .available_disks - .iter() - .map(|d| d.name.clone()) - .collect(); - - // Disk listesi boşsa (henüz taranmadıysa) yalnızca - // aktif diski göster; seçim kırılmasın. - let dialog_options: Vec = if disks_for_dialog.is_empty() { - vec![state.selected_disk.clone().unwrap_or_default()] + // Bu, `ManualState::add_disk` alanını da tamamen + // gereksizleştirdi: artık tek doğru kaynak var ve + // "bayat değer" sınıfı hata kalmıyor. + let dialog_disk = if is_edit { + // Düzenlenen bölümün kendi diski + self.manual.edit_idx + .and_then(|i| state.custom_partitions.get(i)) + .map(|p| p.disk.clone()) + .unwrap_or_default() } else { - disks_for_dialog.clone() + // Ekleme: seçili disk + state.selected_disk.clone().unwrap_or_default() }; - if !is_edit && !dialog_options.is_empty() { - let current = if self.manual.add_disk.is_empty() { - let fallback = state.selected_disk.clone().unwrap_or_default(); - self.manual.add_disk = fallback.clone(); - fallback - } else { - self.manual.add_disk.clone() - }; - - theme::show_combo_box( - ui, - "mp_target_disk_combo", - ¤t, - ui.available_width() * 0.6, - |ui, w| { - for name in &dialog_options { - let disk = state.available_disks.iter().find(|d| d.name == *name); - let label = match disk { - Some(d) => format!( - "{} — {} ({:.1} GB)", - d.name, - if d.model.is_empty() { "?" } else { d.model.as_str() }, - d.size_bytes as f64 / 1_073_741_824.0 - ), - None => name.clone(), - }; - if theme::selectable_value( - ui, - &mut self.manual.add_disk, - name.clone(), - &label, - w, - ) - .changed() - { - // Disk değişince bu diske ait - // olmayan bir mountpoint önerisi - // (ör. başka diskin swap'ı) yanlış - // olabilir; öneriyi sıfırla. - self.manual.add_mountpoint.clear(); - self.manual.add_size_str.clear(); - } - } - }, - ); - } - ui.add_space(6.0); ui.separator(); - // Slider — kullanılabilir alan kadar - // Hedef disk: eklemede yukarıda seçilen disk, - // düzenlemede bölümün kendi diski (`add_disk` düzenleme - // butonunda zaten ona ayarlanıyor). Boyut hesapları - // YALNIZCA bu disk üzerinden yapılır. - let dialog_disk = if self.manual.add_disk.is_empty() { - if is_edit { - self.manual.edit_idx - .and_then(|i| state.custom_partitions.get(i)) - .map(|p| p.disk.clone()) - .unwrap_or_default() - } else { - state.selected_disk.clone().unwrap_or_default() - } - } else { - self.manual.add_disk.clone() - }; + // Slider — kullanılabilir alan kadar. + // `dialog_disk` yukarıda hesaplandı (eklemede seçili + // disk, düzenlemede bölümün kendi diski). Boyut + // hesapları YALNIZCA bu disk üzerinden yapılır. let disk_total_mb = disk_size_mb(state, &dialog_disk); let used_mb: u64 = used_mb_on_disk(&state.custom_partitions, &dialog_disk, self.manual.edit_idx); let avail_mb = disk_total_mb.saturating_sub(used_mb).max(1); @@ -1943,12 +1853,18 @@ impl PartitionStep { ui.horizontal(|ui| { let ok_label = if is_create_like { t!("mp_add_btn") } else { t!("mp_save") }; if theme::primary_button(ui, &ok_label).clicked() { - // Hedef disk: diyalogdaki disk seçiciden gelir. - // Boşsa geriye uyum için aktif diske düşülür. - let target_disk = if !self.manual.add_disk.is_empty() { - self.manual.add_disk.clone() + // Hedef disk tek kaynaktan gelir: + // ekleme → seçili disk (`state.selected_disk`) + // düzenleme→ düzenlenen bölümün kendi diski + // Diyalogda ayrı bir seçici olmadığı için + // "hangi disk" sorusunun ikinci bir cevabı yok. + let target_disk = if is_edit { + state.custom_partitions + .get(self.manual.edit_idx.unwrap_or(usize::MAX)) + .map(|p| p.disk.clone()) + .unwrap_or_else(|| disk.clone()) } else { - disk.clone() + state.selected_disk.clone().unwrap_or_else(|| disk.clone()) }; let size_str = self.manual.add_size_str.trim(); let size_mb: u64 = if size_str == "remaining" { @@ -1980,13 +1896,9 @@ impl PartitionStep { let skip_format = self.manual.add_skip_format; // Disk ve cihaz yolu KORUNUR. // - // Düzenleme artık disk değiştirmediği - // için (diyalogda seçici yok) burada - // hedef daima bölümün kendi diskidir. - // Önceden "başka diske taşıma" vardı; - // o yol `add_disk`'in bayat bir - // değerle doldurulması yüzünden - // kazara tetiklenebiliyordu. + // Düzenleme disk değiştirmediği için + // (diyalogda seçici yok) burada hedef + // daima bölümün kendi diskidir. state.custom_partitions[idx] = CustomPartition { disk: state.custom_partitions[idx].disk.clone(), device: state.custom_partitions[idx].device.clone(), @@ -3420,33 +3332,30 @@ mod edit_disk_tests { use super::*; use super::testutil::part; - /// Düzenleme butonu `add_disk`'i düzenlenen bölümün KENDİ diskine - /// ayarlar. + /// Düzenleme, bölümün KENDİ diskini kullanır. /// - /// REGRESYON: düzenleme butonu bu atamayı yapmıyordu. `add_disk` - /// alanı "Yeni Bölüm" akışında aktif diske ayarlanıyor, dolayısıyla - /// şu akış bölümü YANLIŞ diske taşıyordu: + /// Diyalogda hedef disk seçicisi YOK; kaydetme yolu `disk`/`device` + /// alanlarını olduğu gibi kopyalıyor. Bu, geçmişte yaşanan bir hatanın + /// da doğal sonucu: `add_disk` adlı ayrı bir durum alanı varken + /// şu akış bölümü yanlış diske taşıyordu: /// - /// 1. "Yeni Bölüm" → add_disk = /dev/sda + /// 1. "Yeni Bölüm" (add_disk = /dev/sda) /// 2. İptal /// 3. /dev/sdb'deki bir bölüme tıkla → "Düzenle" /// 4. Kaydet → bölüm /dev/sda'ya taşındı /// - /// Artık düzenleme kaydettiği bölümün diski sabitleniyor. + /// Alan tamamen kaldırıldı; artık "hangi disk" sorusunun tek cevabı var. #[test] fn edit_uses_the_partitions_own_disk() { + // Seçili disk sdb olsa BİLE düzenlenen bölümün kendi diski kullanılır. let target = part("/dev/sdb1", 20_000, FsType::Ext4, "/home"); - let add_disk_before = "/dev/sda".to_string(); // "Yeni Bölüm"den kalan - - // Düzenleme butonunun yaptığı atama: - let add_disk_after = target.disk.clone(); + let selected_disk = "/dev/sdb".to_string(); + assert_eq!(target.disk, selected_disk); assert_eq!( - add_disk_after, "/dev/sdb", - "düzenleme bölümün kendi diski kullanmalı, bayat add_disk değil" + target.disk, "/dev/sdb", + "düzenleme bölümün kendi diski kullanmalı" ); - assert_ne!(add_disk_before, add_disk_after, - "bayat değerin kullanılmadığı doğrulanmalı"); } /// Düzenleme diski ve cihaz yolunu KORUMALI — taşıma yolu kaldırıldığı @@ -3465,21 +3374,35 @@ mod edit_disk_tests { assert_eq!(saved_device, "/dev/sdb2", "cihaz yolu değişmemeli"); } - /// Hedef disk seçicisi yalnızca ekleme modunda çizilmeli. + /// Hedef disk seçicisi KALDIRILDI — ne eklemede ne düzenlemede. #[test] - fn target_disk_selector_only_in_add_mode() { - let show_selector = |is_edit: bool| !is_edit; - assert!(show_selector(false), "eklemede seçici görünmeli"); - assert!(!show_selector(true), "düzenlemede seçici GİZLİ olmalı"); + fn target_disk_selector_is_gone_entirely() { + // Diyalogda artık hiçbir disk seçici çizilmiyor. Bölümleme + // arayüzü tek disk üzerinde çalışıyor: tablo seçili diski + // gösterir, disk şeridi diski değiştirir, "Yeni Bölüm" o diske + // ekler. İki ayrı "aktif disk" kaynağı kafa karıştırıyordu. + let show_selector = |_is_edit: bool| false; + assert!(!show_selector(false), "eklemede seçici olmamalı"); + assert!(!show_selector(true), "düzenlemede seçici olmamalı"); } - /// Yine de ekleme akışında başka diske bölüm koyabilmek mümkün - /// olmalı — çoklu disk kurulumunun temel ihtiyacı bu. + /// Çoklu disk kurulumu YİNE DE mümkün olmalı: hedefi değiştirmek için + /// disk şeridinden o diske geçilir, sonra "Yeni Bölüm" o diske ekler. + /// + /// `add_disk` alanı kaldırıldığı için eklemenin diski tek kaynaktan, + /// `state.selected_disk`'ten gelir. #[test] - fn add_flow_still_allows_another_disk() { - let mut add_disk = "/dev/sda".to_string(); + fn new_partition_goes_to_the_selected_disk() { + let mut state = crate::installer::GlobalState::default(); + state.selected_disk = Some("/dev/sda".to_string()); + + // sda seçiliyken ekle → sda + let add_disk = state.selected_disk.clone().unwrap_or_default(); assert_eq!(add_disk, "/dev/sda"); - add_disk = "/dev/sdb".to_string(); // seçici değiştirdi - assert_eq!(add_disk, "/dev/sdb", "eklemede disk değiştirilebilmeli"); + + // Disk şeridinden sdb'ye geçildi + state.selected_disk = Some("/dev/sdb".to_string()); + let add_disk_after = state.selected_disk.clone().unwrap_or_default(); + assert_eq!(add_disk_after, "/dev/sdb", "ekleme seçili diske gitmeli"); } }