mongo_embedded/
process.rs

1use anyhow::{anyhow, Result};
2use std::process::{Child, Command};
3use std::path::{Path, PathBuf};
4use crate::downloader::Os;
5
6pub struct MongoProcess {
7    child: Child,
8    pub connection_string: String,
9}
10
11impl MongoProcess {
12    pub fn start(
13        extracted_path: &Path,
14        port: u16,
15        db_path: &Path,
16        os: &Os,
17        bind_ip: &str,
18        auth: bool,
19        connection_string: String,
20    ) -> Result<Self> {
21        let binary_name = match os {
22            Os::Windows => "mongod.exe",
23            _ => "mongod",
24        };
25
26        let binary_path = find_binary(extracted_path, binary_name)
27            .ok_or_else(|| anyhow!("Could not find {} in extracted directory", binary_name))?;
28
29        // Ensure binary is executable on Unix
30        #[cfg(unix)]
31        {
32            use std::os::unix::fs::PermissionsExt;
33            let mut perms = std::fs::metadata(&binary_path)?.permissions();
34            perms.set_mode(0o755);
35            std::fs::set_permissions(&binary_path, perms)?;
36        }
37
38        if !db_path.exists() {
39            std::fs::create_dir_all(db_path)?;
40        }
41
42        let mut command = Command::new(binary_path);
43        command
44            .arg("--port")
45            .arg(port.to_string())
46            .arg("--dbpath")
47            .arg(db_path)
48            .arg("--bind_ip")
49            .arg(bind_ip);
50        
51        if auth {
52            command.arg("--auth");
53        }
54
55        let log_path = match os {
56            Os::Windows => "NUL",
57            _ => "/dev/null",
58        };
59
60        command
61            .arg("--quiet")
62            .arg("--logpath")
63            .arg(log_path);
64
65        let child = command.spawn()?;
66
67        Ok(Self { child, connection_string })
68    }
69
70    pub fn kill(&mut self) -> Result<()> {
71        self.child.kill()?;
72        self.child.wait()?;
73        Ok(())
74    }
75}
76
77fn find_binary(root: &Path, name: &str) -> Option<PathBuf> {
78    if root.is_file() {
79        if root.file_name()?.to_str()? == name {
80            return Some(root.to_path_buf());
81        }
82        return None;
83    }
84
85    if root.is_dir() {
86        for entry in std::fs::read_dir(root).ok()? {
87            let entry = entry.ok()?;
88            let path = entry.path();
89            if let Some(found) = find_binary(&path, name) {
90                return Some(found);
91            }
92        }
93    }
94    None
95}