# Contributing to Driftwood ## Building from source ### Dependencies - Rust 1.75+ and Cargo - GTK 4.16+ development headers (`libgtk-4-dev` or `gtk4-devel`) - libadwaita 1.6+ development headers (`libadwaita-1-dev` or `libadwaita-devel`) - SQLite 3 development headers - gettext development headers - `glib-compile-resources` and `glib-compile-schemas` (from `libglib2.0-dev-bin`) ### Quick start ```sh git clone https://github.com/driftwood-app/driftwood cd driftwood cargo build cargo run ``` ### Running tests ```sh cargo test ``` ## Project structure ``` driftwood/ Cargo.toml # Rust package manifest build.rs # GResource and GSettings compilation meson.build # Meson build system for installation src/ main.rs # Entry point, GResource init, CLI dispatch application.rs # GtkApplication subclass, CSS loading, app actions window.rs # Main window, navigation, scanning orchestration config.rs # App ID and version constants cli.rs # Command-line interface (clap) i18n.rs # Internationalization (gettext wrappers) core/ # Backend logic (no GTK dependencies) database.rs # SQLite database (rusqlite), all queries discovery.rs # Filesystem scanning, AppImage detection, SHA256 inspector.rs # AppImage metadata extraction (icon, desktop entry) integrator.rs # Desktop integration (.desktop files, icons) launcher.rs # AppImage launching with FUSE/sandbox support updater.rs # Update checking and applying (GitHub, zsync) fuse.rs # FUSE status detection wayland.rs # Wayland compatibility analysis security.rs # CVE scanning via OSV.dev API duplicates.rs # Duplicate and multi-version detection footprint.rs # Disk footprint analysis (config/data/cache) orphan.rs # Orphaned desktop entry detection and cleanup ui/ # GTK4/libadwaita UI components library_view.rs # Main grid/list view of AppImages app_card.rs # Individual AppImage card widget detail_view.rs # Full detail page for a single AppImage dashboard.rs # System health dashboard preferences.rs # Preferences dialog update_dialog.rs # Update check and apply dialog duplicate_dialog.rs # Duplicate resolution dialog cleanup_wizard.rs # Disk space reclamation wizard security_report.rs # Security scan results view integration_dialog.rs # Desktop integration confirmation widgets.rs # Shared utility widgets (badges, sections) data/ app.driftwood.Driftwood.gschema.xml # GSettings schema app.driftwood.Driftwood.desktop # Desktop entry for Driftwood itself app.driftwood.Driftwood.metainfo.xml # AppStream metadata resources.gresource.xml # GResource manifest resources/style.css # Application CSS po/ # Translation files POTFILES.in # Files with translatable strings LINGUAS # Available translations build-aux/ # Build helpers app.driftwood.Driftwood.json # Flatpak manifest build-appimage.sh # AppImage build script packaging/ PKGBUILD # Arch Linux AUR package ``` ## Architecture The codebase is split into three layers: 1. **core/** - Pure Rust business logic. No GTK dependencies. Can be tested independently. Each module handles one concern. 2. **ui/** - GTK4/libadwaita widgets. Each view is a function that builds a widget tree. Uses `Rc` for shared database access. 3. **window.rs / application.rs** - Orchestration layer. Connects UI to core, handles navigation, spawns background threads for scanning. Background work (scanning, update checks, security scans) runs on `gio::spawn_blocking` threads. Results are sent back to the main thread via `glib::spawn_future_local`. ## Coding conventions - Follow standard Rust formatting (`cargo fmt`) - All new code must compile with zero warnings - Add tests for core/ modules (81+ tests currently) - Use `log::info!`, `log::warn!`, `log::error!` for diagnostics - User-facing strings should be wrapped in `i18n()` for translation - Use `adw::` widgets over raw `gtk::` when an Adwaita equivalent exists - Status badges use CSS classes: `badge-success`, `badge-warning`, `badge-error` ## Database SQLite database stored at `~/.local/share/driftwood/driftwood.db`. Schema migrates automatically (v1 through v4). All queries are in `core/database.rs`. ## Testing ```sh # Run all tests cargo test # Run tests for a specific module cargo test core::database cargo test core::updater # Run with output cargo test -- --nocapture ``` Tests use `Database::open_in_memory()` for isolation.