Fetch non-origin remotes

This commit is contained in:
Caleb Owens 2024-05-24 14:58:56 +02:00
parent 3f291bd9db
commit 27f3b65b79
4 changed files with 48 additions and 14 deletions

View File

@ -31,6 +31,8 @@ pub enum Error {
Other(git2::Error),
#[error(transparent)]
Utf8(#[from] Utf8Error),
#[error(transparent)]
Remotes(git2::Error),
}
impl From<git2::Error> for Error {

View File

@ -3,6 +3,7 @@ use super::{
TreeBuilder, Url,
};
use crate::path::Normalize;
use git2::string_array::StringArray;
use git2::{BlameOptions, Submodule};
use git2_hooks::HookResult;
#[cfg(unix)]
@ -11,6 +12,7 @@ use std::os::unix::fs::PermissionsExt;
use std::os::windows::process::CommandExt;
use std::process::Stdio;
use std::{io::Write, path::Path, str};
use tokio::sync::Mutex;
// wrapper around git2::Repository to get control over how it's used.
pub struct Repository(git2::Repository);
@ -638,6 +640,21 @@ impl Repository {
.blame_file(path, Some(&mut opts))
.map_err(super::Error::Blame)
}
/// Returns a list of remotes
///
/// Returns Vec<String> instead of StringArray because StringArray cannot safly be sent between threads
pub fn remotes(&self) -> Result<Vec<String>> {
self.0
.remotes()
.map(|string_array| {
string_array
.iter()
.filter_map(|s| s.map(String::from))
.collect()
})
.map_err(super::Error::Remotes)
}
}
pub struct CheckoutTreeBuidler<'a> {

View File

@ -607,6 +607,10 @@ impl Repository {
Err(RemoteError::Auth)
}
pub fn remotes(&self) -> Result<Vec<String>> {
self.git_repository.remotes().map_err(anyhow::Error::from)
}
}
#[derive(Debug, thiserror::Error)]

View File

@ -892,25 +892,36 @@ impl ControllerInner {
let project = self.projects.get(project_id)?;
let mut project_repository = project_repository::Repository::open(&project)?;
let default_target = default_target(&project_repository.project().gb_dir())?;
let remotes = project_repository.remotes()?;
let fetch_results: Vec<Result<(), errors::FetchFromTargetError>> = remotes
.iter()
.map(|remote| {
project_repository
.fetch(remote, &self.helper, askpass.clone())
.map_err(errors::FetchFromTargetError::Remote)
})
.collect();
let project_data_last_fetched = match project_repository
.fetch(
default_target.branch.remote(),
&self.helper,
askpass.clone(),
)
.map_err(errors::FetchFromTargetError::Remote)
{
Ok(()) => projects::FetchResult::Fetched {
let project_data_last_fetched = if fetch_results.iter().any(Result::is_err) {
projects::FetchResult::Error {
timestamp: std::time::SystemTime::now(),
},
Err(error) => projects::FetchResult::Error {
error: fetch_results
.iter()
.filter_map(|result| match result {
Ok(_) => None,
Err(error) => Some(error.to_string()),
})
.collect::<Vec<_>>()
.join("\n"),
}
} else {
projects::FetchResult::Fetched {
timestamp: std::time::SystemTime::now(),
error: error.to_string(),
},
}
};
let default_target = default_target(&project_repository.project().gb_dir())?;
// if we have a push remote, let's fetch from this too
if let Some(push_remote) = &default_target.push_remote_name {
let _ = project_repository