mutiny-diff 0.1.22

TUI git diff viewer with worktree management
use std::path::PathBuf;

use tokio::sync::mpsc;

use crate::git::{DiffEngine, RepoCache};

use super::channel::{DiffRequest, DiffResult};

pub struct DiffWorker {
    request_tx: mpsc::UnboundedSender<DiffRequest>,
    result_rx: mpsc::UnboundedReceiver<DiffResult>,
}

impl DiffWorker {
    pub fn new(repo_path: PathBuf) -> Self {
        let (request_tx, mut request_rx) = mpsc::unbounded_channel::<DiffRequest>();
        let (result_tx, result_rx) = mpsc::unbounded_channel::<DiffResult>();

        tokio::spawn(async move {
            while let Some(request) = request_rx.recv().await {
                let path = repo_path.clone();
                let tx = result_tx.clone();

                tokio::task::spawn_blocking(move || {
                    let result = match RepoCache::open(&path) {
                        Ok(repo) => {
                            match DiffEngine::compute_diff(
                                repo.repo(),
                                &request.target,
                                &request.options,
                            ) {
                                Ok(deltas) => DiffResult {
                                    generation: request.generation,
                                    deltas: Ok(deltas),
                                },
                                Err(e) => DiffResult {
                                    generation: request.generation,
                                    deltas: Err(e.to_string()),
                                },
                            }
                        }
                        Err(e) => DiffResult {
                            generation: request.generation,
                            deltas: Err(e.to_string()),
                        },
                    };
                    let _ = tx.send(result);
                });
            }
        });

        Self {
            request_tx,
            result_rx,
        }
    }

    pub fn request(&self, req: DiffRequest) {
        let _ = self.request_tx.send(req);
    }

    pub fn try_recv(&mut self) -> Option<DiffResult> {
        self.result_rx.try_recv().ok()
    }
}