1use std::path::Path;
2
3use git_url_parse::GitUrlParseError;
5use thiserror::Error;
6
7mod domain;
8mod repository;
9mod url;
10
11pub use domain::{actor::Actor, commit::Commit};
12pub use repository::{Local, Remote, Repository};
13pub use url::GitUrl;
14
15pub fn open_repository<P: AsRef<Path>>(p: P) -> Result<Repository<Local>, Error> {
17 Repository::<Local>::new(p)
18}
19
20pub fn clone_repository<P: AsRef<Path>>(
22 url: &str,
23 dest: Option<P>,
24) -> Result<Repository<Local>, Error> {
25 Repository::<Remote>::new(url, dest)
26}
27
28#[derive(Debug, Error)]
29pub enum Error {
30 #[error(transparent)]
32 Git(#[from] git2::Error),
33
34 #[error(transparent)]
36 GitUrlError(#[from] GitUrlParseError),
37
38 #[error("URL scheme was {0}, cannot clone URL.")]
40 UrlScheme(String),
41
42 #[error("{0}")]
44 PathError(String),
45}
46
47#[cfg(test)]
50mod common {
51 use once_cell::sync::Lazy;
52 use std::{fs, path::Path};
53 use tempfile::TempDir;
54
55 use super::{Local, Repository};
56
57 pub const EXPECTED_MSG: &str = "commit msg";
58 pub const EXPECTED_ACTOR_NAME: &str = "test";
59 pub const EXPECTED_ACTOR_EMAIL: &str = "test@example.com";
60
61 fn make_repo(tmpdir: &TempDir) {
63 let repo = git2::Repository::init(tmpdir.path()).expect("Failed to init repo");
64
65 let fp = tmpdir.path().join("file.txt");
66 fs::write(&fp, "Hello World\n").expect("Failed to write to file");
67
68 let mut index = repo.index().expect("Failed to get index");
70 index
71 .add_path(Path::new("file.txt"))
72 .expect("Failed to add file to index");
73 index.write().expect("Failed to write index");
74
75 let tree_id = index.write_tree().expect("Failed to write tree");
76 let tree = repo.find_tree(tree_id).expect("Failed to find tree");
77
78 let sig = git2::Signature::now(EXPECTED_ACTOR_NAME, EXPECTED_ACTOR_EMAIL)
80 .expect("Failed to create actor signature");
81
82 repo.commit(Some("HEAD"), &sig, &sig, EXPECTED_MSG, &tree, &[])
83 .expect("Failed to create commit");
84 }
85
86 static TEST_DATA_DIR: Lazy<TempDir> = Lazy::new(|| {
89 let dir = TempDir::new().expect("Create temp dir");
90 make_repo(&dir);
91 dir
92 });
93
94 fn test_data_dir() -> &'static Path {
96 TEST_DATA_DIR.path()
97 }
98
99 pub fn init_repo() -> Repository<Local> {
101 Repository::<Local>::new(test_data_dir()).expect("Failed to init local repository")
102 }
103}