1use std::path::PathBuf;
2
3use git2::{build::RepoBuilder, FetchOptions, Repository};
4use log::debug;
5
6use crate::error::Result;
7use crate::{convert_to_bare, get_default_branch_name, get_remote_callbacks_default};
8
9pub struct CloneOptions {
11 pub on_transfer_progress: Box<dyn FnMut(usize, usize, usize)>,
13}
14
15impl Default for CloneOptions {
16 fn default() -> Self {
17 Self {
18 on_transfer_progress: Box::new(|_, _, _| {}),
19 }
20 }
21}
22
23pub fn clone(path: PathBuf, url: &str, options: CloneOptions) -> Result<Repository> {
32 let CloneOptions {
33 mut on_transfer_progress,
34 } = options;
35 debug!("path {}", path.display());
36 let path = if path.ends_with(".bare") {
37 debug!("ended with .bare!");
38 path
39 } else {
40 debug!("didn't end with .bare!");
41 path.join(".bare")
42 };
43
44 debug!("final path {}", path.display());
45
46 let auth = get_remote_callbacks_default(Some(url))?;
47 let mut callbacks = auth.callbacks();
48 callbacks.transfer_progress(move |progress| {
49 on_transfer_progress(
50 progress.received_objects(),
51 progress.total_objects(),
52 progress.received_bytes(),
53 );
54 true
55 });
56
57 let mut fetch_options = FetchOptions::new();
58 fetch_options.remote_callbacks(callbacks);
59
60 let mut builder = RepoBuilder::new();
61 builder.bare(true);
62 builder.fetch_options(fetch_options);
63 builder.remote_create(|repo, name, url| {
64 debug!("Creating remote {} at {}", name, url);
65 let remote = repo.remote(name, url)?;
66
67 match get_default_branch_name(repo, Some(remote)) {
68 Ok(default_branch) => {
69 debug!("Default branch: {}", default_branch);
70 repo.remote_add_fetch(
71 name,
72 format!(
73 "+refs/heads/{default_branch}:refs/remotes/origin/{default_branch}",
74 default_branch = default_branch
75 )
76 .as_str(),
77 )?;
78 repo.find_remote(name)
79 }
80 Err(_) => {
81 debug!("No default branch found");
82 repo.remote(name, url)
83 }
84 }
85 });
86
87 debug!("Cloning {} into {}", url, path.display());
88
89 let repo = builder.clone(url, &path)?;
91 convert_to_bare(repo)
94}