1use std::future::Future;
7
8use anyhow::Result;
9
10#[cfg(feature = "config")]
11use crate::config::RemotePinConfig;
12
13#[derive(Debug, Default, Clone)]
14pub struct PinReplaceOutcome {
15 pub previous_remove_error: Option<String>,
16}
17
18pub async fn pin_add_then_rm<FAdd, FRm, FutAdd, FutRm>(
19 old_cid: Option<&str>,
20 new_cid: &str,
21 pin_name: &str,
22 add_named: FAdd,
23 remove_pin: FRm,
24) -> Result<PinReplaceOutcome>
25where
26 FAdd: Fn(String, String) -> FutAdd,
27 FRm: Fn(String) -> FutRm,
28 FutAdd: Future<Output = Result<()>>,
29 FutRm: Future<Output = Result<()>>,
30{
31 let Some(previous) = old_cid else {
32 add_named(new_cid.to_string(), pin_name.to_string()).await?;
33 return Ok(PinReplaceOutcome::default());
34 };
35
36 if previous == new_cid {
37 return Ok(PinReplaceOutcome::default());
38 }
39
40 add_named(new_cid.to_string(), pin_name.to_string()).await?;
41
42 let previous_remove_error = remove_pin(previous.to_string())
43 .await
44 .err()
45 .map(|err| err.to_string());
46
47 Ok(PinReplaceOutcome {
48 previous_remove_error,
49 })
50}
51
52#[cfg(feature = "config")]
53pub async fn remote_pin_replace(
54 kubo_url: &str,
55 remote: &RemotePinConfig,
56 old_cid: Option<&str>,
57 new_cid: &str,
58) -> Result<PinReplaceOutcome> {
59 let add_url = kubo_url.to_string();
60 let add_service = remote.service.clone();
61 let rm_url = kubo_url.to_string();
62 let rm_service = remote.service.clone();
63 pin_add_then_rm(
64 old_cid,
65 new_cid,
66 &remote.name,
67 move |cid, name| {
68 let add_url = add_url.clone();
69 let add_service = add_service.clone();
70 async move {
71 crate::kubo::kubo::remote_pin_add_named(&add_url, &add_service, &cid, &name).await
72 }
73 },
74 move |cid| {
75 let rm_url = rm_url.clone();
76 let rm_service = rm_service.clone();
77 async move { crate::kubo::kubo::remote_pin_rm(&rm_url, &rm_service, &cid).await }
78 },
79 )
80 .await
81}