index_guix/
lib.rs

1mod sexpr;
2#[cfg(feature = "git")]
3mod git;
4#[cfg(feature = "git")]
5pub use git::*;
6
7pub const GUIX_REPO_URL: &str = "https://https.git.savannah.gnu.org/git/guix.git";
8
9#[derive(Debug, Clone)]
10#[non_exhaustive]
11pub struct Package<S> {
12    pub name: S,
13    pub version: S,
14}
15
16/// Parse an .scm file and extract `(define-public … (crate-uri …))` crates from it
17pub fn parse_scm<'a>(file: &'a str) -> Result<impl Iterator<Item=Package<&'a str>>, String> {
18    let all = sexpr::parse(file)?;
19    Ok(all.into_iter().filter_map(|s| {
20        let s = s.into_list()?;
21        if s.len() < 3 || s[0].as_str()? != "define-public" {
22            return None;
23        }
24        let package = s.into_iter().nth(2)?.into_list()?;
25        if package.get(0)?.as_str()? != "package" {
26            return None;
27        }
28        let name = package.iter().skip(1).find_map(|arg| {
29            let origin = arg.if_named("source")?.get(0)?.if_named("origin")?;
30            let uri = origin.iter().find_map(|arg| arg.if_named("uri")?.get(0)?.if_named("crate-uri"))?;
31            uri.get(0)?.as_str()
32        })?;
33        let version = package.into_iter().skip(1).find_map(|arg| {
34            arg.if_named("version")?.get(0)?.as_str()
35        })?;
36        Some(Package { name, version })
37    }))
38}