From 34e7b6f9408eab6ce9e356563c46967259212584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20R=C3=BC=C3=9Fler?= Date: Wed, 3 Apr 2024 10:59:23 +0200 Subject: [PATCH] Use default push remote for push --- asyncgit/src/sync/branch/mod.rs | 14 ++++----- asyncgit/src/sync/cred.rs | 51 ++++++++++++++++++++++++++++++- asyncgit/src/sync/mod.rs | 4 +-- asyncgit/src/sync/remotes/push.rs | 4 +-- src/popups/push.rs | 14 ++++----- src/tabs/status.rs | 23 +++++++++++--- 6 files changed, 86 insertions(+), 24 deletions(-) diff --git a/asyncgit/src/sync/branch/mod.rs b/asyncgit/src/sync/branch/mod.rs index 4dbe89aa3a..02645cf5fa 100644 --- a/asyncgit/src/sync/branch/mod.rs +++ b/asyncgit/src/sync/branch/mod.rs @@ -5,13 +5,13 @@ pub mod merge_ff; pub mod merge_rebase; pub mod rename; -use super::{ - remotes::get_default_remote_in_repo, utils::bytes2string, - RepoPath, -}; +use super::{utils::bytes2string, RepoPath}; use crate::{ error::{Error, Result}, - sync::{repository::repo, utils::get_head_repo, CommitId}, + sync::{ + remotes::get_default_remote_for_push_in_repo, + repository::repo, utils::get_head_repo, CommitId, + }, }; use git2::{Branch, BranchType, Repository}; use scopetime::scope_time; @@ -209,7 +209,7 @@ pub struct BranchCompare { } /// -pub(crate) fn branch_set_upstream( +pub(crate) fn branch_set_upstream_after_push( repo: &Repository, branch_name: &str, ) -> Result<()> { @@ -219,7 +219,7 @@ pub(crate) fn branch_set_upstream( repo.find_branch(branch_name, BranchType::Local)?; if branch.upstream().is_err() { - let remote = get_default_remote_in_repo(repo)?; + let remote = get_default_remote_for_push_in_repo(repo)?; let upstream_name = format!("{remote}/{branch_name}"); branch.set_upstream(Some(upstream_name.as_str()))?; } diff --git a/asyncgit/src/sync/cred.rs b/asyncgit/src/sync/cred.rs index 3f908a6352..54eb2cce94 100644 --- a/asyncgit/src/sync/cred.rs +++ b/asyncgit/src/sync/cred.rs @@ -1,7 +1,12 @@ //! credentials git helper use super::{ - remotes::get_default_remote_in_repo, repository::repo, RepoPath, + remotes::{ + get_default_remote_for_push_in_repo, + get_default_remote_in_repo, + }, + repository::repo, + RepoPath, }; use crate::error::{Error, Result}; use git2::CredentialHelper; @@ -43,6 +48,22 @@ pub fn need_username_password(repo_path: &RepoPath) -> Result { Ok(is_http) } +/// know if username and password are needed for this url +pub fn need_username_password_for_push( + repo_path: &RepoPath, +) -> Result { + let repo = repo(repo_path)?; + let remote = repo + .find_remote(&get_default_remote_for_push_in_repo(&repo)?)?; + let url = remote + .pushurl() + .or_else(|| remote.url()) + .ok_or(Error::UnknownRemote)? + .to_owned(); + let is_http = url.starts_with("http"); + Ok(is_http) +} + /// extract username and password pub fn extract_username_password( repo_path: &RepoPath, @@ -71,6 +92,34 @@ pub fn extract_username_password( }) } +/// extract username and password +pub fn extract_username_password_for_push( + repo_path: &RepoPath, +) -> Result { + let repo = repo(repo_path)?; + let url = repo + .find_remote(&get_default_remote_for_push_in_repo(&repo)?)? + .url() + .ok_or(Error::UnknownRemote)? + .to_owned(); + let mut helper = CredentialHelper::new(&url); + + //TODO: look at Cred::credential_helper, + //if the username is in the url we need to set it here, + //I dont think `config` will pick it up + + if let Ok(config) = repo.config() { + helper.config(&config); + } + + Ok(match helper.execute() { + Some((username, password)) => { + BasicAuthCredential::new(Some(username), Some(password)) + } + None => extract_cred_from_url(&url), + }) +} + /// extract credentials from url pub fn extract_cred_from_url(url: &str) -> BasicAuthCredential { url::Url::parse(url).map_or_else( diff --git a/asyncgit/src/sync/mod.rs b/asyncgit/src/sync/mod.rs index fd9392c92e..f5334ba43a 100644 --- a/asyncgit/src/sync/mod.rs +++ b/asyncgit/src/sync/mod.rs @@ -79,8 +79,8 @@ pub use merge::{ }; pub use rebase::rebase_branch; pub use remotes::{ - get_default_remote, get_remotes, push::AsyncProgress, - tags::PushTagsProgress, + get_default_remote, get_default_remote_for_push, get_remotes, + push::AsyncProgress, tags::PushTagsProgress, }; pub(crate) use repository::repo; pub use repository::{RepoPath, RepoPathRef}; diff --git a/asyncgit/src/sync/remotes/push.rs b/asyncgit/src/sync/remotes/push.rs index 37cdd4a9ca..dab50f79ef 100644 --- a/asyncgit/src/sync/remotes/push.rs +++ b/asyncgit/src/sync/remotes/push.rs @@ -2,7 +2,7 @@ use crate::{ error::{Error, Result}, progress::ProgressPercent, sync::{ - branch::branch_set_upstream, + branch::branch_set_upstream_after_push, cred::BasicAuthCredential, remotes::{proxy_auto, Callbacks}, repository::repo, @@ -176,7 +176,7 @@ pub fn push_raw( } if !delete { - branch_set_upstream(&repo, branch)?; + branch_set_upstream_after_push(&repo, branch)?; } Ok(()) diff --git a/src/popups/push.rs b/src/popups/push.rs index 8891c12edf..82787cce30 100644 --- a/src/popups/push.rs +++ b/src/popups/push.rs @@ -13,8 +13,8 @@ use anyhow::Result; use asyncgit::{ sync::{ cred::{ - extract_username_password, need_username_password, - BasicAuthCredential, + extract_username_password_for_push, + need_username_password_for_push, BasicAuthCredential, }, get_branch_remote, remotes::get_default_remote_for_push, @@ -106,11 +106,11 @@ impl PushPopup { self.show()?; - if need_username_password(&self.repo.borrow())? { - let cred = extract_username_password(&self.repo.borrow()) - .unwrap_or_else(|_| { - BasicAuthCredential::new(None, None) - }); + if need_username_password_for_push(&self.repo.borrow())? { + let cred = extract_username_password_for_push( + &self.repo.borrow(), + ) + .unwrap_or_else(|_| BasicAuthCredential::new(None, None)); if cred.is_complete() { self.push_to_remote(Some(cred), force) } else { diff --git a/src/tabs/status.rs b/src/tabs/status.rs index 67605f8e84..feaf62bd49 100644 --- a/src/tabs/status.rs +++ b/src/tabs/status.rs @@ -57,6 +57,11 @@ enum DiffTarget { WorkingDir, } +struct RemoteStatus { + has_remotes: bool, + has_remote_for_push: bool, +} + pub struct Status { repo: RepoPathRef, visible: bool, @@ -65,8 +70,8 @@ pub struct Status { index: ChangesComponent, index_wd: ChangesComponent, diff: DiffComponent, + remotes: RemoteStatus, git_diff: AsyncDiff, - has_remotes: bool, git_state: RepoState, git_status_workdir: AsyncStatus, git_status_stage: AsyncStatus, @@ -155,7 +160,10 @@ impl Status { Self { queue: env.queue.clone(), visible: true, - has_remotes: false, + remotes: RemoteStatus { + has_remotes: false, + has_remote_for_push: false, + }, git_state: RepoState::Clean, focus: Focus::WorkDir, diff_target: DiffTarget::WorkingDir, @@ -407,9 +415,14 @@ impl Status { } fn check_remotes(&mut self) { - self.has_remotes = + self.remotes.has_remotes = sync::get_default_remote(&self.repo.borrow().clone()) .is_ok(); + self.remotes.has_remote_for_push = + sync::get_default_remote_for_push( + &self.repo.borrow().clone(), + ) + .is_ok(); } /// @@ -600,11 +613,11 @@ impl Status { .as_ref() .map_or(true, |state| state.ahead > 0); - is_ahead && self.has_remotes + is_ahead && self.remotes.has_remote_for_push } const fn can_pull(&self) -> bool { - self.has_remotes && self.git_branch_state.is_some() + self.remotes.has_remotes && self.git_branch_state.is_some() } fn can_abort_merge(&self) -> bool {