-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathbuilder.rs
More file actions
138 lines (126 loc) · 4.01 KB
/
Copy pathbuilder.rs
File metadata and controls
138 lines (126 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Builder for constructing a [`Deployer`] with sensible defaults.
//!
//! The builder pattern hides dependency wiring (repository, clock, etc.)
//! so SDK consumers only need to provide the workspace path.
//!
//! # Example
//!
//! ```rust,no_run
//! use torrust_tracker_deployer_lib::presentation::sdk::Deployer;
//!
//! let deployer = Deployer::builder()
//! .working_dir("/home/user/deployer-workspace")
//! .build()
//! .unwrap();
//! ```
use std::path::{Path, PathBuf};
use std::sync::Arc;
use thiserror::Error;
use super::deployer::Deployer;
use crate::application::traits::{CommandProgressListener, NullProgressListener};
use crate::bootstrap::sdk::{default_clock, default_repository_provider, DEFAULT_SDK_LOCK_TIMEOUT};
/// Builder for constructing a [`Deployer`] instance.
///
/// # Required
///
/// - [`working_dir`](DeployerBuilder::working_dir) — the workspace root
/// where `data/` and `build/` directories live
///
/// # Example
///
/// ```rust,no_run
/// use torrust_tracker_deployer_lib::presentation::sdk::Deployer;
///
/// let deployer = Deployer::builder()
/// .working_dir("/path/to/workspace")
/// .build()
/// .expect("Failed to build deployer");
/// ```
pub struct DeployerBuilder {
working_dir: Option<PathBuf>,
progress_listener: Option<Arc<dyn CommandProgressListener + Send + Sync>>,
}
impl DeployerBuilder {
/// Create a new builder with no configuration.
#[must_use]
pub fn new() -> Self {
Self {
working_dir: None,
progress_listener: None,
}
}
/// Set the workspace root directory.
///
/// This is the directory containing `data/` and `build/` subdirectories.
/// It is the only required setting.
#[must_use]
pub fn working_dir(mut self, path: impl Into<PathBuf>) -> Self {
self.working_dir = Some(path.into());
self
}
/// Set a default progress listener for all operations.
///
/// The listener receives step-by-step progress events from long-running
/// operations (provision, configure, release). If not set, a
/// [`NullProgressListener`] is used (silent).
///
/// # Example
///
/// ```rust,no_run
/// use std::sync::Arc;
/// use torrust_tracker_deployer_lib::presentation::sdk::{Deployer, NullProgressListener};
///
/// let deployer = Deployer::builder()
/// .working_dir("/path/to/workspace")
/// .progress_listener(Arc::new(NullProgressListener))
/// .build()
/// .unwrap();
/// ```
#[must_use]
pub fn progress_listener(
mut self,
listener: Arc<dyn CommandProgressListener + Send + Sync>,
) -> Self {
self.progress_listener = Some(listener);
self
}
/// Build the [`Deployer`] instance.
///
/// # Errors
///
/// Returns [`DeployerBuildError::MissingWorkingDir`] if `working_dir`
/// was not set.
pub fn build(self) -> Result<Deployer, DeployerBuildError> {
let working_dir = self
.working_dir
.ok_or(DeployerBuildError::MissingWorkingDir)?;
let file_repository_factory = default_repository_provider(DEFAULT_SDK_LOCK_TIMEOUT);
let data_dir = working_dir.join("data");
let data_directory: Arc<Path> = Arc::from(data_dir.as_path());
let repository = file_repository_factory.create(data_dir.clone());
let clock = default_clock();
let listener = self
.progress_listener
.unwrap_or_else(|| Arc::new(NullProgressListener));
Ok(Deployer::new(
working_dir,
repository,
file_repository_factory,
clock,
data_directory,
listener,
))
}
}
impl Default for DeployerBuilder {
fn default() -> Self {
Self::new()
}
}
/// Errors that can occur when building a [`Deployer`].
#[derive(Debug, Error)]
pub enum DeployerBuildError {
/// The required `working_dir` was not provided.
#[error("working_dir is required but was not set")]
MissingWorkingDir,
}