Merge pull request 'Merge dev in testing: Feat: Erstellt die Crate program' (#1) from dev into testing
Testing Build, Check & Preview Release / Build, Check & Create Preview Release (push) Successful in 15s

Reviewed-on: #1
This commit was merged in pull request #1.
This commit is contained in:
2026-08-26 17:36:18 +00:00
8 changed files with 251 additions and 77 deletions
-9
View File
@@ -1,9 +0,0 @@
[registry]
default = "gitea"
[registries.gitea]
index = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/" # Sparse index
# index = "https://gitea.creative-dragonslayer.de/Rust-Crates/_cargo-index.git" # Git
[net]
git-fetch-with-cli = true
+1
View File
@@ -3,6 +3,7 @@
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
+11 -9
View File
@@ -1,12 +1,14 @@
# AGENTS.md
Dieses Dokument definiert Richtlinien, Konventionen und Arbeitsanweisungen für KI-Agenten und LLM-Tools, die an diesem Repository oder daraus erstellten Rust-Crates arbeiten.
Dieses Dokument definiert Richtlinien, Konventionen und Arbeitsanweisungen für KI-Agenten und LLM-Tools, die an der Rust-Bibliothek `program-ctdra` arbeiten.
---
## 1. Projektübersicht & Kontext
- **Typ:** Rust Library Crate Template
- **Name:** `program-ctdra`
- **Typ:** Rust Library Crate
- **Zweck:** Einfache und zuverlässige Ermittlung des Programmnamens (Dateistamm der aktuellen ausführbaren Datei) mit sicherem Fallback
- **Rust Edition:** `2024`
- **Einstiegspunkt:** `src/lib.rs`
- **CI/CD Plattform:** Gitea Actions (`.gitea/workflows/`)
@@ -20,11 +22,12 @@ Dieses Dokument definiert Richtlinien, Konventionen und Arbeitsanweisungen für
### 2.1 Sprache & Idiomatik
- Verwende modernes, idiomatisches Rust (Edition 2024).
- Bevorzuge explizite Typen und klare Signaturen in öffentlichen Schnittstellen (`pub`).
- Halte die API ergonomisch und benutzerfreundlich.
- Halte die API ergonomisch, minimalistisch und benutzerfreundlich.
- Vermeide unnötige externe Abhängigkeiten (Zero Dependencies).
### 2.2 Fehlerbehandlung
- Nutze `Result<T, E>` und `Option<T>` für alle potenziell fehlschlagenden Operationen.
- Definiere aussagekräftige, domänenspezifische Fehlertypen (z. B. via `thiserror` oder standardmäßig `std::error::Error`).
- Definiere aussagekräftige, domänenspezifische Fehlertypen, falls zutreffend.
- **Verboten im produktiven Bibliothekscode (`src/`):**
- Unbegründete `unwrap()`, `expect()` oder `panic!()` Aufrufe.
- Ignorieren von Fehlern via `let _ = ...`, es sei denn, es ist explizit begründet und dokumentiert.
@@ -92,10 +95,9 @@ Die CI/CD-Pipelines werden über Gitea Actions gesteuert:
---
## 5. Arbeitsanweisungen für Agenten bei Projekt-Initialisierung
## 5. Richtlinien für Agenten bei Änderungen
Wenn dieser Template-Stand verwendet wird, um eine neue Crate zu erstellen:
1. Aktualisiere die `Cargo.toml`-Metadaten (`name`, `version`, `authors`, `repository`, `description`).
2. Passe die `README.md` an die konkrete Funktionalität der neuen Crate an.
3. Behalte die Gitea-Workflows bei oder passe sie an das Ziel-Repository an.
1. Halte die `Cargo.toml`-Metadaten (`name`, `version`, `authors`, `repository`, `description`) aktuell und konsistent.
2. Halte die `README.md` synchron mit allen Änderungen an der API oder Funktionalität der Crate.
3. Behalte die Gitea-Workflows bei und stelle sicher, dass alle Validierungsschritte bestehen.
4. Stelle sicher, dass keine Secrets, temporären Build-Dateien (`target/`) oder IDE-spezifischen Caches (außer `.idea` Konfigurationen) committed werden.
Generated
+1 -1
View File
@@ -3,5 +3,5 @@
version = 4
[[package]]
name = "rust-creat-template"
name = "program-ctdra"
version = "1.0.0"
+5 -5
View File
@@ -1,12 +1,12 @@
[package]
name = "rust-creat-template" # TODO Setzen
version = "1.0.0" # TODO Setzen
name = "program-ctdra"
version = "1.0.0"
edition = "2024"
authors = ['DragonSlayer_14'] # TODO Setzen
authors = ['DragonSlayer_14']
readme = "README.md"
license = "GPL-3.0-or-later"
repository = "https://gitea.creative-dragonslayer.de/Templates/rust-crate-template" # TODO Setzen
description = "Ein Template-Projekt, das fürs erstellen von Rust-Crates verwendet werden kann." # TODO Setzen
repository = "https://gitea.creative-dragonslayer.de/Rust-Crates/program"
description = "Eine schlanke Rust-Bibliothek zur einfachen und zuverlässigen Ermittlung des Namens der aktuellen ausführbaren Datei."
[dependencies]
+63 -53
View File
@@ -1,17 +1,66 @@
# Rust Crate Template
# program-ctdra
Ein vorkonfiguriertes Template-Projekt für die schnelle und standardisierte Entwicklung von Rust-Crates (Libraries) mit automatisierter CI/CD-Pipeline für Gitea.
Eine schlanke, abhängigkeitsfreie Rust-Bibliothek zur einfachen und zuverlässigen Ermittlung des Programmnamens (Dateistamm der aktuellen ausführbaren Datei).
---
## 🚀 Übersicht & Features
- **Rust Edition 2024**: Moderner Rust-Standard mit optimierten Profil-Einstellungen (`profile.release.debug = "none"`).
- **Einfache API**:
- `program_name()`: Ermittelt den Programmnamen mit sicherem Fallback (`"app"`).
- `program_name_or(fallback)`: Ermittelt den Programmnamen mit anpassbarem Fallback.
- `try_program_name()`: Gibt den Programmnamen als `Option<String>` zurück.
- **Zero Dependencies**: Nutzt ausschließlich die Rust-Standardbibliothek (`std::env`, `std::path`).
- **Rust Edition 2024**: Moderner Rust-Standard mit optimierten Release-Profil-Einstellungen (`debug = "none"`).
- **Vollständig getestet & dokumentiert**: Mit Unit-Tests, Integrationstests und getesteten Rustdoc-Codebeispielen.
- **Automatisierte CI/CD-Workflows (Gitea Actions)**:
- **Testing-Pipeline (`testing`-Branch)**: Führt Tests und Compiler-Checks aus und erstellt automatisch ein Gitea Pre-Release (`v<VERSION>-preview`) inklusive `.crate`-Paket als Release-Asset.
- **Main-Release-Pipeline (`main`-Branch)**: Führt Tests und Compiler-Checks aus, paketiert die Crate, veröffentlicht sie in der Gitea Cargo Package Registry und erstellt ein offizielles Gitea Release (`v<VERSION>`) mit Asset.
- **Integrierte Gitea Package Registry**: Vorkonfigurierte sparse index Registry-Anbindung.
- **GPL-3.0-or-later Lizenz**: Vorkonfiguriert mit Lizenzdatei und Metadaten.
- **Testing-Pipeline (`testing`-Branch)**: Baut, testet und erstellt automatisch ein Gitea Pre-Release (`v<VERSION>-preview`) inklusive `.crate`-Paket.
- **Main-Release-Pipeline (`main`-Branch)**: Baut, testet, paketiert, veröffentlicht in der Gitea Cargo Package Registry und erstellt ein Gitea Release (`v<VERSION>`).
- **GPL-3.0-or-later Lizenz**: Freie Software unter der GNU General Public License v3.0 oder neuer.
---
## 📦 Installation & Einbindung
Um `program-ctdra` aus der Gitea Package Registry in einem Cargo-Projekt zu verwenden:
### 1. Registry konfigurieren
Füge die Gitea Package Registry zu deiner lokalen `~/.cargo/config.toml` oder projektweiten `.cargo/config.toml` hinzu:
```toml
[registries.gitea]
index = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/"
```
### 2. Abhängigkeit in `Cargo.toml` deklarieren
```toml
[dependencies]
program-ctdra = { version = "1.0.0", registry = "gitea" }
```
---
## 💡 Anwendungsbeispiele
```rust
use program_ctdra::{program_name, program_name_or, try_program_name};
fn main() {
// 1. Standard-Aufruf mit Fallback "app"
let name = program_name();
println!("Aktuelles Programm: {name}");
// 2. Mit benutzerdefiniertem Fallback
let service_name = program_name_or("mein-dienst");
println!("Dienst-Name: {service_name}");
// 3. Optionale Ermittlung ohne Fallback
match try_program_name() {
Some(name) => println!("Executable-Name ermittelt: {name}"),
None => eprintln!("Konnte Programmnamen nicht ermitteln!"),
}
}
```
---
@@ -25,7 +74,9 @@ Ein vorkonfiguriertes Template-Projekt für die schnelle und standardisierte Ent
│ └── testing.yaml # CI/CD: Test, Check & Pre-Release für 'testing'
├── .idea/ # Vorkonfigurierte JetBrains IDE Einstellungen
├── src/
│ └── lib.rs # Einstiegspunkt der Crate / Library
│ └── lib.rs # Bibliotheks-Implementierung & Unit-Tests
├── tests/
│ └── integration_test.rs # Integrationstests für die öffentliche API
├── Cargo.lock
├── Cargo.toml # Crate-Manifest & Metadaten
├── LICENSE # GNU General Public License v3.0
@@ -35,39 +86,16 @@ Ein vorkonfiguriertes Template-Projekt für die schnelle und standardisierte Ent
---
## 🛠️ Verwendung als Template
## 💻 Lokale Entwicklung & Validierung
### 1. Template initialisieren & Metadaten anpassen
Passe nach dem Klonen bzw. Erstellen des neuen Repositories die Platzhalter in `Cargo.toml` an:
```toml
[package]
name = "mein-crate-name"
version = "0.1.0"
edition = "2024"
authors = ['DeinName <deine.email@example.com>']
readme = "README.md"
license = "GPL-3.0-or-later"
repository = "https://gitea.example.com/Organisation/mein-crate-name"
description = "Beschreibung der Crate."
```
### 2. Gitea Repository Secrets einrichten
Für die Veröffentlichung und Release-Erstellung in Gitea Actions muss mindestens ein Access-Token als Repository-Secret hinterlegt werden (z. B. unter `Einstellungen -> Secrets -> Actions`):
- `PACKAGE_TOKEN` (oder alternativ `RELEASE_TOKEN`, `GITEA_TOKEN`): Ein Personal Access Token mit Berechtigungen für Packages (`write:package`) und Repositories/Releases (`write:repository`).
---
## 💻 Lokale Entwicklung & Befehle
Die gängigen Cargo-Befehle zur Entwicklung:
Die gängigen Cargo-Befehle zur Entwicklung und Verifizierung:
- **Kompilierung prüfen:**
```bash
cargo check --all-targets
```
- **Tests ausführen:**
- **Tests ausführen (Unit-, Integrations- und Doc-Tests):**
```bash
cargo test
```
@@ -97,25 +125,7 @@ Die gängigen Cargo-Befehle zur Entwicklung:
| `testing` | Push auf `testing` | • `cargo test`<br>• `cargo check --all-targets`<br>• `cargo package`<br>• Erstellt/Aktualisiert Pre-Release `v<VERSION>-preview` mit `.crate`-Asset |
| `main` | Push auf `main` | • `cargo test`<br>• `cargo check --all-targets`<br>• `cargo package`<br>• Veröffentlicht Crate in Gitea Package Registry<br>• Erstellt/Aktualisiert Release `v<VERSION>` mit `.crate`-Asset |
> **Hinweis zur Versionierung:** Die Versionsnummer wird automatisch aus `Cargo.toml` (`version = "..."`) ausgelesen. Passe vor einem Merge auf `main` oder `testing` die Version in `Cargo.toml` entsprechend SemVer an.
---
## 📦 Verwenden der Crate in anderen Projekten
Um die in der Gitea Package Registry veröffentlichte Crate in einem anderen Cargo-Projekt zu verwenden:
1. Trage die Registry in deiner lokalen `~/.cargo/config.toml` oder projektweiten `.cargo/config.toml` ein:
```toml
[registries.gitea]
index = "sparse+https://gitea.creative-dragonslayer.de/api/packages/Rust-Crates/cargo/"
```
2. Binde die Crate in deiner `Cargo.toml` ein:
```toml
[dependencies]
mein-crate-name = { version = "1.0.0", registry = "gitea" }
```
> **Hinweis zur Versionierung:** Die Versionsnummer wird automatisch aus `Cargo.toml` (`version = "..."`) ausgelesen. Vor einem Merge auf `main` oder `testing` muss die Version in `Cargo.toml` entsprechend SemVer angepasst werden.
---
+148
View File
@@ -0,0 +1,148 @@
//! # program-ctdra
//!
//! Eine schlanke, abhängigkeitsfreie Rust-Bibliothek zur einfachen und zuverlässigen
//! Ermittlung des aktuellen Programmnamens (des Dateistamms der ausführbaren Datei).
//!
//! ## Übersicht
//!
//! - [`program_name`]: Gibt den Programmnamen zurück oder `"app"`, falls dieser nicht ermittelt werden kann.
//! - [`try_program_name`]: Gibt den Programmnamen als [`Option<String>`] zurück.
//! - [`program_name_or`]: Gibt den Programmnamen oder einen benutzerdefinierten Fallback zurück.
//!
//! ## Beispiele
//!
//! ```rust
//! use program_ctdra::{program_name, program_name_or, try_program_name};
//!
//! // Standard-Programmname mit Fallback "app"
//! let name = program_name();
//! assert!(!name.is_empty());
//!
//! // Programmname mit benutzerdefiniertem Fallback
//! let custom = program_name_or("mein-dienst");
//! assert!(!custom.is_empty());
//!
//! // Optionale Ermittlung ohne Fallback
//! if let Some(prog) = try_program_name() {
//! println!("Ausgeführt als: {prog}");
//! }
//! ```
use std::env;
use std::path::Path;
/// Ermittelt den Programmnamen (Dateistamm) aus einem übergebenen Pfad.
fn extract_stem_from_path(path: &Path) -> Option<String> {
path.file_stem()
.map(|s| s.to_string_lossy().to_string())
.filter(|s| !s.is_empty())
}
/// Versucht, den Programmnamen (Dateistamm der aktuellen ausführbaren Datei) zu ermitteln.
///
/// Gibt `Some(String)` zurück, wenn der Pfad der aktuellen Executable ermittelt werden
/// konnte und ein nicht-leerer Dateistamm vorhanden ist, andernfalls `None`.
///
/// # Beispiele
///
/// ```rust
/// use program_ctdra::try_program_name;
///
/// let maybe_name = try_program_name();
/// // In einer regulären Test- oder Binärumgebung ist der Name in der Regel vorhanden:
/// assert!(maybe_name.is_some());
/// ```
#[must_use]
pub fn try_program_name() -> Option<String> {
env::current_exe()
.ok()
.and_then(|p| extract_stem_from_path(&p))
}
/// Liefert den Programmnamen (Dateistamm der aktuellen ausführbaren Datei) oder einen Fallback-Wert.
///
/// # Parameter
///
/// - `fallback`: Ein Wert, der in ein [`String`] umgewandelt werden kann und verwendet wird,
/// wenn der Programmname nicht ermittelt werden kann.
///
/// # Beispiele
///
/// ```rust
/// use program_ctdra::program_name_or;
///
/// let name = program_name_or("fallback_app");
/// assert!(!name.is_empty());
/// ```
#[must_use]
pub fn program_name_or(fallback: impl Into<String>) -> String {
try_program_name().unwrap_or_else(|| fallback.into())
}
/// Liefert den Programmnamen (Dateistamm der aktuellen ausführbaren Datei).
///
/// # Rückgabewert
///
/// - Dateistamm der aktuellen Executable als [`String`].
/// - Fallback `"app"`, wenn der Name nicht ermittelt werden kann.
///
/// # Beispiele
///
/// ```rust
/// use program_ctdra::program_name;
///
/// let name = program_name();
/// assert!(!name.is_empty());
/// ```
#[must_use]
pub fn program_name() -> String {
program_name_or("app")
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::PathBuf;
#[test]
fn test_extract_stem_from_path_valid() {
assert_eq!(
extract_stem_from_path(&PathBuf::from("/usr/bin/my-daemon")),
Some("my-daemon".to_string())
);
assert_eq!(
extract_stem_from_path(&PathBuf::from("/opt/apps/server.exe")),
Some("server".to_string())
);
assert_eq!(
extract_stem_from_path(&PathBuf::from("app.bin")),
Some("app".to_string())
);
}
#[test]
fn test_extract_stem_from_path_empty_or_root() {
assert_eq!(extract_stem_from_path(&PathBuf::from("/")), None);
assert_eq!(extract_stem_from_path(&PathBuf::from("")), None);
}
#[test]
fn test_program_name_returns_non_empty() {
let name = program_name();
assert!(!name.is_empty());
}
#[test]
fn test_try_program_name_in_test_env() {
let name = try_program_name();
assert!(name.is_some());
let name_str = name.unwrap();
assert!(!name_str.is_empty());
}
#[test]
fn test_program_name_or_with_custom_fallback() {
let name = program_name_or("custom_fallback");
assert!(!name.is_empty());
}
}
+22
View File
@@ -0,0 +1,22 @@
use program_ctdra::{program_name, program_name_or, try_program_name};
#[test]
fn test_public_api_program_name() {
let name = program_name();
assert!(!name.is_empty());
}
#[test]
fn test_public_api_try_program_name() {
let name = try_program_name();
assert!(name.is_some());
if let Some(n) = name {
assert!(!n.is_empty());
}
}
#[test]
fn test_public_api_program_name_or() {
let name = program_name_or("fallback_integration_test");
assert!(!name.is_empty());
}