use crate::{MANIFEST_FILENAME, Manifest};
use leo_errors::Backtraced;
use std::{
fs,
path::{Path, PathBuf},
process::Command,
sync::atomic::{AtomicU64, Ordering},
time::{SystemTime, UNIX_EPOCH},
};
pub(crate) fn git_available() -> bool {
Command::new("git").arg("--version").output().map(|o| o.status.success()).unwrap_or(false)
}
pub(crate) fn run_git(dir: &Path, args: &[&str]) -> String {
let out = Command::new("git").args(args).current_dir(dir).output().expect("failed to spawn git");
assert!(out.status.success(), "git {args:?} failed: {}", String::from_utf8_lossy(&out.stderr));
String::from_utf8_lossy(&out.stdout).trim().to_string()
}
pub(crate) fn unique_dir(tag: &str) -> PathBuf {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let seq = COUNTER.fetch_add(1, Ordering::Relaxed);
let dir = std::env::temp_dir().join(format!("leo-git-test-{}-{tag}-{seq}", std::process::id()));
let _ = std::fs::remove_dir_all(&dir);
std::fs::create_dir_all(&dir).unwrap();
dir
}
pub(crate) fn write_file(path: &Path, contents: &str) {
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent).unwrap();
}
std::fs::write(path, contents).unwrap();
}
pub(crate) fn init_repo(dir: &Path, tag: Option<&str>) {
run_git(dir, &["init", "-q", "-b", "main"]);
run_git(dir, &["config", "user.email", "t@example.com"]);
run_git(dir, &["config", "user.name", "Test"]);
run_git(dir, &["add", "."]);
run_git(dir, &["commit", "-q", "-m", "init"]);
if let Some(tag) = tag {
run_git(dir, &["tag", tag]);
}
}
pub(crate) fn file_url(path: &Path) -> String {
let s = path.display().to_string().replace('\\', "/");
if s.starts_with('/') { format!("file://{s}") } else { format!("file:///{s}") }
}
pub(crate) fn fixture_repo(base: &Path) -> (String, String, String) {
let src = base.join("src");
std::fs::create_dir_all(&src).unwrap();
run_git(&src, &["init", "-q", "-b", "main"]);
run_git(&src, &["config", "user.email", "t@example.com"]);
run_git(&src, &["config", "user.name", "Test"]);
std::fs::write(src.join("a.txt"), "one").unwrap();
run_git(&src, &["add", "."]);
run_git(&src, &["commit", "-q", "-m", "c1"]);
run_git(&src, &["tag", "v1"]);
let c1 = run_git(&src, &["rev-parse", "HEAD"]);
run_git(&src, &["checkout", "-q", "-b", "feature"]);
std::fs::write(src.join("b.txt"), "feat").unwrap();
run_git(&src, &["add", "."]);
run_git(&src, &["commit", "-qm", "feat"]);
run_git(&src, &["checkout", "-q", "main"]);
std::fs::write(src.join("a.txt"), "two").unwrap();
run_git(&src, &["commit", "-qam", "c2"]);
let c2 = run_git(&src, &["rev-parse", "HEAD"]);
(file_url(&src), c1, c2)
}
pub(crate) fn write_library(dir: &Path, name: &str, deps_json: &str) {
write_file(
&dir.join(MANIFEST_FILENAME),
&format!(
r#"{{"program":"{name}","version":"0.1.0","description":"","license":"MIT","dependencies":{deps_json}}}"#
),
);
write_file(&dir.join("src/lib.leo"), "// lib\n");
}
pub(crate) fn write_program(dir: &Path, name: &str, deps_json: &str) {
write_file(
&dir.join(MANIFEST_FILENAME),
&format!(
r#"{{"program":"{name}","version":"0.1.0","description":"","license":"MIT","dependencies":{deps_json}}}"#
),
);
write_file(&dir.join("src/main.leo"), "// main\n");
}
pub(crate) fn write_consumer(dir: &Path, deps: &str) {
write_file(
&dir.join(MANIFEST_FILENAME),
&format!(
r#"{{"program":"consumer.aleo","version":"0.1.0","description":"","license":"MIT","dependencies":[{deps}]}}"#
),
);
write_file(&dir.join("src/main.leo"), "// main\n");
}
pub(crate) fn manifest_json(dependencies: &str, dev_dependencies: &str) -> String {
format!(
r#"{{
"program": "test.aleo",
"version": "0.1.0",
"description": "",
"license": "MIT",
"dependencies": {dependencies},
"dev_dependencies": {dev_dependencies}
}}"#
)
}
pub(crate) fn read_manifest(contents: &str) -> Result<Manifest, Backtraced> {
static COUNTER: AtomicU64 = AtomicU64::new(0);
let unique = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_nanos();
let seq = COUNTER.fetch_add(1, Ordering::Relaxed);
let dir = std::env::temp_dir().join(format!("leo-manifest-test-{}-{unique}-{seq}", std::process::id()));
fs::create_dir(&dir).unwrap();
let path = dir.join(MANIFEST_FILENAME);
fs::write(&path, contents).unwrap();
let result = Manifest::read_from_file(&path);
fs::remove_dir_all(dir).unwrap();
result
}