tinymist_package/pack/
gitcl.rs

1use ecow::EcoString;
2
3use super::*;
4
5/// A package in the git.
6#[derive(Clone)]
7pub struct GitClPack<P> {
8    /// The namespace to mount.
9    pub namespace: EcoString,
10    /// The URL of the git.
11    pub url: P,
12}
13
14impl<P: AsRef<str>> GitClPack<P> {
15    /// Creates a new `GitClPack` instance.
16    pub fn new(namespace: EcoString, url: P) -> Self {
17        Self { namespace, url }
18    }
19}
20
21impl<P: AsRef<str>> fmt::Debug for GitClPack<P> {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        write!(f, "GitClPack({})", self.url.as_ref())
24    }
25}
26
27impl<P: AsRef<str>> PackFs for GitClPack<P> {
28    fn read_all(
29        &mut self,
30        f: &mut (dyn FnMut(&str, PackFile) -> PackageResult<()> + Send + Sync),
31    ) -> PackageResult<()> {
32        let temp_dir = std::env::temp_dir();
33        let temp_dir = temp_dir.join("tinymist/package-gitcl");
34
35        tinymist_std::fs::paths::temp_dir_in(temp_dir, |temp_dir| {
36            let package_path = temp_dir.join("package");
37            clone(self.url.as_ref(), &package_path)?;
38
39            Ok(DirPack::new(package_path).read_all(f))
40        })
41        .map_err(other)?
42    }
43}
44
45impl<P: AsRef<str>> Pack for GitClPack<P> {}
46impl<P: AsRef<str>> PackExt for GitClPack<P> {}
47
48fn clone(url: &str, dst: &Path) -> io::Result<()> {
49    let mut cmd = gitcl();
50    cmd.arg("clone").arg(url).arg(dst);
51    let status = cmd.status()?;
52    if !status.success() {
53        return Err(io::Error::other(format!("git clone failed: {status}")));
54    }
55    Ok(())
56}
57
58fn gitcl() -> std::process::Command {
59    std::process::Command::new("git")
60}