tinymist_package/pack/
gitcl.rs

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
use ecow::EcoString;

use super::*;

/// A package in the git.
#[derive(Clone)]
pub struct GitClPack<P> {
    /// The namespace to mount.
    pub namespace: EcoString,
    /// The URL of the git.
    pub url: P,
}

impl<P: AsRef<str>> GitClPack<P> {
    /// Creates a new `GitClPack` instance.
    pub fn new(namespace: EcoString, url: P) -> Self {
        Self { namespace, url }
    }
}

impl<P: AsRef<str>> fmt::Debug for GitClPack<P> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "GitClPack({})", self.url.as_ref())
    }
}

impl<P: AsRef<str>> PackFs for GitClPack<P> {
    fn read_all(
        &mut self,
        f: &mut (dyn FnMut(&str, PackFile) -> PackageResult<()> + Send + Sync),
    ) -> PackageResult<()> {
        let temp_dir = std::env::temp_dir();
        let temp_dir = temp_dir.join("tinymist/package-gitcl");

        tinymist_std::fs::paths::temp_dir_in(temp_dir, |temp_dir| {
            let package_path = temp_dir.join("package");
            clone(self.url.as_ref(), &package_path)?;

            Ok(DirPack::new(package_path).read_all(f))
        })
        .map_err(other)?
    }
}

impl<P: AsRef<str>> Pack for GitClPack<P> {}
impl<P: AsRef<str>> PackExt for GitClPack<P> {}

fn clone(url: &str, dst: &Path) -> io::Result<()> {
    let mut cmd = gitcl();
    cmd.arg("clone").arg(url).arg(dst);
    let status = cmd.status()?;
    if !status.success() {
        return Err(io::Error::new(
            io::ErrorKind::Other,
            format!("git clone failed: {status}"),
        ));
    }
    Ok(())
}

fn gitcl() -> std::process::Command {
    std::process::Command::new("git")
}