+ use std::collections::BTreeMap;
+ use std::future::Future;
+ use std::path::{Path, PathBuf};
+ use std::pin::Pin;
+ use std::sync::Mutex;
+ use std::task::{Context, Poll, Waker};
+
+ use futures_util::future::BoxFuture;
+ use futures_util::FutureExt;
+ use pijul_interaction::ProgressBar;
+ use tokio::sync::mpsc;
+
+ use crate::{RemoteRepo, CS};
+
+ pub struct FetchChangesState<'a> {
+ shared: Mutex<Shared<'a>>,
+ }
+
+ struct Shared<'a> {
+ task: BoxFuture<'a, Result<bool, anyhow::Error>>,
+ changes: BTreeMap<CS, ChangeState>,
+ }
+
+ struct ChangeState {
+ wakers: Vec<Waker>,
+ }
+
+ impl<'a> FetchChangesState<'a> {
+ pub fn new<T>(
+ remote: &'a mut RemoteRepo,
+ progress_bar: ProgressBar,
+ dest_dir: T,
+ full: bool,
+ ) -> Self
+ where
+ T: AsRef<Path> + Send + 'a,
+ {
+ let (in_tx, mut in_rx) = mpsc::unbounded_channel();
+ let (mut out_tx, out_rx) = mpsc::channel(100);
+
+ let task = async move {
+ remote
+ .download_changes(
+ progress_bar,
+ &mut in_rx,
+ &mut out_tx,
+ dest_dir.as_ref(),
+ full,
+ )
+ .await
+ }
+ .boxed();
+
+ FetchChangesState {
+ shared: Mutex::new(Shared {
+ task,
+ changes: Default::default(),
+ }),
+ }
+ }
+
+ pub fn fetch(&mut self, cs: CS) -> FetchJob {
+ todo!()
+ }
+ }
+
+ pub struct FetchJob<'a> {
+ shared: &'a Mutex<Shared<'a>>,
+ }
+
+ impl<'a> Future for FetchJob<'a> {
+ type Output = bool;
+
+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
+ let mut shared = self.shared.lock().unwrap();
+
+ shared.task.poll_unpin(cx);
+
+ todo!()
+ }
+ }