use std::collections::BTreeSet; use std::env::args_os; use std::fs::File; use std::io::Read; use std::os::unix::prelude::*; use std::process::{Command, Stdio}; use cargo::core::SourceId; use serde::{Deserialize, Serialize}; use serde_json; use toml::value::Table as TomlTable; #[derive(Debug, Serialize)] struct Output { git: BTreeSet, } #[derive(Debug, Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq)] struct PrefetchGit { url: String, rev: String, sha256: String, #[serde(rename = "fetchSubmodules")] fetch_submodules: bool, #[serde(rename = "deepClone")] deep_clone: bool, #[serde(rename = "leaveDotGit")] leave_dot_git: bool, } fn main() { let lockfile_path = args_os().skip(1).next().expect("missing lockfile path"); let mut lockfile_bytes = vec![]; let mut lockfile_fd = File::open(lockfile_path).expect("lockfile does not exist"); lockfile_fd .read_to_end(&mut lockfile_bytes) .expect("failed to read lockfile"); let lockfile: TomlTable = toml::from_slice(&lockfile_bytes).expect("can't parse lockfile"); let packages = lockfile .get("package") .expect("missing 'package' key") .as_array() .expect("package is not array"); let sources: BTreeSet<_> = packages .into_iter() .flat_map(|package| package.get("source")) .map(|source| { SourceId::from_url(source.as_str().expect("source not string")) .expect("source not string") }) .filter(|source| source.is_git()) .collect(); let output: BTreeSet = sources .into_iter() .map(|source| { let output = Command::new("nix-prefetch-git") .arg("--fetch-submodules") .arg(source.url().as_str()) .arg(source.precise().expect("missing precise in source URL")) .stderr(Stdio::inherit()) .output() .expect("failed to spawn nix-prefetch-git"); if !output.status.success() { if let Some(code) = output.status.code() { panic!("nix-prefetch-git exited with status {}", code); } else { panic!( "nix-prefetch-git exited with signal {}", output.status.signal().unwrap() ); } } // FIXME: no need to read stdout into a buffer. serde_json::from_slice(&output.stdout).expect("failed to parse nix-prefetch-git output") }) .collect(); println!( "{}", toml::ser::to_string_pretty(&Output { git: output }) .expect("failed to serialize nix-prefetch-git output as TOML") ); }