1#[cfg(not(target_arch = "wasm32"))]
2use git2::{FetchOptions, Oid, Repository};
3use std::error::Error;
4#[cfg(not(target_arch = "wasm32"))]
5use std::path::Path;
6
7#[cfg(not(target_arch = "wasm32"))]
10pub fn fetch_and_checkout<P: AsRef<Path>>(
11 remote: &str,
12 target_directory: P,
13 refspec: &str,
14) -> Result<(), Box<dyn Error>> {
15 let repo = Repository::init(&target_directory)?;
19 let res = _fetch_and_checkout(remote, repo, refspec);
20 if res.is_err() {
21 std::fs::remove_dir_all(target_directory).expect("Failed to clean up directory");
22 }
23
24 res
25}
26
27#[cfg(not(target_arch = "wasm32"))]
28fn _fetch_and_checkout(
29 remote: &str,
30 repo: Repository,
31 refspec: &str,
32) -> Result<(), Box<dyn Error>> {
33 let mut remote = repo.remote("origin", remote)?;
34
35 let mut fetch_options = FetchOptions::new();
36
37 fetch_options.depth(1);
38
39 if let Err(e) = remote.fetch(&[refspec], Some(&mut fetch_options), None) {
41 if let (git2::ErrorClass::Net, git2::ErrorCode::GenericError) = (e.class(), e.code()) {
42 return Err(format!("{}\nMake sure revision {} exists in remote", e, refspec).into());
45 } else {
46 return Err(e.into());
47 }
48 }
49
50 let oid = Oid::from_str(refspec)?;
52 let commit = repo.find_commit(oid)?;
53
54 repo.checkout_tree(commit.as_object(), None)?;
56 repo.set_head_detached(oid)?;
57
58 Ok(())
59}
60
61#[cfg(target_arch = "wasm32")]
62pub fn fetch_and_checkout(
63 _remote: &str,
64 _target_directory: &str,
65 _refspec: &str,
66) -> Result<(), Box<dyn Error>> {
67 Err("Not supported on WASM".into())
68}