Skip to content

Commit

Permalink
refactor: fetch with git2
Browse files Browse the repository at this point in the history
  • Loading branch information
altsem committed Feb 25, 2024
1 parent 09c6054 commit 15c6971
Show file tree
Hide file tree
Showing 16 changed files with 347 additions and 119 deletions.
3 changes: 0 additions & 3 deletions src/git/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,6 @@ pub(crate) fn commit_fixup_cmd(reference: &str) -> Command {
pub(crate) fn pull_cmd() -> Command {
git(&["pull"])
}
pub(crate) fn fetch_all_cmd() -> Command {
git(&["fetch", "--all"])
}
pub(crate) fn rebase_interactive_cmd(reference: &str) -> Command {
git(&["rebase", "-i", "--autostash", reference])
}
Expand Down
60 changes: 51 additions & 9 deletions src/git/remote.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,56 @@
use crate::Res;
use git2::FetchOptions;
use git2::PushOptions;
use git2::RemoteCallbacks;
use git2::Repository;

pub(crate) fn fetch_upstream(repo: &Repository) -> Res<String> {
let Ok(head) = repo.head() else {
return Err(Box::new(RemoteError::NoHead));
};
let Ok(upstream) = repo.branch_upstream_remote(head.name().unwrap()) else {
return Err(Box::new(RemoteError::NoUpstreamRemote));
};

fetch(repo, repo.find_remote(upstream.as_str().unwrap()).unwrap())
}

pub(crate) fn fetch_all(repo: &Repository) -> Res<String> {
for remote in repo.remotes()?.iter().flatten() {
fetch(repo, repo.find_remote(remote).unwrap())?;
}

Ok("Fetched all".to_string())
}

fn fetch(repo: &Repository, mut remote: git2::Remote<'_>) -> Res<String> {
{
let mut opts = FetchOptions::new();
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(|url, username_from_url, allowed_types| {
auth_git2::GitAuthenticator::default().credentials(&repo.config()?)(
url,
username_from_url,
allowed_types,
)
});

opts.remote_callbacks(callbacks);

let refspec_array = &remote.fetch_refspecs()?;
let refspecs = refspec_array.into_iter().flatten().collect::<Vec<_>>();
remote.fetch::<&str>(&refspecs, Some(&mut opts), None)?;
};

Ok(format!("Fetched {}", remote.name().unwrap()))
}

pub(crate) fn push_upstream(repo: &Repository) -> Res<String> {
let Ok(head) = repo.head() else {
return Err(Box::new(PushError::NoHead));
return Err(Box::new(RemoteError::NoHead));
};
let Ok(upstream) = repo.branch_upstream_remote(head.name().unwrap()) else {
return Err(Box::new(PushError::NoUpstreamRemote));
return Err(Box::new(RemoteError::NoUpstreamRemote));
};

let mut remote = repo.find_remote(upstream.as_str().unwrap()).unwrap();
Expand Down Expand Up @@ -36,27 +78,27 @@ pub(crate) fn push_upstream(repo: &Repository) -> Res<String> {
}

if let Some(status) = out_status {
return Err(Box::new(PushError::ResponseStatus(status)));
return Err(Box::new(RemoteError::ResponseStatus(status)));
}

Ok(format!("Pushed {} to {}", out_name, remote.name().unwrap()))
}

#[derive(Debug)]
pub(crate) enum PushError {
pub(crate) enum RemoteError {
NoHead,
NoUpstreamRemote,
ResponseStatus(String),
}

impl std::fmt::Display for PushError {
impl std::fmt::Display for RemoteError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(match self {
PushError::NoHead => "No head",
PushError::NoUpstreamRemote => "No upstream remote",
PushError::ResponseStatus(status) => status,
RemoteError::NoHead => "No head",
RemoteError::NoUpstreamRemote => "No upstream remote",
RemoteError::ResponseStatus(status) => status,
})
}
}

impl std::error::Error for PushError {}
impl std::error::Error for RemoteError {}
10 changes: 6 additions & 4 deletions src/keybinds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,16 @@ pub(crate) const KEYBINDS: &[Keybind] = &[
// Fetch
Keybind::nomod(None, Char('f'), Submenu(Fetch)),
Keybind::nomod(Fetch, Char('a'), FetchAll),
Keybind::nomod(Fetch, Char('u'), FetchUpstream),
// Log
Keybind::nomod(None, Char('l'), Submenu(Log)),
Keybind::nomod(Log, Char('l'), LogCurrent),
// Pull
Keybind::shift(None, Char('F'), Submenu(Pull)),
Keybind::nomod(Pull, Char('p'), PullRemote),
Keybind::nomod(Pull, Char('u'), PullUpstream),
// Push
Keybind::shift(None, Char('P'), Submenu(Push)),
Keybind::nomod(Push, Char('u'), PushUpstreamRemote),
Keybind::nomod(Push, Char('u'), PushUpstream),
// Rebase
Keybind::nomod(None, Char('r'), Submenu(Rebase)),
Keybind::nomod(Rebase, Char('i'), Target(RebaseInteractive)),
Expand Down Expand Up @@ -138,12 +139,13 @@ pub(crate) enum Op {
ToggleSection,
HalfPageUp,
HalfPageDown,
PushUpstreamRemote,
PullRemote,
PushUpstream,
PullUpstream,
Submenu(SubmenuOp),
Commit,
CommitAmend,
FetchAll,
FetchUpstream,
LogCurrent,
RebaseAbort,
RebaseContinue,
Expand Down
Loading

0 comments on commit 15c6971

Please sign in to comment.