wrale_acdm/application/
use_cases.rs1use anyhow::{Context, Result};
4use std::path::{Path, PathBuf};
5
6use crate::application::dto::{
7 AddDependencyDto, IncludePathsDto, InitConfigDto, UpdateDependenciesDto,
8};
9use crate::domain::repositories::{
10 ConfigurationRepository, FileSystemManager, GitOperations, RepositoryFetcher,
11};
12use crate::domain::services::DependencyManager;
13use crate::domain::{Dependency, RepositoryType};
14
15pub struct InitConfigUseCase<C: ConfigurationRepository> {
17 config_repo: C,
18}
19
20impl<C: ConfigurationRepository> InitConfigUseCase<C> {
21 pub fn new(config_repo: C) -> Self {
22 Self { config_repo }
23 }
24
25 pub fn execute(&self, dto: InitConfigDto) -> Result<()> {
26 self.config_repo
28 .init(&dto.config_path)
29 .context("Failed to initialize configuration")?;
30
31 if let Some(location) = dto.default_location {
33 let mut config = self
34 .config_repo
35 .load(&dto.config_path)
36 .context("Failed to load configuration")?;
37
38 config.default_location = Some(PathBuf::from(location));
39
40 self.config_repo
41 .save(&config, &dto.config_path)
42 .context("Failed to save configuration")?;
43 }
44
45 Ok(())
46 }
47}
48
49pub struct AddDependencyUseCase<C: ConfigurationRepository> {
51 config_repo: C,
52}
53
54impl<C: ConfigurationRepository> AddDependencyUseCase<C> {
55 pub fn new(config_repo: C) -> Self {
56 Self { config_repo }
57 }
58
59 pub fn execute(&self, config_path: &Path, dto: AddDependencyDto) -> Result<()> {
60 let mut config = self
62 .config_repo
63 .load(config_path)
64 .context("Failed to load configuration")?;
65
66 if config.dependencies.iter().any(|d| d.name == dto.name) {
68 return Err(anyhow::anyhow!(
69 "A dependency with the name '{}' already exists",
70 dto.name
71 ));
72 }
73
74 let repo_type = match dto.repository_type.to_lowercase().as_str() {
76 "git" => RepositoryType::Git,
77 _ => {
78 return Err(anyhow::anyhow!(
79 "Unsupported repository type: {}",
80 dto.repository_type
81 ))
82 }
83 };
84
85 let dependency = Dependency {
87 name: dto.name,
88 repository_url: dto.repository_url,
89 revision: dto.revision,
90 repository_type: repo_type,
91 sparse_paths: Vec::new(),
92 target_location: PathBuf::from(dto.target_location),
93 };
94
95 config.dependencies.push(dependency);
97
98 self.config_repo
100 .save(&config, config_path)
101 .context("Failed to save configuration")?;
102
103 Ok(())
104 }
105}
106
107pub struct IncludePathsUseCase<C: ConfigurationRepository> {
109 config_repo: C,
110}
111
112impl<C: ConfigurationRepository> IncludePathsUseCase<C> {
113 pub fn new(config_repo: C) -> Self {
114 Self { config_repo }
115 }
116
117 pub fn execute(&self, config_path: &Path, dto: IncludePathsDto) -> Result<()> {
118 let mut config = self
120 .config_repo
121 .load(config_path)
122 .context("Failed to load configuration")?;
123
124 let dep_idx = config
126 .dependencies
127 .iter()
128 .position(|d| d.name == dto.dependency_name)
129 .ok_or_else(|| anyhow::anyhow!("Dependency '{}' not found", dto.dependency_name))?;
130
131 for path in dto.paths {
133 if !config.dependencies[dep_idx].sparse_paths.contains(&path) {
134 config.dependencies[dep_idx].sparse_paths.push(path);
135 }
136 }
137
138 self.config_repo
140 .save(&config, config_path)
141 .context("Failed to save configuration")?;
142
143 Ok(())
144 }
145}
146
147pub struct UpdateDependenciesUseCase<C, R, F, G>
149where
150 C: ConfigurationRepository,
151 R: RepositoryFetcher,
152 F: FileSystemManager,
153 G: GitOperations,
154{
155 config_repo: C,
156 dependency_manager: DependencyManager<R, F, G>,
157}
158
159impl<C, R, F, G> UpdateDependenciesUseCase<C, R, F, G>
160where
161 C: ConfigurationRepository,
162 R: RepositoryFetcher,
163 F: FileSystemManager,
164 G: GitOperations,
165{
166 pub fn new(
167 config_repo: C,
168 repository_fetcher: R,
169 file_system_manager: F,
170 git_operations: G,
171 ) -> Self {
172 Self {
173 config_repo,
174 dependency_manager: DependencyManager::new(
175 repository_fetcher,
176 file_system_manager,
177 git_operations,
178 ),
179 }
180 }
181
182 pub fn execute(&self, dto: UpdateDependenciesDto) -> Result<()> {
183 let config = self
185 .config_repo
186 .load(&dto.config_path)
187 .context("Failed to load configuration")?;
188
189 let dependencies_to_update = if let Some(dep_names) = dto.dependencies {
191 config
192 .dependencies
193 .iter()
194 .filter(|d| dep_names.contains(&d.name))
195 .cloned()
196 .collect::<Vec<_>>()
197 } else {
198 config.dependencies.clone()
199 };
200
201 if dependencies_to_update.is_empty() {
202 return Err(anyhow::anyhow!("No dependencies found to update"));
203 }
204
205 let repo_root = dto
207 .config_path
208 .parent()
209 .ok_or_else(|| anyhow::anyhow!("Failed to determine repository root"))?;
210
211 self.dependency_manager
213 .update_all(&dependencies_to_update, repo_root, dto.force)
214 .map_err(|e| anyhow::anyhow!("Failed to update dependencies: {}", e))?;
215
216 Ok(())
217 }
218}