Files
gsmartcontrol/.github/copilot-instructions.md

125 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# GSmartControl – Copilot Instructions
GSmartControl is a C++20 GTK3/Gtkmm GUI for inspecting hard-drive and SSD health via SMART data
(wrapping `smartctl` from smartmontools). It supports Linux, Windows (MSYS2/MinGW), macOS, and BSDs.
## Build
```bash
mkdir build && cd build
# Standard Linux build (uses dev toolchain with warnings enabled)
cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_TOOLCHAIN_FILE=../toolchains/linux-dev.cmake
# Windows (MSYS2/MinGW64)
cmake .. -G "MSYS Makefiles" \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_TOOLCHAIN_FILE=../toolchains/win64-mingw-msys2.cmake
# Build on MSYS2/MinGW64 (from build dir)
cmake --build . --target all -j 18
```
The `configure-dev` script is a convenience wrapper: `./configure-dev -t <toolchain> -c <compiler> -b <build_type>`.
Key CMake options:
- `-DAPP_BUILD_TESTS=ON` – enable test targets
- `-DAPP_BUILD_EXAMPLES=ON` – enable example targets
- `-DAPP_COMPILER_ENABLE_WARNINGS=ON` – strict compiler warnings (set automatically by `linux-dev.cmake`)
## Tests
Tests use **Catch2** (vendored in `dependencies/catch2/`). They are only built when `-DAPP_BUILD_TESTS=ON` is passed.
```bash
# Build and run all tests
cmake .. -DAPP_BUILD_TESTS=ON
cmake --build .
ctest -C RelWithDebInfo --rerun-failed --output-on-failure
# Run a single test executable directly (from build dir)
./test_all "[smartctl_parser]" # Catch2 tag filter
./test_all "test name substring" # substring match
```
Test sources live in `src/applib/tests/` and `src/hz/tests/`; they are linked into `src/test_all/`.
## Linting
Clang-tidy config is at `.clang-tidy` in the repo root. Run it via CMake or directly:
```bash
clang-tidy src/applib/storage_device.cpp -- -std=c++20 $(pkg-config --cflags gtkmm-3.0)
```
## Architecture
The codebase is split into libraries and one GUI executable:
| Component | Location | Purpose |
|---|---|---|
| `applib` | `src/applib/` | Core logic: SMART parsing, device detection, command execution |
| `hz` | `src/hz/` | General-purpose C++ utilities (strings, filesystem, error types) |
| `rconfig` | `src/rconfig/` | Runtime config load/save with auto-save support |
| `libdebug` | `src/libdebug/` | Debug logging with named channels |
| `gui` | `src/gui/` | GTK/Gtkmm UI (windows, dialogs, Glade `.ui` files) |
### Parsing pipeline
`smartctl` output is parsed through a strategy pattern:
- JSON parsers (`smartctl_json_ata_parser`, `smartctl_json_nvme_parser`, `smartctl_json_basic_parser`) target smartctl ≥ 7.3.
- Text parsers (`smartctl_text_ata_parser`, `smartctl_text_basic_parser`) handle legacy output.
- Parsed results are stored as `StorageProperty` objects in a `StoragePropertyRepository` on `StorageDevice`.
### Device detection
`StorageDetector` is an abstract interface; platform implementations are:
- `storage_detector_linux.cpp` – scans `/dev/sd*`, `/dev/nvme*`, etc.
- `storage_detector_win32.cpp` – WMI/registry enumeration
- `storage_detector_other.cpp` – generic `/dev` scanning (BSD/macOS)
### Async execution
`AsyncCommandExecutor` wraps `CommandExecutor` (which shells out to `smartctl`) in a background thread.
Completion is signalled via **libsigc++** signals back to the GTK main loop. Never call GTK APIs from the worker thread;
queue them through signals or `Glib::signal_idle()`.
### Error handling
Use `hz::ExpectedValue<T, E>` (wrapping `tl::expected`) for recoverable errors instead of exceptions.
Enum-based error types (`StorageDeviceError`, `SmartctlParserError`) are preferred over string errors.
## Key Conventions
**Naming:**
- Classes: `PascalCase` (e.g., `StorageDevice`, `SmartctlParser`)
- Methods and members: `snake_case`; private/member fields have a trailing `_` (e.g., `device_list_`)
- GUI classes in `src/gui/` are prefixed `Gsc` (e.g., `GscMainWindow`)
- Filenames: `snake_case.cpp` / `snake_case.h`
**Headers:**
- Use `#ifndef FILENAME_H` / `#define FILENAME_H` guards (not `#pragma once`)
- Include order: standard library → third-party (GTK/Gtkmm) → project headers
- All project headers are included relative to `src/` (the include root)
**Modern C++20/23 patterns used throughout:**
- `std::optional<T>` for nullable values
- `hz::ExpectedValue<T, E>` for error-returning functions
- `std::string_view` for non-owning string parameters
- `fmt::format()` (vendored `fmt` library) for string formatting
- Smart pointers exclusively; no raw owning pointers
**Vendored dependencies** are in `dependencies/` and added via `add_subdirectory`.
Do not modify them; prefer upgrading the whole vendored copy.
**Translations:** UI strings are wrapped with `_()` (gettext). `.po` files live in `po/`.
Translations are not yet supported.
**Platform guards:** Use `#ifdef CONFIG_KERNEL_FAMILY_WINDOWS`,
`#ifdef CONFIG_KERNEL_LINUX`, etc.
## Agentic Development
Place all plans and temporary files in `agent_workspace/`. This directory is ignored by Git.