archlinux_inputs_fsck/
makepkg.rs

1use crate::errors::*;
2use std::path::Path;
3use std::process::Stdio;
4use tokio::process::Command;
5
6pub const SUPPORTED_ALGS: &[&str] = &["sha256sums", "sha512sums", "b2sums", "md5sums", "sha1sums"];
7
8#[derive(Debug, PartialEq)]
9pub enum Source {
10    Url(String),
11    UrlWithFilename((String, String)),
12}
13
14impl Source {
15    pub fn filename(&self) -> Option<&str> {
16        match self {
17            Source::Url(_) => None,
18            Source::UrlWithFilename((_, filename)) => Some(filename),
19        }
20    }
21
22    pub fn url(&self) -> &str {
23        match self {
24            Source::Url(url) => url,
25            Source::UrlWithFilename((url, _file)) => url,
26        }
27    }
28
29    pub fn scheme(&self) -> Option<&str> {
30        self.url().split_once("://").map(|x| x.0)
31    }
32}
33
34async fn exec_sh(folder: &Path, cmd: &str) -> Result<Vec<String>> {
35    let child = Command::new("bash")
36        .arg("-c")
37        .arg(format!("source ./PKGBUILD;{}", cmd))
38        .stdout(Stdio::piped())
39        .current_dir(folder)
40        .spawn()
41        .context("Failed to run bash")?;
42
43    let out = child.wait_with_output().await?;
44    if !out.status.success() {
45        bail!(
46            "Process (bash, {:?}) exited with error: {:?}",
47            cmd,
48            out.status
49        );
50    }
51
52    let buf = String::from_utf8(out.stdout).context("Shell output contains invalid utf8")?;
53    Ok(buf.lines().map(String::from).collect())
54}
55
56pub async fn list_variable(folder: &Path, var: &str) -> Result<Vec<String>> {
57    exec_sh(
58        folder,
59        &format!("for x in ${{{}[@]}}; do echo \"$x\"; done", var),
60    )
61    .await
62}
63
64pub async fn list_sources(folder: &Path) -> Result<Vec<Source>> {
65    let sources = list_variable(folder, "source").await?;
66    let sources = sources
67        .into_iter()
68        .map(|line| {
69            if let Some((file, url)) = line.split_once("::") {
70                Source::UrlWithFilename((url.to_string(), file.to_string()))
71            } else {
72                Source::Url(line)
73            }
74        })
75        .collect();
76    Ok(sources)
77}