use crate::git_ops::ensure_remote;
use anyhow::Result;
use std::path::PathBuf;
use std::time::Duration;
use tokio::process::Command;
use tokio::time::sleep;
use tracing::{error, info, warn};
pub struct GitSyncWorker {
repo_path: PathBuf,
}
impl GitSyncWorker {
pub fn new(repo_path: PathBuf) -> Self {
Self { repo_path }
}
pub async fn run(&self) {
info!("GitSyncWorker started. Will sync remotes periodically.");
loop {
if let Err(e) = self.sync_all_remotes().await {
error!("GitSyncWorker failed during sync cycle: {}", e);
}
sleep(Duration::from_secs(3600)).await;
}
}
async fn sync_all_remotes(&self) -> Result<()> {
info!("GitSyncWorker: Starting sync cycle.");
let output = Command::new("git")
.current_dir(&self.repo_path)
.args(["remote"])
.output()
.await?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
error!("GitSyncWorker: Failed to list git remotes: {}", stderr);
return Err(anyhow::anyhow!("Failed to list remotes"));
}
let remotes_str = String::from_utf8_lossy(&output.stdout);
let remotes: Vec<&str> = remotes_str
.lines()
.map(|l| l.trim())
.filter(|l| !l.is_empty() && !l.starts_with("fetcher-"))
.collect();
info!("GitSyncWorker: Found {} remotes to check.", remotes.len());
for remote in remotes {
let url_output = Command::new("git")
.current_dir(&self.repo_path)
.args(["remote", "get-url", remote])
.output()
.await?;
if !url_output.status.success() {
warn!(
"GitSyncWorker: Failed to get URL for remote {}. Skipping.",
remote
);
continue;
}
let url = String::from_utf8_lossy(&url_output.stdout)
.trim()
.to_string();
if let Err(e) = ensure_remote(&self.repo_path, remote, &url, false).await {
error!("GitSyncWorker: Failed to sync remote {}: {}", remote, e);
}
}
info!("GitSyncWorker: Sync cycle complete.");
Ok(())
}
}