heroforge_core/sync/
builder.rs1use crate::error::{FossilError, Result};
4use crate::repo::Repository;
5
6#[derive(Debug, Clone, PartialEq)]
8pub enum SyncProtocol {
9 Quic,
11}
12
13pub struct SyncBuilder<'a> {
15 repo: &'a Repository,
16 url: Option<String>,
17 username: Option<String>,
18 password: Option<String>,
19}
20
21impl<'a> SyncBuilder<'a> {
22 pub(crate) fn new(repo: &'a Repository) -> Self {
23 Self {
24 repo,
25 url: None,
26 username: None,
27 password: None,
28 }
29 }
30
31 pub fn to(mut self, url: &str) -> Self {
33 self.url = Some(url.to_string());
34 self
35 }
36
37 pub fn from(mut self, url: &str) -> Self {
39 self.url = Some(url.to_string());
40 self
41 }
42
43 pub fn with(mut self, url: &str) -> Self {
45 self.url = Some(url.to_string());
46 self
47 }
48
49 pub fn url(self, url: &str) -> Self {
51 self.with(url)
52 }
53
54 pub fn auth(mut self, username: &str, password: &str) -> Self {
56 self.username = Some(username.to_string());
57 self.password = Some(password.to_string());
58 self
59 }
60
61 pub fn username(mut self, username: &str) -> Self {
63 self.username = Some(username.to_string());
64 self
65 }
66
67 pub fn password(mut self, password: &str) -> Self {
69 self.password = Some(password.to_string());
70 self
71 }
72
73 fn normalize_url(url: &str) -> String {
75 if url.starts_with("quic://") {
76 url.replacen("quic://", "", 1)
77 } else {
78 url.to_string()
79 }
80 }
81
82 pub fn push(self) -> Result<SyncResult> {
84 self.execute()
85 }
86
87 pub fn pull(self) -> Result<SyncResult> {
89 self.execute()
90 }
91
92 pub fn execute(self) -> Result<SyncResult> {
94 let url = self
95 .url
96 .ok_or_else(|| FossilError::InvalidArtifact("sync URL is required".to_string()))?;
97 let normalized_url = Self::normalize_url(&url);
98
99 #[cfg(feature = "sync-quic")]
100 {
101 use crate::sync::QuicClient;
102 use std::path::PathBuf;
103
104 let rt = tokio::runtime::Runtime::new()
105 .map_err(|e| FossilError::SyncError(e.to_string()))?;
106 let stats = rt.block_on(async {
107 QuicClient::sync(self.repo, &PathBuf::new(), &normalized_url).await
108 })?;
109 Ok(SyncResult {
110 artifacts_sent: stats.artifacts_sent,
111 artifacts_received: stats.artifacts_received,
112 protocol: SyncProtocol::Quic,
113 })
114 }
115 #[cfg(not(feature = "sync-quic"))]
116 {
117 let _ = (normalized_url, self.repo);
118 Err(FossilError::InvalidArtifact(
119 "QUIC sync requires 'sync-quic' feature".to_string(),
120 ))
121 }
122 }
123}
124
125#[derive(Debug)]
127pub struct SyncResult {
128 pub artifacts_sent: usize,
130 pub artifacts_received: usize,
132 pub protocol: SyncProtocol,
134}