compose_rs/
builder.rs

1use std::{
2    env::current_dir,
3    path::{Path, PathBuf},
4};
5
6use relative_path::RelativePath;
7
8use crate::{Compose, ComposeBuilderError};
9
10#[derive(Default)]
11pub struct ComposeBuilder {
12    path: Option<String>,
13}
14
15impl ComposeBuilder {
16    /// Create a new ComposeBuilder.
17    pub fn new() -> Self {
18        Self::default()
19    }
20
21    /// Set the path to the docker-compose file.
22    /// The path can be either absolute or relative.
23    pub fn path(mut self, path: impl ToString) -> Self {
24        self.path = Some(path.to_string());
25        self
26    }
27
28    /// Build the Compose object.
29    ///
30    /// # Errors
31    ///
32    /// Returns a [ComposeBuilderError] if the path is missing or the file is not found.
33    pub fn build(self) -> Result<Compose, ComposeBuilderError> {
34        let path = match self.path {
35            Some(path) => path,
36            None => return Err(ComposeBuilderError::MissingField("path".to_string())),
37        };
38
39        let path = match Path::new(&path).is_absolute() {
40            true => PathBuf::from(path),
41            false => {
42                let base = current_dir()?;
43                RelativePath::new(&path).to_logical_path(base)
44            }
45        };
46
47        if path.exists() {
48            Ok(Compose {
49                path: path.to_string_lossy().to_string(),
50            })
51        } else {
52            Err(ComposeBuilderError::FileNotFound(
53                path.to_string_lossy().to_string(),
54            ))
55        }
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn test_compose_builder() {
65        let compose = Compose::builder().path("non-existent.yml").build();
66
67        matches!(compose, Err(ComposeBuilderError::FileNotFound(_)));
68    }
69}