diff --git a/src/config.rs b/src/config.rs index 40a537b..f10b64f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,6 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; +use crate::utils::sanitize_env_vars; fn default_true() -> bool { true @@ -108,7 +109,22 @@ pub fn get_config_file_path() -> PathBuf { /// Lädt die Anwendungskonfiguration. Verwendet Standardwerte, falls keine Datei vorhanden ist. pub fn load_config() -> AppConfig { - config_ctdra::load_config::() + let mut config = config_ctdra::load_config::(); + let mut env_vars = std::env::vars().collect(); + sanitize_env_vars(&mut env_vars); + if let Some(gitea_url) = env_vars.get("GITEA_URL") { + config.gitea_url = Some(gitea_url.clone()); + } + if let Some(gitea_token) = env_vars.get("GITEA_TOKEN") { + config.gitea_token = Some(gitea_token.clone()); + } + if let Some(registry_owner) = env_vars.get("REGISTRY_OWNER") { + config.registry_owner = Some(registry_owner.clone()); + } + if let Some(github_token) = env_vars.get("GITHUB_TOKEN") { + config.github_token = Some(github_token.clone()); + } + config } /// Speichert die Anwendungskonfiguration auf der Festplatte. diff --git a/src/lib.rs b/src/lib.rs index 4d04728..16da4ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,3 +6,4 @@ pub mod config; pub mod gitea; pub mod github; pub mod pipeline; +pub mod utils; diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..02a2138 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,31 @@ + +/// Sanitizes a string by removing surrounding quotes (single or double). +/// +/// # Arguments +/// +/// * `input` - The string to sanitize. +/// +/// # Returns +/// +/// The sanitized string with surrounding quotes removed. +pub fn sanitize_string(input: &str) -> String { + let trimmed = input.trim(); + if trimmed.starts_with('"') && trimmed.ends_with('"') { + trimmed[1..trimmed.len() - 1].to_string() + } else if trimmed.starts_with('') && trimmed.ends_with('') { + trimmed[1..trimmed.len() - 1].to_string() + } else { + trimmed.to_string() + } +} + +/// Sanitizes environment variables by removing surrounding quotes. +/// +/// # Arguments +/// +/// * `env_vars` - A reference to a mutable map of environment variables. +pub fn sanitize_env_vars(env_vars: &mut std::collections::HashMap) { + for (_key, value) in env_vars.iter_mut() { + *value = sanitize_string(value); + } +} diff --git a/tests/config_tests.rs b/tests/config_tests.rs index c844d4b..0fbb851 100644 --- a/tests/config_tests.rs +++ b/tests/config_tests.rs @@ -1,53 +1,92 @@ -use mirror_package::config::{AppConfig, RepoConfig}; +use mirror_package::config::{load_config, AppConfig, RepoConfig}; +use mirror_package::utils::{sanitize_env_vars, sanitize_string}; +use std::collections::HashMap; + +#[test] +fn test_sanitize_env_vars() { + let mut env_vars = HashMap::new(); + env_vars.insert("GITEA_URL".to_string(), "\"https://gitea.example.com\"".to_string()); + env_vars.insert("GITEA_TOKEN".to_string(), "\"token123\"".to_string()); + env_vars.insert("REGISTRY_OWNER".to_string(), "\"owner\"".to_string()); + env_vars.insert("GITHUB_TOKEN".to_string(), "\"github_token123\"".to_string()); + + sanitize_env_vars(&mut env_vars); + + assert_eq!(env_vars.get("GITEA_URL").unwrap(), "https://gitea.example.com"); + assert_eq!(env_vars.get("GITEA_TOKEN").unwrap(), "token123"); + assert_eq!(env_vars.get("REGISTRY_OWNER").unwrap(), "owner"); + assert_eq!(env_vars.get("GITHUB_TOKEN").unwrap(), "github_token123"); +} + +#[test] +fn test_load_config_with_env_vars() { + // This test relies on environment variables being set externally. + // To avoid `unsafe` blocks, we skip setting them programmatically. + // In a real test environment, set these variables before running the test: + // GITEA_URL="https://gitea.example.com" + // GITEA_TOKEN="token123" + // REGISTRY_OWNER="owner" + // GITHUB_TOKEN="github_token123" + let config = load_config(); + + // Only assert if the environment variables are set + if std::env::var("GITEA_URL").is_ok() { + assert_eq!(config.gitea_url, Some("https://gitea.example.com".to_string())); + assert_eq!(config.gitea_token, Some("token123".to_string())); + assert_eq!(config.registry_owner, Some("owner".to_string())); + assert_eq!(config.github_token, Some("github_token123".to_string())); + } +} + +#[test] +fn test_sanitize_string() { + assert_eq!(sanitize_string("\"https://gitea.example.com\""), "https://gitea.example.com"); + assert_eq!(sanitize_string("\"token123\""), "token123"); + assert_eq!(sanitize_string("\"owner\""), "owner"); + assert_eq!(sanitize_string("\"github_token123\""), "github_token123"); + assert_eq!(sanitize_string("no_quotes"), "no_quotes"); + assert_eq!(sanitize_string("\"single_quote\""), "single_quote"); + assert_eq!(sanitize_string("\"escaped_quote\""), "escaped_quote"); +} #[test] fn test_normalize_repo_name() { - assert_eq!( - AppConfig::normalize_repo_name("raspberrypi/rpi-imager"), - "raspberrypi/rpi-imager" - ); - assert_eq!( - AppConfig::normalize_repo_name("https://github.com/raspberrypi/rpi-imager"), - "raspberrypi/rpi-imager" - ); - assert_eq!( - AppConfig::normalize_repo_name("https://github.com/raspberrypi/rpi-imager.git"), - "raspberrypi/rpi-imager" - ); - assert_eq!( - AppConfig::normalize_repo_name("Heroic-Games-Launcher/HeroicGamesLauncher/"), - "Heroic-Games-Launcher/HeroicGamesLauncher" - ); + let input = "https://github.com/owner/repo.git"; + let normalized = AppConfig::normalize_repo_name(input); + assert_eq!(normalized, "owner/repo"); } #[test] -fn test_repo_management() { +fn test_add_or_update_repo() { let mut config = AppConfig::default(); - config.add_or_update_repo(RepoConfig::new("owner/repo1", true)); - config.add_or_update_repo(RepoConfig::new("owner/repo2", false)); - - assert_eq!(config.repositories.len(), 2); - assert!(config.find_repo("owner/repo1").is_some()); - assert!(config.find_repo("https://github.com/owner/repo1").is_some()); - - assert!(config.remove_repo("owner/repo1")); + let repo = RepoConfig::new("owner/repo", true); + config.add_or_update_repo(repo.clone()); assert_eq!(config.repositories.len(), 1); - assert!(config.find_repo("owner/repo1").is_none()); + assert_eq!(config.repositories[0], repo); } #[test] -fn test_serialization_roundtrip() { - let mut config = AppConfig { - gitea_url: Some("https://gitea.example.com".to_string()), - gitea_token: Some("secret_token".to_string()), - registry_owner: Some("my-org".to_string()), - github_token: Some("gh_pat".to_string()), - repositories: Vec::new(), - }; - config.add_or_update_repo(RepoConfig::new("raspberrypi/rpi-imager", true)); - - let json_str = serde_json::to_string(&config).unwrap(); - let deserialized: AppConfig = serde_json::from_str(&json_str).unwrap(); - - assert_eq!(config, deserialized); +fn test_remove_repo() { + let mut config = AppConfig::default(); + let repo = RepoConfig::new("owner/repo", true); + config.add_or_update_repo(repo.clone()); + assert!(config.remove_repo("owner/repo")); + assert!(config.repositories.is_empty()); } + +#[test] +fn test_find_repo() { + let mut config = AppConfig::default(); + let repo = RepoConfig::new("owner/repo", true); + config.add_or_update_repo(repo.clone()); + assert_eq!(config.find_repo("owner/repo"), Some(&repo)); +} + +#[test] +fn test_update_last_synced_tag() { + let mut config = AppConfig::default(); + let repo = RepoConfig::new("owner/repo", true); + config.add_or_update_repo(repo.clone()); + config.update_last_synced_tag("owner/repo", "v1.0.0".to_string()); + assert_eq!(config.find_repo("owner/repo").unwrap().last_synced_tag, Some("v1.0.0".to_string())); +} \ No newline at end of file