diff --git a/src/refractr.rs b/src/refractr.rs index 1f89495..6b70924 100644 --- a/src/refractr.rs +++ b/src/refractr.rs @@ -52,22 +52,48 @@ impl Refractr { common::verbose(self.verbose, 2, format!("Pulling origin")); repo.find_remote("origin")?.fetch(&branches, None, None)?; - let fetch_head = repo.find_reference("FETCH_HEAD")?; - let fetch_commit = repo.reference_to_annotated_commit(&fetch_head)?; - let analysis = repo.merge_analysis(&[&fetch_commit])?; - if analysis.0.is_fast_forward() { - for branch in branches { - let refname = format!("refs/remotes/origin/{}", branch); - let mut reference = repo.find_reference(&refname)?; - reference.rename(format!("refs/heads/{}", branch).as_str(), false, "")?; - repo.set_head(&refname)?; - let _ = repo.checkout_head(Some(CheckoutBuilder::default().force())); - } + for branch in branches { + let refname = format!("refs/remotes/origin/{}", branch); + let mut reference = repo.find_reference(&refname)?; + reference.rename(format!("refs/heads/{}", branch).as_str(), true, "")?; } Ok(()) } + fn fetch(&self, repo: &Repository, branches: &Vec, ssh: Option<&String>) -> Result<(), Error> { + match ssh { + Some(key) => { + let mut cb = RemoteCallbacks::new(); + let mut fo = FetchOptions::new(); + cb.credentials(move |_,_,_| Cred::ssh_key( + "git", + None, + Path::new(&key), + None)); + cb.certificate_check(|cert, url| { + let mut sha256 = String::new(); + for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() { + sha256.push_str(&hex::encode(i.to_string())); + } + common::warning( + format!("implicitly trusting unknown host {} with sha256 host key {}", + url, + hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()))); + common::warning( + format!("to ignore this error in the future, add this host to your known_hosts file")); + Ok(CertificateCheckStatus::CertificateOk) + }); + fo.download_tags(git2::AutotagOption::All); + fo.remote_callbacks(cb); + repo.find_remote("origin")?.fetch(&branches, Some(&mut fo), None)?; + }, + None => repo.find_remote("origin")?.fetch(&branches, None, None)? + }; + + Ok(()) + } + fn set_up_refs(&self, repo: &Repository, branches: &Vec) -> Result<(), Error> { for branch in branches { let mut fetch_head = repo.find_reference(format!("refs/remotes/origin/{}", branch).as_str())?; @@ -192,14 +218,6 @@ impl Refractr { self.verbose, 2, format!("Interval for {} has arrived, pulling", repos[i].cfg.from)); - let mut origin = repos[i].repo.find_remote("origin").unwrap(); - let mut refs = Vec::new(); - let strings = self.get_refs(&repos[i].cfg.branches); - for branch in &strings { - refs.push(branch.as_str()); - } - origin.fetch(&refs, None, None).unwrap(); - self.set_up_refs(&repos[i].repo, &repos[i].cfg.branches); let _ = self.fast_forward(&repos[i].path, &repos[i].cfg.branches); if let Err(e) = self.push_remotes( @@ -256,11 +274,33 @@ impl Refractr { 1, format!("Cloning repository: {}", &cfg.config.from)); - let cb = RemoteCallbacks::new(); + let mut builder = RepoBuilder::new(); + let mut cb = RemoteCallbacks::new(); let mut fo = FetchOptions::new(); + + if cfg.config.from.starts_with("ssh://") { + let key_string = cfg.config.git.ssh_identity_file.clone(); + cb.credentials(move |_,_,_| Cred::ssh_key( + "git", + None, + Path::new(&key_string), + None)); + cb.certificate_check(|cert, url| { + let mut sha256 = String::new(); + for i in cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec() { + sha256.push_str(&hex::encode(i.to_string())); + } + common::warning( + format!("implicitly trusting unknown host {} with sha256 host key {}", + url, + hex::encode(cert.as_hostkey().unwrap().hash_sha256().unwrap().to_vec()))); + common::warning( + format!("to ignore this error in the future, add this host to your known_hosts file")); + Ok(CertificateCheckStatus::CertificateOk) + }); + } fo.download_tags(git2::AutotagOption::All); fo.remote_callbacks(cb); - let mut builder = RepoBuilder::new(); builder.fetch_options(fo); let repo_dir = format!("{}/{}", &path_str, repo_name); @@ -279,17 +319,10 @@ impl Refractr { } }; - let repo_fresh = Repository::open(Path::new(&repo_dir)).unwrap(); - self.set_up_refs(&repo_fresh, &cfg.config.branches); - let mut origin = repo_fresh.find_remote("origin").unwrap(); - let mut refs = Vec::new(); - let strings = self.get_refs(&cfg.config.branches); - for branch in &strings { - refs.push(branch.as_str()); - } - origin.fetch(&refs, None, None).unwrap(); + self.set_up_refs(&repo, &cfg.config.branches); + self.fetch(&repo, &cfg.config.branches, Some(&cfg.config.git.ssh_identity_file)).unwrap(); - let remotes = match self.make_remotes(&repo_fresh, &cfg) { + let remotes = match self.make_remotes(&repo, &cfg) { Ok(v) => v, Err(e) => return Err(e) };