diff --git a/src-tauri/src/commands/credential.rs b/src-tauri/src/commands/credential.rs index 2334b25..0213eae 100644 --- a/src-tauri/src/commands/credential.rs +++ b/src-tauri/src/commands/credential.rs @@ -12,8 +12,8 @@ pub fn set_tuleap_credentials( username: String, password: String, ) -> Result { - let password_encrypted = crypto::encrypt(&state.encryption_key, &password) - .map_err(AppError::from)?; + let password_encrypted = + crypto::encrypt(&state.encryption_key, &password).map_err(AppError::from)?; let db = state .db diff --git a/src-tauri/src/commands/notification.rs b/src-tauri/src/commands/notification.rs index 12be37a..40a33d3 100644 --- a/src-tauri/src/commands/notification.rs +++ b/src-tauri/src/commands/notification.rs @@ -15,10 +15,7 @@ pub fn list_notifications( } #[tauri::command] -pub fn mark_notification_read( - state: State<'_, AppState>, - id: String, -) -> Result<(), AppError> { +pub fn mark_notification_read(state: State<'_, AppState>, id: String) -> Result<(), AppError> { let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?; Notification::mark_read(&conn, &id)?; Ok(()) diff --git a/src-tauri/src/commands/orchestrator.rs b/src-tauri/src/commands/orchestrator.rs index 8894472..da14504 100644 --- a/src-tauri/src/commands/orchestrator.rs +++ b/src-tauri/src/commands/orchestrator.rs @@ -23,10 +23,7 @@ pub fn get_ticket_result( } #[tauri::command] -pub fn retry_ticket( - state: State<'_, AppState>, - ticket_id: String, -) -> Result<(), AppError> { +pub fn retry_ticket(state: State<'_, AppState>, ticket_id: String) -> Result<(), AppError> { let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?; let ticket = ProcessedTicket::get_by_id(&conn, &ticket_id)?; @@ -47,7 +44,8 @@ pub fn retry_ticket( if let Some(wt) = Worktree::get_by_ticket_id(&conn, &ticket_id)? { if wt.status == "Active" { let project_id = { - let tracker = crate::models::tracker::WatchedTracker::get_by_id(&conn, &ticket.tracker_id)?; + let tracker = + crate::models::tracker::WatchedTracker::get_by_id(&conn, &ticket.tracker_id)?; tracker.project_id }; let project = crate::models::project::Project::get_by_id(&conn, &project_id)?; @@ -64,10 +62,7 @@ pub fn retry_ticket( } #[tauri::command] -pub fn cancel_ticket( - state: State<'_, AppState>, - ticket_id: String, -) -> Result<(), AppError> { +pub fn cancel_ticket(state: State<'_, AppState>, ticket_id: String) -> Result<(), AppError> { let conn = state.db.lock().map_err(|e| AppError::from(e.to_string()))?; let ticket = ProcessedTicket::get_by_id(&conn, &ticket_id)?; diff --git a/src-tauri/src/error.rs b/src-tauri/src/error.rs index 914ed59..a605507 100644 --- a/src-tauri/src/error.rs +++ b/src-tauri/src/error.rs @@ -29,7 +29,9 @@ impl From for AppError { impl From for AppError { fn from(e: reqwest::Error) -> Self { - AppError { message: e.to_string() } + AppError { + message: e.to_string(), + } } } diff --git a/src-tauri/src/models/credential.rs b/src-tauri/src/models/credential.rs index 0849947..880bffa 100644 --- a/src-tauri/src/models/credential.rs +++ b/src-tauri/src/models/credential.rs @@ -105,13 +105,9 @@ mod tests { TuleapCredentials::upsert(&conn, "https://old.example.com", "old_user", "old_enc") .expect("first upsert should succeed"); - let second = TuleapCredentials::upsert( - &conn, - "https://new.example.com", - "new_user", - "new_enc", - ) - .expect("second upsert should succeed"); + let second = + TuleapCredentials::upsert(&conn, "https://new.example.com", "new_user", "new_enc") + .expect("second upsert should succeed"); // Only one record should exist let creds = TuleapCredentials::get(&conn) @@ -133,13 +129,9 @@ mod tests { #[test] fn test_get_returns_credentials() { let conn = setup(); - let created = TuleapCredentials::upsert( - &conn, - "https://tuleap.example.com", - "bob", - "enc_pass", - ) - .expect("upsert should succeed"); + let created = + TuleapCredentials::upsert(&conn, "https://tuleap.example.com", "bob", "enc_pass") + .expect("upsert should succeed"); let fetched = TuleapCredentials::get(&conn) .expect("get should succeed") diff --git a/src-tauri/src/models/notification.rs b/src-tauri/src/models/notification.rs index 0d1d4be..61d6c96 100644 --- a/src-tauri/src/models/notification.rs +++ b/src-tauri/src/models/notification.rs @@ -77,7 +77,10 @@ impl Notification { } pub fn mark_read(conn: &Connection, id: &str) -> Result<()> { - conn.execute("UPDATE notifications SET read = 1 WHERE id = ?1", params![id])?; + conn.execute( + "UPDATE notifications SET read = 1 WHERE id = ?1", + params![id], + )?; Ok(()) } diff --git a/src-tauri/src/models/project.rs b/src-tauri/src/models/project.rs index e91dba9..20b3160 100644 --- a/src-tauri/src/models/project.rs +++ b/src-tauri/src/models/project.rs @@ -104,8 +104,14 @@ mod tests { #[test] fn test_insert_project_local_path() { let conn = setup(); - let project = Project::insert(&conn, "My Project", "/home/user/code/myproject", None, "main") - .expect("insert should succeed"); + let project = Project::insert( + &conn, + "My Project", + "/home/user/code/myproject", + None, + "main", + ) + .expect("insert should succeed"); assert_eq!(project.name, "My Project"); assert_eq!(project.path, "/home/user/code/myproject"); @@ -127,7 +133,10 @@ mod tests { ) .expect("insert should succeed"); - assert_eq!(project.cloned_from.as_deref(), Some("https://github.com/org/repo.git")); + assert_eq!( + project.cloned_from.as_deref(), + Some("https://github.com/org/repo.git") + ); assert_eq!(project.base_branch, "stable"); } diff --git a/src-tauri/src/services/filter_engine.rs b/src-tauri/src/services/filter_engine.rs index 958dbf6..075a955 100644 --- a/src-tauri/src/services/filter_engine.rs +++ b/src-tauri/src/services/filter_engine.rs @@ -16,7 +16,9 @@ pub fn apply_filters( } fn matches_all_groups(artifact: &serde_json::Value, groups: &[FilterGroup]) -> bool { - groups.iter().all(|g| matches_any_condition(artifact, &g.conditions)) + groups + .iter() + .all(|g| matches_any_condition(artifact, &g.conditions)) } fn matches_any_condition(artifact: &serde_json::Value, conditions: &[Filter]) -> bool { @@ -30,12 +32,10 @@ fn matches_condition(artifact: &serde_json::Value, condition: &Filter) -> bool { let field_values = extract_artifact_field_values(artifact, &condition.field); match condition.operator.as_str() { "Equals" => { - condition.value.len() == 1 - && field_values.iter().any(|v| v == &condition.value[0]) + condition.value.len() == 1 && field_values.iter().any(|v| v == &condition.value[0]) } "NotEquals" => { - condition.value.len() == 1 - && !field_values.iter().any(|v| v == &condition.value[0]) + condition.value.len() == 1 && !field_values.iter().any(|v| v == &condition.value[0]) } "In" => field_values.iter().any(|v| condition.value.contains(v)), "NotIn" => !field_values.iter().any(|v| condition.value.contains(v)), diff --git a/src-tauri/src/services/poller.rs b/src-tauri/src/services/poller.rs index 16480d4..341273b 100644 --- a/src-tauri/src/services/poller.rs +++ b/src-tauri/src/services/poller.rs @@ -1,8 +1,8 @@ use crate::models::credential::TuleapCredentials; use crate::models::ticket::ProcessedTicket; use crate::models::tracker::WatchedTracker; -use crate::services::{crypto, filter_engine, notifier}; use crate::services::tuleap_client::TuleapClient; +use crate::services::{crypto, filter_engine, notifier}; use rusqlite::Connection; use std::sync::{Arc, Mutex}; use tauri::{AppHandle, Emitter}; @@ -87,7 +87,10 @@ fn should_poll(tracker: &WatchedTracker) -> bool { let last = match chrono::DateTime::parse_from_rfc3339(last_polled_at) { Ok(dt) => dt, Err(e) => { - eprintln!("poller: failed to parse last_polled_at '{}': {}", last_polled_at, e); + eprintln!( + "poller: failed to parse last_polled_at '{}': {}", + last_polled_at, e + ); return true; // Treat as never polled on parse error } }; @@ -116,7 +119,10 @@ async fn poll_single_tracker( let artifacts = match client.get_artifacts(tracker.tracker_id).await { Ok(a) => a, Err(e) => { - eprintln!("poller: failed to fetch artifacts for tracker {}: {}", tracker.id, e); + eprintln!( + "poller: failed to fetch artifacts for tracker {}: {}", + tracker.id, e + ); let _ = app_handle.emit( "polling-error", serde_json::json!({ @@ -147,10 +153,7 @@ async fn poll_single_tracker( let mut inserted = Vec::new(); for artifact in &filtered { - let artifact_id = artifact - .get("id") - .and_then(|v| v.as_i64()) - .unwrap_or(0) as i32; + let artifact_id = artifact.get("id").and_then(|v| v.as_i64()).unwrap_or(0) as i32; let artifact_title = artifact .get("title") @@ -158,8 +161,8 @@ async fn poll_single_tracker( .unwrap_or("") .to_string(); - let artifact_data = serde_json::to_string(artifact) - .unwrap_or_else(|_| "{}".to_string()); + let artifact_data = + serde_json::to_string(artifact).unwrap_or_else(|_| "{}".to_string()); match ProcessedTicket::insert_if_new( &conn, @@ -171,14 +174,20 @@ async fn poll_single_tracker( Ok(Some(ticket)) => inserted.push(ticket), Ok(None) => {} Err(e) => { - eprintln!("poller: failed to insert ticket (artifact {}): {}", artifact_id, e); + eprintln!( + "poller: failed to insert ticket (artifact {}): {}", + artifact_id, e + ); } } } // 4. Update last_polled_at if let Err(e) = WatchedTracker::update_last_polled(&conn, &tracker.id) { - eprintln!("poller: failed to update last_polled_at for tracker {}: {}", tracker.id, e); + eprintln!( + "poller: failed to update last_polled_at for tracker {}: {}", + tracker.id, e + ); } inserted diff --git a/src-tauri/src/services/tuleap_client.rs b/src-tauri/src/services/tuleap_client.rs index c23d81f..5f80d2b 100644 --- a/src-tauri/src/services/tuleap_client.rs +++ b/src-tauri/src/services/tuleap_client.rs @@ -39,7 +39,10 @@ impl TuleapClient { for attempt in 1..=MAX_ATTEMPTS { let started_at = Instant::now(); - eprintln!("[tuleap] -> GET {} (attempt {}/{})", url, attempt, MAX_ATTEMPTS); + eprintln!( + "[tuleap] -> GET {} (attempt {}/{})", + url, attempt, MAX_ATTEMPTS + ); let response = self .http @@ -59,7 +62,8 @@ impl TuleapClient { ); // Retry transient HTTP failures. - if (status == reqwest::StatusCode::TOO_MANY_REQUESTS || status.is_server_error()) + if (status == reqwest::StatusCode::TOO_MANY_REQUESTS + || status.is_server_error()) && attempt < MAX_ATTEMPTS { let delay_ms = BASE_DELAY_MS * 2u64.pow(attempt - 1); @@ -156,10 +160,7 @@ impl TuleapClient { .await .map_err(|e| format!("failed to parse response: {}", e))?; - let artifacts = body - .as_array() - .cloned() - .unwrap_or_default(); + let artifacts = body.as_array().cloned().unwrap_or_default(); let fetched = artifacts.len(); all_artifacts.extend(artifacts); @@ -213,11 +214,7 @@ fn extract_field_values(field: &serde_json::Value) -> Vec { .get("values") .and_then(|v| v.as_array()) .filter(|arr| !arr.is_empty()) - .or_else(|| { - field - .get("bind_value_objects") - .and_then(|v| v.as_array()) - }); + .or_else(|| field.get("bind_value_objects").and_then(|v| v.as_array())); let arr = match candidates { Some(a) => a, @@ -269,10 +266,7 @@ pub fn extract_artifact_field_values( None => return vec![], }; - let field_type = entry - .get("type") - .and_then(|t| t.as_str()) - .unwrap_or(""); + let field_type = entry.get("type").and_then(|t| t.as_str()).unwrap_or(""); match field_type { "sb" | "rb" => { @@ -286,7 +280,9 @@ pub fn extract_artifact_field_values( if let Some(id) = v.get("id") { match id { serde_json::Value::String(s) => push_unique(&mut out, s.clone()), - serde_json::Value::Number(n) => push_unique(&mut out, n.to_string()), + serde_json::Value::Number(n) => { + push_unique(&mut out, n.to_string()) + } _ => {} } } @@ -309,7 +305,9 @@ pub fn extract_artifact_field_values( if let Some(id) = v.get("id") { match id { serde_json::Value::String(s) => push_unique(&mut out, s.clone()), - serde_json::Value::Number(n) => push_unique(&mut out, n.to_string()), + serde_json::Value::Number(n) => { + push_unique(&mut out, n.to_string()) + } _ => {} } } diff --git a/src-tauri/src/services/worktree_manager.rs b/src-tauri/src/services/worktree_manager.rs index d5cbdaa..9de3ac0 100644 --- a/src-tauri/src/services/worktree_manager.rs +++ b/src-tauri/src/services/worktree_manager.rs @@ -33,13 +33,24 @@ pub fn create_worktree( run_git( project_path, - &["worktree", "add", wt_path_str, "-b", &branch_name, base_branch], + &[ + "worktree", + "add", + wt_path_str, + "-b", + &branch_name, + base_branch, + ], )?; Ok((wt_path_str.to_string(), branch_name)) } -pub fn get_diff(project_path: &str, base_branch: &str, branch_name: &str) -> Result { +pub fn get_diff( + project_path: &str, + base_branch: &str, + branch_name: &str, +) -> Result { let range = format!("{}...{}", base_branch, branch_name); run_git(project_path, &["diff", &range]) } @@ -96,7 +107,10 @@ pub fn delete_worktree( worktree_path: &str, branch_name: &str, ) -> Result<(), String> { - run_git(project_path, &["worktree", "remove", worktree_path, "--force"])?; + run_git( + project_path, + &["worktree", "remove", worktree_path, "--force"], + )?; let _ = run_git(project_path, &["branch", "-D", branch_name]); Ok(()) } @@ -119,7 +133,11 @@ mod tests { let dir = tempfile::tempdir().expect("create temp dir"); let path = dir.path().to_str().unwrap(); - Command::new("git").args(["init"]).current_dir(path).output().unwrap(); + Command::new("git") + .args(["init"]) + .current_dir(path) + .output() + .unwrap(); Command::new("git") .args(["config", "user.email", "test@test.com"]) .current_dir(path) @@ -132,7 +150,11 @@ mod tests { .unwrap(); std::fs::write(dir.path().join("README.md"), "# Test").unwrap(); - Command::new("git").args(["add", "."]).current_dir(path).output().unwrap(); + Command::new("git") + .args(["add", "."]) + .current_dir(path) + .output() + .unwrap(); Command::new("git") .args(["commit", "-m", "init"]) .current_dir(path) @@ -184,7 +206,11 @@ mod tests { let (wt_path, branch) = create_worktree(path, &base_branch, 2).unwrap(); std::fs::write(Path::new(&wt_path).join("fix.txt"), "fixed").unwrap(); - Command::new("git").args(["add", "."]).current_dir(&wt_path).output().unwrap(); + Command::new("git") + .args(["add", "."]) + .current_dir(&wt_path) + .output() + .unwrap(); Command::new("git") .args(["commit", "-m", "fix"]) .current_dir(&wt_path) @@ -205,7 +231,11 @@ mod tests { let (wt_path, branch) = create_worktree(path, &base_branch, 3).unwrap(); std::fs::write(Path::new(&wt_path).join("a.txt"), "a").unwrap(); - Command::new("git").args(["add", "."]).current_dir(&wt_path).output().unwrap(); + Command::new("git") + .args(["add", "."]) + .current_dir(&wt_path) + .output() + .unwrap(); Command::new("git") .args(["commit", "-m", "first"]) .current_dir(&wt_path) @@ -213,7 +243,11 @@ mod tests { .unwrap(); std::fs::write(Path::new(&wt_path).join("b.txt"), "b").unwrap(); - Command::new("git").args(["add", "."]).current_dir(&wt_path).output().unwrap(); + Command::new("git") + .args(["add", "."]) + .current_dir(&wt_path) + .output() + .unwrap(); Command::new("git") .args(["commit", "-m", "second"]) .current_dir(&wt_path) @@ -266,7 +300,11 @@ mod tests { let (wt_path, branch) = create_worktree(path, &base_branch, 7).unwrap(); std::fs::write(Path::new(&wt_path).join("fix.txt"), "the fix").unwrap(); - Command::new("git").args(["add", "."]).current_dir(&wt_path).output().unwrap(); + Command::new("git") + .args(["add", "."]) + .current_dir(&wt_path) + .output() + .unwrap(); Command::new("git") .args(["commit", "-m", "apply fix"]) .current_dir(&wt_path)