···11+use std::borrow::Cow;22+use std::fs;33+use std::io;44+use std::path;55+use std::process;66+77+use url::Url;88+99+use crate::model::knot_state::RepositoryProvider;1010+use crate::types::repository_spec::RepositoryKey;1111+1212+fn test_repositories_base() -> Cow<'static, path::Path> {1313+ Cow::Borrowed(path::Path::new(env!("OUT_DIR")))1414+}1515+1616+/// Clone a respository into `base_dir` and reset to the specified1717+/// `reference`.1818+///1919+/// The path for the repository is extracted from the path of the clone URL,2020+/// and will not be cloned if it already exists.2121+fn setup_test_repository(base_dir: &path::Path, source_url: &str, reference: &str) {2222+ let url = Url::parse(source_url).expect("repo source must be a valid URL");2323+ let repo = url.path().trim_start_matches('/');2424+2525+ if let Err(error) = fs::create_dir_all(&base_dir)2626+ && error.kind() != io::ErrorKind::AlreadyExists2727+ {2828+ panic!("could not create test repository base directory: {error}");2929+ }3030+3131+ let path = base_dir.join(repo);3232+ if !fs::exists(&path).unwrap() {3333+ assert!(3434+ process::Command::new("git")3535+ .args(["clone", "--bare", url.as_str()])3636+ .arg(&path)3737+ .stderr(process::Stdio::inherit())3838+ .status()3939+ .expect("git command must be available")4040+ .success(),4141+ "could not clone test repository '{url}'"4242+ );4343+ }4444+4545+ // Reset HEAD to the specified reference, so we always have a known state to4646+ // compare to.4747+ assert!(4848+ process::Command::new("git")4949+ .args(["-C"])5050+ .arg(&path)5151+ .args(["reset", "--soft", reference])5252+ .stderr(process::Stdio::inherit())5353+ .status()5454+ .expect("git command must be available")5555+ .success(),5656+ "could not reset test repository '{url}' to '{reference}"5757+ );5858+}5959+6060+#[derive(Clone)]6161+pub struct TestState(path::PathBuf);6262+6363+impl Default for TestState {6464+ fn default() -> Self {6565+ fn setup() -> path::PathBuf {6666+ let base_dir = test_repositories_base();6767+ setup_test_repository(6868+ &base_dir,6969+ "https://knot.tjh.dev/did:plc:65gha4t3avpfpzmvpbwovss7/core",7070+ "v1.12.0-alpha",7171+ );7272+ base_dir.to_path_buf()7373+ }7474+7575+ Self(setup())7676+ }7777+}7878+7979+impl RepositoryProvider for TestState {8080+ fn path_for_repository(&self, key: &RepositoryKey) -> path::PathBuf {8181+ self.0.join(key.owner_str()).join(key.rkey())8282+ }8383+}