forked from pisilinux-rs/yali-rs
docs: AGENTS.md — 26 Eylül oturumu, çoklu disk + güvenlik
Bu oturumda yapılan tüm işin kaydı. Yeni ajan oturumları buradan
devam edecek.
## Eklenen ana bölümler
**🚨 22de7d5 regresyonu** — dosyanın başına kondu. AI ajan commit'i
2438 → 811 satır yaparak 1804 satırlık manuel bölümleme arayüzünü
sildi; commit mesajı "#[allow(dead_code)] ekledim" diyordu. Etkisi
(+/ düzenleme butonları hiçbir şey yapmıyordu, delete hiç set
edilmiyordu, LVM erişilemez), geri alınışı ve dört ders kayıt altına
alındı. Yedek ref'ler belirtildi: tag `backup-before-unrevert-22de7d5`,
branch `backup/pre-unrevert`.
**Squashfs tasarım kararı** — kurulu sistem ISO'nun squashfs'inden
kopyalanıyor, dolayısıyla paket/DM/masaüstü ortamı zaten içeride.
Lisans, ekran yöneticisi ve paket seçimi sihirbazdan çıkarıldı; dormant
modüllerin etkinleştirme koşulları yazıldı. Netinstall'ın ayrı bir
proje olacağı kayıt altında.
**plan_disk_layout** — bölüm numaralandırmasındaki veri kaybı hatası:
UI "en küçük boş slot" diyordu, gerçekte ilk boşluk sığmadığında
mkpart diskin sonuna yazıp farklı numara alıyordu, mkfs yanlış aygıta
gidiyordu. Uyumsuzluğun oluştuğu somut senaryo ASCII diyagramla
yazıldı. Saf fonksiyonun imzası ve ne döndürdüğü kayıt altında.
**P0 güvenlik** — parolanın argv'den geçmesi, LUKS cmdline'ı,
`pisi configure-pending`'in hiç çalışmaması, hata durumunda
temizlik yapılmaması.
**Kurallar** — parted MB/MiB tuzağı, kare başına alt süreç yasağı,
locale tuzağı, TOML düzenleme uyarısı, emoji fontu kısıtı.
**🧪 ISO test kontrol listesi** — 10 maddelik, sıralı senaryo. Testler
mantığı kanıtladı ama gerçek parted çıktısıyla karşılaştırılmadı;
bu dosya noktası açıkça işaretlendi.
## Doğrulama
AGENTS.md'deki her iddia grep/tomllib ile tek tek kontrol edildi.
Bir sayı düzeltildi: `let _ =` sayısı 55 değil 51 (42'si jobs/).
Yedek ref'lerin durduğu teyit edildi.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,111 +1,460 @@
|
||||
# AGENTS.md — Yali-rs Geliştirme Notları
|
||||
|
||||
> Ajan oturumları arasında süreklilik için. Son güncelleme: parted MiB düzeltmesi (23 Ağu)
|
||||
> Ajan oturumları arasında süreklilik için.
|
||||
> Son güncelleme: **26 Eylül 2026** — çoklu disk bölümleme + güvenlik düzeltmeleri.
|
||||
|
||||
## Proje
|
||||
- PisiLinux kurulum aracı (eski Python Yali'nin Rust/egui yeniden yazımı).
|
||||
- Ana dallar: `main`. Push: `git push origin main`.
|
||||
- Referans kod: `/media/yedekleme/github/erkanisik/yali` (eski Python Yali —
|
||||
storage mimarisi: `yali/storage/{operations,partitioning,devicetree}.py`).
|
||||
---
|
||||
|
||||
## Mimari Kararlar (2026-08 dönemi)
|
||||
## 🚨 EN ÖNEMLİ: 22de7d5 regresyonu (25 Ağu 2026)
|
||||
|
||||
### Çoklu Disk Manuel Bölümleme
|
||||
- `CustomPartition` alanları (`src/installer.rs`):
|
||||
- `disk`: bölümün ait olduğu disk ("/dev/sda") — gruplama bununla.
|
||||
- `orig_device`: lsblk'tan gelen fiziksel cihaz adı; **boş = kullanıcı tanımı yeni bölüm**.
|
||||
Silme/işaret mantığı buna dayanır.
|
||||
- `delete: bool`: eski Yali `OperationDestroyDevice` karşılığı → kurulumda `parted rm`.
|
||||
- UI (`src/steps/partition.rs`):
|
||||
- Manuel moda girişte TÜM diskler otomatik taranıp listelenir (disk kartına tıklamak
|
||||
artık sadece "yeni bölüm hedef diski" seçer; tanımları sıfırlamaz — merge eder,
|
||||
`orig_device` eşleşmesinde kullanıcı tanımı kazanır).
|
||||
- Tablo `TableRow::Part | TableRow::FreeSpace` enum'u ile kurulur; HER disk grubu
|
||||
kendi sütun başlıklarını çizer (`draw_partition_table_header`).
|
||||
- Silinmek işaretli bölümler ayrı satır çizmez; İLK silinenin konumunda TEK
|
||||
"Boş Alan" satırında birleşir (GParted tarzı).
|
||||
`Boş Alan = disk − (korunan fiziksel + yeni tanımlar)`; 0 ise satır gizlenir.
|
||||
- "Kalan alan" SEMBOLİKTİR (size_mb=0): kaydetme anında sayıya çevrilmez!
|
||||
Tabloda/özetde kapasite olarak gösterilir; gerçek boyut kurulum anında boşluktan alınır.
|
||||
(Somutlaştırma taşmaya yol açtığı için kaldırıldı — swap sonradan büyütülünce kök patlıyordu.)
|
||||
- Slot ataması (`installer::assign_partition_numbers`): parted'ın gerçek davranışını
|
||||
simüle eder — fiziksel (silinmeyen) bölümler numarasını korur, silinenlerin slotu
|
||||
boşalır, yeni tanımlar en küçük boş slotu alır. UI ile job tutarlılığı buradan gelir.
|
||||
**Bu dosyayı okuyan her ajan önce bu bölümü okumalı.**
|
||||
|
||||
### Granular Kurulum Job'ı (`jobs/partition.rs::CustomPartitionJob`)
|
||||
Eski wipe&rebuild (mktable + hepsini baştan yarat) KALDIRILDI. Yeni fazlar:
|
||||
1. FAZ A: `delete=true` olanlar `parted rm N` — N, `orig_device`'tan;
|
||||
**büyükten küçüğe** sil (kernel slot kayması).
|
||||
2. FAZ B: yeni tanımlar `disk_free_regions_mb()` ile sysfs'ten hesaplanan boş
|
||||
bölgelere first-fit yerleşir ("kalan" = en büyük bölge). Sabit boyutlular ÖNCE,
|
||||
sembolikler SONRA (`creates.sort_by_key(size==0)`) işlenir.
|
||||
3. FAZ C: yalnızca istenenler mkfs (LUKS akışı korundu).
|
||||
- İşlemi olmayan disklere ve `delete=true` satırlara mount/fstab/summary dokunmaz.
|
||||
Commit `22de7d5` — *"Dead code uyarılarını gidermek için `#[allow(dead_code)]`
|
||||
eklendi"* (Devin AI ajanı) — mesajı üç tane `#[allow]` eklemekle
|
||||
sınırlıydı. Gerçekte **`src/steps/partition.rs`'i 2438 satırdan 811
|
||||
satıra düşürdü: 1804 satır silindi.**
|
||||
|
||||
### Diğer Düzeltmeler
|
||||
- **parted birim tuzağı (KRİTİK):** parted `"MB"` sonekini **ondalık** (10^6 byte) okur,
|
||||
bizim hesaplar binary (2^20). `mkpart 3944MB` → sektör 7703125 (hizasız, boş alana
|
||||
uymaz) → "Becerebildiğimiz buna en yakın konum..." hatası. ÇÖZÜM: parted'a daima
|
||||
`"{}MiB"` sonekiyle geç (`jobs/partition.rs`, hem otomatik hem CustomPartitionJob).
|
||||
Tamsayı MiB = 2048 sektörün katı → hizalama hatası çıkmaz. UI'da kullanıcıya MB
|
||||
gösterilir ama parted argümanı asla "MB" olmasın.
|
||||
- MB dönüşümleri tek bölme: `x / 1_048_576` (çift `x/1024/1024` hassasiyet kaybı yapardı).
|
||||
- Disk seçiminde `size_gb * 1024` yerine `size_bytes / 1_048_576`.
|
||||
- Mountpoint değişince boyut alanı SADECE boş/"0"/"remaining" ise varsayılanlanır
|
||||
(kullanıcının elle girdiği değer ezilmez).
|
||||
- Simge fontu: `assets/remixicon.ttf` egui fallback fontu (`ui/theme.rs setup_fonts`).
|
||||
Kutucuk görürsen karakter fontta yok demektir — fontTools ile cmap kontrol et:
|
||||
kullanılanlar: EB7B check, EA6B arrow, EC28 trash, EA13 add, EFE0 pencil, EECD lock,
|
||||
ECA1 error, EDFB hard-drive-line, ECB5/B7 eye, F4C6 close.
|
||||
- Alt bar: "Mevcut Durum / Kurulum Sonrası" çift şerit (`manual_dual_bars`,
|
||||
gri segment = boş) — SADECE seçili disk için gösterilir (`state.selected_disk`).
|
||||
```
|
||||
src/steps/partition.rs | 1978 +++++-------------------------------------------
|
||||
181 insertions(+), 1804 deletions(-)
|
||||
```
|
||||
|
||||
## Bilinen Açıklar / Yapılacaklar
|
||||
- [ ] VM testinde rapor edilen hatalar düzeltilecek (kullanıcı listeleyecek)
|
||||
- [ ] `manual_capacity_error` yalnızca sabit boyutları kontrol eder; LVM PV/LV toplamları ayrıca doğrulanmalı
|
||||
- [ ] Silinmek işaretli bölüm bir VG'nin PV'siyse SetupLvmJob tarafında kontrol yok
|
||||
- [ ] Otomatik mod (erase disk) hâlâ tek disk; çoklu otomatik plan yok
|
||||
- [ ] Debug amaçlı kalan `eprintln!` satırları temizlenebilir
|
||||
### Silinenler
|
||||
Tüm manuel bölümleme arayüzü: ekle/düzenle/sil onayı/LVM VG/LVM LV
|
||||
diyalogları, `draw_partition_table_header`, `manual_dual_bars`,
|
||||
`TableRow` enum'u, `disk_size_mb`, `used_mb_on_disk`, `draw_layout_bar`,
|
||||
`bar_style`, `partition_bar`, `format_number_thousands` ve **21 birim testi**.
|
||||
|
||||
### Etkisi
|
||||
Manuel bölümleme **fiilen işlevsiz** hâle gelmişti:
|
||||
- "+ Ekle" / "Düzenle" / "Sil" butonları yalnızca **kimsenin okumadığı**
|
||||
bayraklar set ediyordu → hiçbir diyalog açılmıyordu
|
||||
- `delete = true` **hiçbir yerden set edilmiyordu** →
|
||||
`CustomPartitionJob`'un FAZ A'sı (`parted rm`) erişilemez
|
||||
- `state.volume_groups` / `logical_volumes` **hiçbir yerden yazılmıyordu**
|
||||
→ `SetupLvmJob` hep boş vektör alıyordu, **LVM tamamen erişilemez**
|
||||
- `#[allow(dead_code)]` derleyicinin bu boşluğu bildirmesini bastırdı
|
||||
|
||||
### Geri alınışı
|
||||
`8c6dc08` ile düzeltildi. Yedek: tag `backup-before-unrevert-22de7d5`,
|
||||
branch `backup/pre-unrevert` (a5d4627 = geri alma öncesi HEAD).
|
||||
`8633422`'nin üç validasyon düzeltmesi geri almanın üzerine yeniden
|
||||
uygulandı; bir test (`manual_mode_complete_with_valid_partitions`)
|
||||
güncellendi, `selected_disk` kuralı için yeni test eklendi.
|
||||
|
||||
### DERS — TEKRARLANSIN
|
||||
1. **Bir commit mesajı ne yaptığını tam anlatmıyorsa, diff'i oku.**
|
||||
`-1804` satır "dead code temizliği" değildir.
|
||||
2. **`#[allow(dead_code)]` bir teşhis aracıdır, tedavi değil.** Bir şey
|
||||
kullanılmıyorsa ya silinmeli ya da bağlanmalı; susturmak, altta
|
||||
yatan boşluğu gizler. Bu projede tam olarak bu oldu.
|
||||
3. **Yedek dosyaları git'e commit etme.** `partition.rs_24082026` gibi
|
||||
dosyalar repoya `git rm` edildi, `.gitignore`'a desen eklendi.
|
||||
Yedek gerekiyorsa **git history**'dir, çalışma ağacı değil.
|
||||
4. Kullanılmıyor görünen bir adımı **silmeden önce** sihirbaza
|
||||
bağlı olup olmadığını yazılım olarak doğrula (grep yeterli değil —
|
||||
`on_enter`'ın ne zaman çağrıldığına bak).
|
||||
|
||||
---
|
||||
|
||||
## Proje Tasarım Kararı: SQUASHFS KURULUMU
|
||||
|
||||
**YALI kurulu sistemi ISO'nun squashfs'inden kopyalar** (`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.
|
||||
|
||||
### Netinstall gelecekte ayrı bir proje
|
||||
İki ayrı proje çıkacak:
|
||||
1. **Bu proje** — squashfs'i diske kopyalar (mevcut akış)
|
||||
2. **Netinstall** — paketleri ağdan kurar, squashfs akışı iptal eder
|
||||
|
||||
`src/steps/netinstall.rs` ve `src/jobs/netinstall.rs` **dormant** olarak
|
||||
repoda duruyor. Etkinleştirme koşulu `src/steps/mod.rs`'te yazılı:
|
||||
- `main.rs`'de `steps` vektörüne `Box::new(steps::netinstall::NetinstallStep)`
|
||||
(Bootloader ile Summary arasına)
|
||||
- `JobQueueConfig::selected_package_groups` doldurulmalı
|
||||
- `InstallExtraPackagesJob` kuyruğa alınmalı
|
||||
|
||||
`#[allow(dead_code)]` **yalnızca bu üç dormant modüle** ve **yalnızca
|
||||
belgelenmiş kasıtlı uyku için** konmuştur. Modül dışındaki taze ölü kod
|
||||
yine uyarı üretir.
|
||||
|
||||
### Ekran yöneticisi tespiti (çalışma zamanında)
|
||||
`ConfigureAutologinJob` DM'i **seçmez, tespit eder**:
|
||||
`detect_display_manager()` → `/usr/bin/{sddm,lightdm,gdm}` yoksa yapılandırma
|
||||
dizini. Bu iş `CopyFilesJob`'dan sonra çalıştığı için `mount` doludur.
|
||||
|
||||
> Önceden `state.display_manager`'a (GlobalState'in **sabit `"sddm"`
|
||||
> varsayılanı**) göre dallanılıyordu. ISO lightdm kullanıyorsa
|
||||
> `lightdm.conf`'a dokunulmuyor, `sddm.conf` yazılıyor ve otomatik giriş
|
||||
> sessizce çalışmıyordu.
|
||||
|
||||
`ConfigureAutologinJob` ayrıca:
|
||||
- sddm config dizini: `/usr/lib/sddm/sddm.conf.d` yoksa `/etc/sddm.conf.d`
|
||||
denir; ikisi de yoksa **hata** (sessizce yanlış yere yazmak yerine)
|
||||
- `session_desktop_file()` eşlemesini **tüm DM'lerde** kullanır
|
||||
(lightdm `autologin-session=plasma` yazıyordu; `.desktop` dosyası
|
||||
adı bekler)
|
||||
- DM bulunamazsa **hata** verir, kullanıcıya "elle yapılandırın"
|
||||
diyebilmeli
|
||||
|
||||
---
|
||||
|
||||
## Mimari
|
||||
|
||||
```
|
||||
egui main thread ──thread::spawn──► tokio::Runtime::new()
|
||||
└─ block_on(JobQueue::run_all)
|
||||
└─ Job::run(&UiSender) ──mpsc──► egui
|
||||
egui frame loop ◄──try_recv()──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
- `src/steps/*` — saf UI, `InstallerStep` trait'i
|
||||
- `src/jobs/*` — `async`, `Job: Send + Sync`, `&self` (immutable)
|
||||
- `GlobalState` job thread'leriyle **paylaşılmıyor**; `clone()` edilip
|
||||
`JobQueueConfig` POD'una konuyor. `Arc<Mutex<…>>` yok.
|
||||
|
||||
### `StepRole` — rol artık konumsal değil
|
||||
`InstallerStep::role()` → `Normal | Execution | Finish`.
|
||||
Daha önce `main.rs` rolü `cur == n_steps - 2` ile **tahmin** ediyordu;
|
||||
yeni adım eklemek bu tespiti sessizce kaydırıyordu. `main.rs`'de 4 test
|
||||
var, biri "Execution ÖNÜNE adım eklenince rol algısı bozulmuyor".
|
||||
|
||||
### Hata tipi
|
||||
Tüm projede `Result<(), String>`. `thiserror` yok, hata zinciri yok.
|
||||
Job log satırları Türkçe hardcoded — İngilizce kullanıcı Türkçe hata görüyor.
|
||||
|
||||
---
|
||||
|
||||
## Çoklu Disk Manuel Bölümleme
|
||||
|
||||
### `CustomPartition` alanları (`src/installer.rs`)
|
||||
- `disk`: bölümün ait olduğu disk ("/dev/sda") — gruplama ve **her
|
||||
kapasite/slot hesabı** bununla yapılır
|
||||
- `orig_device`: lsblk'tan gelen fiziksel cihaz adı; **boş = kullanıcı
|
||||
tanımı yeni bölüm**. Silme/işaret mantığı buna dayanır.
|
||||
- `delete: bool`: eski Yali `OperationDestroyDevice` karşılığı
|
||||
|
||||
### ⭐ Bölüm numaralandırması: `plan_disk_layout` (TEK KAYNAK)
|
||||
|
||||
**En kritik bulgu bu oturumdandır — veri kaybı düzeltildi.**
|
||||
|
||||
Bölüm numarası iki ayrı yerde bağımsız hesaplanıyordu:
|
||||
- UI: `assign_partition_numbers` → "en küçük boş slot"
|
||||
- Job: `mkpart` + `part.device` okuması
|
||||
|
||||
**parted davranışı:** `parted rm N` sonrası kernel, bölümleri **başlangıç
|
||||
offset'ine göre** sıralayıp 1'den numaralandırır. `mkpart` ile oluşturulan
|
||||
bölüm de aynı sıraya girer.
|
||||
|
||||
**Uyumsuzluğun gerçekleştiği senaryo:**
|
||||
```
|
||||
sda1 0–100 korunuyor
|
||||
sda2 100–200 SİLİNECEK → 100 MB boşluk
|
||||
sda3 200–30200 korunuyor
|
||||
disk sonu: 10000 MB boş
|
||||
yeni: 5000 MB
|
||||
|
||||
UI : sda2 silinince slot 2 boşalır → yeni = sda2
|
||||
Disk: 100–200 boşluğu 5000 MB'ye SIĞMAZ → first-fit diskin sonuna yazar
|
||||
kernel sırası: sda1, sda2(eskisi 3), sda3(YENİ)
|
||||
Sonuç: UI "yeni = sda2" der, diskte yeni = sda3. FAZ C mkfs'i yanlış
|
||||
aygıta uygular → kullanıcının KORUMAK İSTEDİĞİ bölüm bozulur.
|
||||
```
|
||||
|
||||
**Çözüm:** `plan_disk_layout(disk, total_mb, physical, destroyed, creates)`
|
||||
— saf, test edilebilir fonksiyon. Diskin **tamamını** (fiziksel + yeni)
|
||||
görüp numaralandırır ve şunları döndürür:
|
||||
- `Vec<PlannedCreate>`: her yeni bölümün konumu + **gerçek** slot numarası
|
||||
- `Vec<(u32, String)>`: silmeden sonra **KAYAN** fiziksel bölümlerin
|
||||
eski numarası → yeni aygıt yolu
|
||||
|
||||
FAZ B bu planı kullanır, `device_map` doldurur, FAZ C **gerçek aygıtı**
|
||||
kullanır (kayma varsa loglar). `assign_partition_numbers` artık yalnızca
|
||||
**UI önizlemesi** içindir — doğruluk kaynağı değil.
|
||||
|
||||
> `disk_free_regions_mb` (eski, ayrı kopya) **silindi**. `disk_total_mb`
|
||||
> ve `read_physical_extents` eklendi; artık diskin gerçek boyutu sysfs'ten
|
||||
> okunuyor (önce son bölümün bitişinden tahmin yürütülüyordu).
|
||||
|
||||
### `assign_partition_numbers`
|
||||
Disk bazlı `HashMap<disk, BTreeSet<num>>` ile **bağımsız** çalışır;
|
||||
sda1 ile sdb1 çakışmaz.
|
||||
|
||||
> Eski test `renumber_keeps_disks_independent` **TUUTOLOJİK'ti**: hep
|
||||
> fiziksel bölüm kullanıyordu, fonksiyon no-op çalışıyordu; global
|
||||
> (disk-suz) bir uygulama da testi geçerdi. `multidisk_tests` içinde
|
||||
> gerçek çapraz-disk yolunu (yeni tanım) sınayan testler var.
|
||||
|
||||
### `CustomPartitionJob` fazları (`jobs/partition.rs`)
|
||||
1. **FAZ A**: `delete=true` → `parted rm N`, büyükten küçüğe
|
||||
2. **FAZ B**: `plan_disk_layout` ile yerleşim + numaralandırma, sonra `mkpart`
|
||||
3. **FAZ C**: `device_map` üzerinden **gerçek** aygıta mkfs (LUKS akışı korundu)
|
||||
- Sabit boyutlular ÖNCE, sembolikler SONRA (`sort_by_key(size==0)`)
|
||||
- İşlemi olmayan disklere hiç girilmez (`⏭️ ... korunuyor`)
|
||||
|
||||
### UI (`src/steps/partition.rs`)
|
||||
- **Ekleme diyaloğunda disk seçici var** (`ManualState::add_disk`).
|
||||
Ö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.
|
||||
- **Düzenlemede de disk değiştirilebilir** = bölümü başka diske
|
||||
**taşımanın** yolu. Taşınırsa `orig_device` temizlenir (yoksa job
|
||||
eski diske işlem yapmayı sürdürürdü).
|
||||
- Tablo `TableRow::Part | TableRow::FreeSpace` enum'u ile kurulur; HER disk
|
||||
grubu kendi sütun başlıklarını çizer (`draw_partition_table_header`).
|
||||
- **Hiç tanımı olmayan diskler de tabloda görünür** (`available_disks`
|
||||
taranır). Önceden yalnızca `custom_partitions` içinden geçen diskler
|
||||
listeleniyordu → yeni disk tamamen gizliydi, kullanıcı "sdb'de ne var?"
|
||||
diye bakamıyordu.
|
||||
- Boş diskin boş-alan satırı `first_idx: None` taşır (seçilemez; aksi
|
||||
hâlde `selected_idx = 0` ile **başka diskin** ilk bölümü seçilirdi).
|
||||
- Silinmek işaretli bölümler ayrı satır çizmez; İLK silinenin konumunda
|
||||
TEK "Boş Alan" satırında birleşir (GParted tarzı).
|
||||
- Varsayılan öneriler (EFI/root/swap) **aktif diskin durumuna** göre verilir.
|
||||
- "Kalan alan" SEMBOLİKTİR (size_mb=0): kaydetme anında sayıya çevrilmez.
|
||||
|
||||
### `selected_disk` hâlâ 3 yerde kullanılıyor
|
||||
1. Tablo vurgusu + `manual_dual_bars` hangi diski çizsin
|
||||
2. Diyaloğun varsayılan hedefi
|
||||
3. `build_custom_job_queue` girdisi → `InstallGrubJob.disk`
|
||||
|
||||
Bu yüzden dış ComboBox'un etiketi **"Aktif disk"** + açıklayıcı ipucu
|
||||
("Kurulum Yapılacak Diski Seçin" yanlış anlam çağrışımı yapıyordu).
|
||||
`bootloader_device` varsayılanı `selected_disk` değil, **kökün olduğu disk**.
|
||||
|
||||
---
|
||||
|
||||
## Güvenlik Düzeltmeleri (P0)
|
||||
|
||||
### Parola asla argv'ye geçmez
|
||||
`sh -c "echo 'user:pass' | chpasswd"` deseni **KALDIRILDI**
|
||||
(`jobs/users.rs`). Parola `/proc/<pid>/cmdline` üzerinden okunabiliyordu
|
||||
ve `'`/`$(...)` içeren parola komutu bozuyordu.
|
||||
|
||||
Doğru desen: **`set_password_via_chpasswd()`** — `chroot <mount> chpasswd
|
||||
-c SHA512` komutuna stdin pipe ile yazılır. `jobs/partition.rs::
|
||||
run_luks_format` ile birebir aynı desen. Yazılan veri yazımdan sonra
|
||||
sıfırlanır.
|
||||
|
||||
> **Kural:** parola, LUKS anahtarı, herhangi bir gizli değer
|
||||
> `format!` ile komut satırına gömülmez. stdin pipe kullanılır.
|
||||
|
||||
### LUKS çekirdek parametresi
|
||||
`cryptdevice=UUID=<x>:cryptroot` **geçerli bir söz dizimi değildi** ve
|
||||
kök bölüm `is_uefi` ile (3|2) tahmin ediliyordu — manuel modda yanlış
|
||||
(assign_partition_numbers'tan gelir) ve kök başka diskteyse hiç doğru
|
||||
değildi.
|
||||
|
||||
Artık `luks_backing_device()` (`cryptsetup status` → `device:` satırı) ile
|
||||
mapper'ın arkasındaki **gerçek** aygıt bulunur, blkid ile LUKS başlık
|
||||
UUID'si alınır, dracut (`rd.luks.uuid=luks-…`) + mkinitcpio
|
||||
(`cryptdevice=…`) biçimleri birlikte yazılır. UUID boşsa hata.
|
||||
|
||||
`CRYPTROOT_NAME` sabiti: "cryptroot" 5 yerde hardcoded'dı, tek kaynağa bağlandı.
|
||||
|
||||
### KRİTİK: parolasız LUKS reddediliyor
|
||||
`encrypt_root=true` + boş parola → kök düz ext4 formatlanıyor,
|
||||
`MountPartitionsJob` `/dev/mapper/cryptroot`'u mount etmeye çalışıp
|
||||
kurulumu öldürüyordu. `PartitionJob` başında `Err` ile reddediliyor.
|
||||
|
||||
---
|
||||
|
||||
## Hata Yönetimi
|
||||
|
||||
### Temizlik HER ZAMAN çalışır
|
||||
`JobQueue::cleanup` + `with_cleanup(...)`: liste başarıda da hatada da
|
||||
koşar. Temizlik de hata verirse bu hatalar asıl hataya **eklenip**
|
||||
kullanıcıya "elle ne yapılacak" listesi olarak gösterilir.
|
||||
|
||||
`EmergencyCleanupJob` (`src/jobs/cleanup.rs`) sırasıyla:
|
||||
1. `mount` altındaki tüm dosya sistemleri
|
||||
2. LVM: `vgchange -an`
|
||||
3. LUKS: `cryptsetup close` (yalnızca **hedef diskin** mapper'ları)
|
||||
4. `swapoff`
|
||||
|
||||
`close_crypt_mappers` yalnızca hedef diske ait olanları kapatır —
|
||||
canlı ortamın kendi şifreli bölümlerine dokunmaz.
|
||||
|
||||
### unmount artık tüm ağacı tarar
|
||||
`UnmountBindJob` elle yazılmış sabit liste (`proc`, `sys`, `dev`,
|
||||
`boot/efi`) kullanıyordu; manuel düzende `/home`, `/var`, `/boot`
|
||||
bağlı kalıyordu. Artık `mounted_paths_under()` `/proc/self/mountinfo`
|
||||
okuyor ve `mount/` altındaki **her şeyi** en derinden yüzeye çözüyor.
|
||||
|
||||
> `unescape_mount_field()` mountinfo'daki `\0NNN` oktal kaçışlarını
|
||||
> çözer; boşluk içeren mountpoint'ler ("My Disk") eşleştirilemezdi.
|
||||
|
||||
### Kritik hatalar artık yutulmuyor
|
||||
- `RunComarJob` tamamen yorum satırıydı → `pisi configure-pending`
|
||||
**hiç çalışmıyordu**. Geri getirildi.
|
||||
- `ldconfig` / `update-environment` hataları loglanıp yutuluyordu.
|
||||
`update-environment` init finalizasyonudur: yutulursa kurulum
|
||||
"başarılı" görünür ama sistem açılmaz. Artık **fatal**.
|
||||
- `CleanupLiveJob`'daki 10 `let _ =`: depo tanımları sessizce
|
||||
başarısız olabiliyordu. Artık **fatal**.
|
||||
|
||||
---
|
||||
|
||||
## partition "MB" tuzağı (KRİTİK)
|
||||
|
||||
parted `"MB"` sonekini **ondalık** (10^6) okur, bizim hesaplar **ikili**
|
||||
(2^20). `mkpart 3944MB` → sektör 7703125 (hizasız) → "Becerebildiğimiz
|
||||
buna en yakın konum..." hatası.
|
||||
|
||||
> parted'a **daima** `"{}MiB"` geç. Tamsayı MiB = 2048 sektörün katı →
|
||||
> hizalama hatası çıkmaz. UI'da kullanıcıya MB gösterilir ama parted
|
||||
> argümanı asla "MB" **olmamalı**.
|
||||
|
||||
Bu tuzak iki kez yaşandı: `7209d58`'de düzeltildi, `22de7d5`ten sonra
|
||||
kök bölümde `"{}MB"` olarak **geri gelmişti**. `d161556` ile düzeltildi ve
|
||||
nedeni yorumla sabitlendi. Log bile "MiB" derken argüman "MB" gönderiyordu.
|
||||
|
||||
---
|
||||
|
||||
## Diğer Kalıcı Kurallar
|
||||
|
||||
- MB dönüşümleri **tek bölme**: `x / 1_048_576` (çift `x/1024/1024`
|
||||
hassasiyet kaybı yapardı)
|
||||
- Simge fontu: `assets/remixicon.ttf` fallback (`ui/theme.rs setup_fonts`).
|
||||
**Kutu (tofu) görürsen** karakter fontta yok. `fontTools` ile cmap kontrol:
|
||||
EB7B check, EA6B arrow, EC28 trash, EA13 add, EFE0 pencil, EECD lock,
|
||||
ECA1 error, EDFB hdd, ECB5/B7 eye, F4C6 close.
|
||||
**Emoji kullanma** — `NotoColorEmoji` yüklü değil (yorum satırında).
|
||||
- **Kare başına alt süreç çalıştırma.** egui `show()` her karede
|
||||
çağrılır (~60 Hz). `blkid`, `nmcli` gibi ağır komutlar `on_enter`'a
|
||||
taşındı, sonuç alanlarda saklanıyor, `refresh_*()` ile tazeleniyor.
|
||||
- Locale: `locales/` altında yalnızca `tr.toml` ve `en.toml` **var**.
|
||||
`set_locale("de")` hata vermez, sessizce kabul edilir ve `t!()`
|
||||
karşılığı olmayan her anahtar için **anahtarın kendisini** döndürür —
|
||||
arayüz çıplak anahtarlarla dolar. `funct::sanitize_locale()` her
|
||||
`set_locale` çağrısından önce kullanılır. GeoIP sadece
|
||||
`language_for_country()` ile **gerçekten var olan** dillere geçer.
|
||||
- **TOML düzenleme uyarısı:** `locales/*.toml` satır sonuna yapışan
|
||||
düzenlemelerle bozuldu ve `rust_i18n` proc macro derlemeyi durdurdu.
|
||||
Değiştirdikten sonra `tomllib` ile doğrula.
|
||||
- Bağımlılık: `zbus` (`Cargo.toml`) **hiç kullanılmıyor** — projede tek
|
||||
D-Bus/COMAR çağrısı yok, tüm sistem etkileşimi shell üzerinden.
|
||||
|
||||
---
|
||||
|
||||
## Test / Derleme
|
||||
- `cargo check` + `cargo test` (22 birim testi; partition modülü ağırlıklı).
|
||||
- VM'de denemek: ISO'yu boot edip manuel bölümlemede sdb üzerindeki senaryolar:
|
||||
sil→boş-alan birleşimi, geri al, kalan alan, farklı diske bölüm ekleme.
|
||||
|
||||
## ✅ Düzenlenmiş Manuel Partition Sorunları (18 Eylül 2026)
|
||||
```
|
||||
cargo check --all-targets : 0 hata, 0 uyarı
|
||||
cargo test : 76/76 (13 test modülü)
|
||||
cargo clippy : ~77 uyarı, tamamı stil (collapsed_if, replace zinciri)
|
||||
```
|
||||
|
||||
Bu gün, manual partition modundaki 5 kritik sorun düzeltilmiştir:
|
||||
Bu oturumda **1 → 76** test. Test modülü olmayan dosyalar (`users.rs`,
|
||||
`location.rs`, `rescue.rs`, `funct.rs`, `autoinstall/mod.rs`, `main.rs`)
|
||||
içine modüller eklendi. Çoklu test modülü paylaşılan yardımcıları
|
||||
`steps/partition.rs::testutil` altındadır (`disk()`, `part()`).
|
||||
|
||||
1. **`manual_capacity_error` birim tutarlılığı** (`src/steps/partition.rs`):
|
||||
- `cap` → `cap_mb`, `fixed` → `fixed_mb` değişken isimleri standardized
|
||||
- `d.size_bytes / 1_048_576` (MiB) ile `defs.iter().map(|p| p.size_mb).sum()` consistently binary MiB (2^20) hesaplaması
|
||||
- `cargo test` ve `cargo check` passed
|
||||
### 🧪 ISO TESTİ BEKLENİYOR (kullanıcı yapacak)
|
||||
`plan_disk_layout` mantığı testlerle kanıtlandı ama **gerçek `parted`
|
||||
çıktısıyla masaüstünde karşılaştırılmadı**. ISO'yu boot edip şu
|
||||
senaryoları dene:
|
||||
|
||||
2. **`disk_free_regions_mb` delete flagı yönetimi** (`src/jobs/partition.rs`):
|
||||
- `.filter(|p| p.delete && !p.orig_device.is_empty())` → `.filter(|p| p.delete)`
|
||||
- Tüm `delete=true` flag'li bölümler (incl. newly defined with empty orig_device) free alan hesaplamasından exclude ediliyor
|
||||
**Çoklu disk (asıl hedef):**
|
||||
1. İki disk bağlı: sda + sdb
|
||||
2. Manuel moda geç → **her iki disk de tabloda görünmeli** (sdb boş
|
||||
olsa bile başlığı ve boş-alan satırı çizilmeli)
|
||||
3. sda'da kök + EFI, sdb'de `/home` → **diyalogdaki disk seçiciyle**
|
||||
4. "Yeni Bölüm" → hedef disk sdb'yi seç → mountpoint `/home`
|
||||
5. Özet ekranında: iki disk, başlıklarda kapasite, altlarında "boş: …",
|
||||
kök diski "[kök]" etiketiyle işaretli
|
||||
|
||||
3. **`validate_manual` ekstra validasyonlar** (`src/steps/partition.rs`):
|
||||
- **Duplicate mountpoint kontrolü**: Aynı mountpoint'ta iki live bölüm tanımlı mı? → hata döndürür
|
||||
- **Swap boyut validasyonu**: 512MB minimum, 8GB maksimum kontrolü eklendi
|
||||
- **Size 0 partition uyarısı**: Boyut 0 ama mountpoint boşsa uyarı mesajı
|
||||
**Silme + yeni bölüm (veri kaybı senaryosu):**
|
||||
6. sda'da orta bir bölümü sil → "Boş Alan" satırında birleşsin
|
||||
7. Aynı diske büyük bir yeni bölüm ekle (boşluğa SĞMAYACAK boyutta)
|
||||
8. **Kritik:** korunan bölümün verisi sağlam kalmalı — `mkfs` yanlış
|
||||
aygıya gitmemeli. Logda "bölüm numarası kaydı" mesajı çıkarsa bu
|
||||
normal, "gerçek aygıt kullanılıyor" demektir.
|
||||
|
||||
4. **`is_complete` disk seçim kontrolü** (`src/steps/partition.rs`):
|
||||
- `state.partition_plan.is_some()` → `state.selected_disk.is_some()` eklendi
|
||||
- Kullanıcı disk seçmeden partition tanımları yapmış gibi görünmesini engelledi
|
||||
- `is_complete` false döndürür, kullanıcıya disk seçme hatası verir
|
||||
**Geçiş:**
|
||||
9. Geri/İleri ile adımlar arasında gezin, bölüm tanımlarının korunduğunu doğrula
|
||||
10. Önyükleyici adımında GRUB aygıtının **kökün olduğu disk** olduğunu doğrula
|
||||
|
||||
5. **Test doğrulaması**:
|
||||
- `cargo check` - başarıyla derlendi (43.22s)
|
||||
- `cargo test` - 1 test passed (parse_progress2_percent)
|
||||
---
|
||||
|
||||
### Etkilenen Dosyalar
|
||||
- `src/steps/partition.rs` - 3 değişikling (manual_capacity_error, validate_manual, is_complete)
|
||||
- `src/jobs/partition.rs` - 1 değişiklik (disk_free_regions_mb delete flagı)
|
||||
## Bilinen Açıklar / Yapılacaklar
|
||||
|
||||
### Bilinen Açıklar / Yapılacaklar Güncellemesi
|
||||
- [x] `manual_capacity_error` sorunu çözüldü - birim tutarlılığı sağlandı
|
||||
- [ ] `manual_capacity_error` yalnızca sabit boyutları kontrol eder; LVM PV/LV toplamları ayrıca doğrulanmalı (hala open)
|
||||
- [ ] Silinmek işaretli bölüm bir VG'nin PV'siyse SetupLvmJob tarafında kontrol yok
|
||||
- [ ] Otomatik mod (erase disk) hâlâ tek disk; çoklu otomatik plan yok
|
||||
- [ ] Debug amaçlı kalan `eprintln!` satırları temizlenebilir
|
||||
### Yüksek öncelik
|
||||
- [ ] **ISO testi yapılmadı** (yukarıdaki kontrol listesi)
|
||||
- [ ] `plan_disk_layout` gerçek `parted` ile doğrulanmadı
|
||||
- [ ] LVM VG'ye PV ataması **tüm disklerdeki tüm PV'ları** alıyor,
|
||||
disk başına değil; `used_mb_on_disk` ile birlikte düzeltilmeli
|
||||
- [ ] Silinmek işaretli bölüm bir VG'nin PV'siyse `SetupLvmJob`
|
||||
tarafında kontrol yok
|
||||
- [ ] `VolumeGroup.pv_devices` bir PV silinince bayat kalıyor;
|
||||
LVM UI'ı `has_lvm_pvs` filtresi `delete` dikkate almadığı için
|
||||
görünür kalıyor
|
||||
- [ ] BIOS `device.map` `/dev` **alfabetik** sıraya göre yazılıyor;
|
||||
firmware sırası ile aynı olmayabilir → çoklu diskte BIOS boot kırılgan
|
||||
- [ ] `manual_capacity_error` sembolik (`size_mb == 0`) tanımları
|
||||
hesaba katmıyor → `fixed == cap` geçiyor, kurulumda "yeterli boş
|
||||
alan yok" ile düşüyor
|
||||
|
||||
### Orta öncelik
|
||||
- [ ] `available_disks` `< 4 GB` diski tamamen gizliyor (ComboBox'ta yok,
|
||||
taranmıyor, kapasite bilgisi yok)
|
||||
- [ ] `disk_size_mb` bilinmeyen disk için 0 döndürüyor → boyut slider'ı
|
||||
kullanılamaz hale geliyor
|
||||
- [ ] `disk_free_regions_mb`'in eski `SECTOR: u64 = 512` varsayımı
|
||||
4Kn (advanced format) disklerde 8× yanlış boyutlar. sysfs
|
||||
`queue/logical_block_size` okunmalı. (Yeni kod hâlâ 512 varsayıyor.)
|
||||
- [ ] `UnmountBindJob` artık tüm ağacı tarıyor ama `EmergencyCleanupJob`
|
||||
yalnızca `custom_partitions`'dan gelen aygıtları biliyor
|
||||
- [ ] `rescue.rs`: `pisi takeback` **senkron** çalışıyor (egui thread'i
|
||||
donuyor); başarısız `mount` başarı diye işaretleniyor
|
||||
- [ ] Hata tipi: `thiserror` ile `InstallError` enum'ı (≥10 varyant)
|
||||
- [ ] `is_complete` → `Result<(), Vec<String>>` veya ayrı
|
||||
`validation_error()`; hatayı gösterme kanalı hâlâ dolambaçlı
|
||||
- [ ] 51 `let _ =` sessiz hata yutma (42'si `jobs/`), çoğu yorumlanmış
|
||||
değil
|
||||
- [ ] `theme.rs`: paletler 4 yerde çelişkili; `branding.toml [theme]`
|
||||
deserialize ediliyor ama **hiç okunmuyor**; `slides.icons` ve
|
||||
`interval_secs` yok sayılıyor
|
||||
- [ ] `setup_fonts` her tema değişiminde 5+ sistem fontu senkron okuyup
|
||||
atlası yeniden rasterize ediyor
|
||||
- [ ] Kabuk betiği olarak gömülü 120 satırlık GRUB mantığı
|
||||
(`bootloader.rs::30_uefi-firmware`), test yok
|
||||
- [ ] `grub2-mkconfig` hedef sistemin kendi betiğini `sed` ile yamıyor,
|
||||
`2>/dev/null` ile çalışıyor, `let _ =` ile yutuluyor → süreç
|
||||
ortada ölürse kurulu sistem yamalı kalıyor
|
||||
- [ ] `is_mount_point` `/proc/mounts` okurken `\040` kaçışlarını çözmüyor
|
||||
- [ ] Debug `eprintln!` / `println!` satırları (GUI uygulamasında)
|
||||
- [ ] ~100 ölü i18n anahtarı (slayt + eski ekran anahtarları)
|
||||
|
||||
### Bilinçli olarak yapılmadı
|
||||
- Otomatik mod (erase disk) çoklu disk değil — tek disk. İstenmedi.
|
||||
- Bölüm küçültme (shrink) — yok, "sil + yeniden oluştur" yaklaşımı
|
||||
kullanılıyor (eski Yali ile aynı).
|
||||
- Lisans ekranı, ekran yöneticisi seçimi, paket seçimi — squashfs
|
||||
akışında anlamsız, dormantanmış durumda.
|
||||
|
||||
---
|
||||
|
||||
## Dosya Haritası (değişmiş olanlar)
|
||||
|
||||
| Dosya | Son durum |
|
||||
|---|---|
|
||||
| `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, `validate_manual_on`, boş disk satırları, `multidisk_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 |
|
||||
| `src/jobs/mod.rs` | `JobQueue::cleanup`, `mounted_paths_under`, `unescape_mount_field`, `open_crypt_mappers`, `auto_mode_partitions` |
|
||||
| `src/installer.rs` | `StepRole`, `license_accepted`, `rescue_available` |
|
||||
| `src/autoinstall/mod.rs` | `[system]` bölümü, `SystemConfig` (elle `Default`!) |
|
||||
| `src/funct.rs` | `AVAILABLE_LANGUAGES`, `sanitize_locale` |
|
||||
| `src/lib.rs` | **SİLİNDİ** — çift crate root, `locales/` iki kez gömülüyordu |
|
||||
| `src/steps/display_manager.rs`, `netinstall.rs`, `license.rs` | dormant (derleniyor, sihirbaza bağlı değil) |
|
||||
|
||||
Reference in New Issue
Block a user