mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 17:08:21 +00:00
wip
This commit is contained in:
parent
d846174c38
commit
3b9f698c29
12 changed files with 196 additions and 249 deletions
|
|
@ -4,17 +4,14 @@ use crate::{
|
|||
asyncjob::{AsyncJob, RunParams},
|
||||
error::Result,
|
||||
sync::cred::BasicAuthCredential,
|
||||
sync::{
|
||||
remotes::{get_default_remote, tags_missing_remote},
|
||||
RepoPath,
|
||||
},
|
||||
sync::{remotes::tags_missing_remote, RepoPath},
|
||||
AsyncGitNotification,
|
||||
};
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
enum JobState {
|
||||
Request(Option<BasicAuthCredential>),
|
||||
Request(Option<BasicAuthCredential>, String),
|
||||
Response(Result<Vec<String>>),
|
||||
}
|
||||
|
||||
|
|
@ -30,12 +27,14 @@ impl AsyncRemoteTagsJob {
|
|||
///
|
||||
pub fn new(
|
||||
repo: RepoPath,
|
||||
remote: String,
|
||||
basic_credential: Option<BasicAuthCredential>,
|
||||
) -> Self {
|
||||
Self {
|
||||
repo,
|
||||
state: Arc::new(Mutex::new(Some(JobState::Request(
|
||||
basic_credential,
|
||||
remote,
|
||||
)))),
|
||||
}
|
||||
}
|
||||
|
|
@ -45,7 +44,7 @@ impl AsyncRemoteTagsJob {
|
|||
if let Ok(mut state) = self.state.lock() {
|
||||
if let Some(state) = state.take() {
|
||||
return match state {
|
||||
JobState::Request(_) => None,
|
||||
JobState::Request(_, _) => None,
|
||||
JobState::Response(result) => Some(result),
|
||||
};
|
||||
}
|
||||
|
|
@ -65,15 +64,12 @@ impl AsyncJob for AsyncRemoteTagsJob {
|
|||
) -> Result<Self::Notification> {
|
||||
if let Ok(mut state) = self.state.lock() {
|
||||
*state = state.take().map(|state| match state {
|
||||
JobState::Request(basic_credential) => {
|
||||
let result = get_default_remote(&self.repo)
|
||||
.and_then(|remote| {
|
||||
tags_missing_remote(
|
||||
&self.repo,
|
||||
&remote,
|
||||
basic_credential,
|
||||
)
|
||||
});
|
||||
JobState::Request(basic_credential, remote) => {
|
||||
let result = tags_missing_remote(
|
||||
&self.repo,
|
||||
&remote,
|
||||
basic_credential,
|
||||
);
|
||||
|
||||
JobState::Response(result)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ 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},
|
||||
|
|
@ -198,6 +195,7 @@ pub struct BranchCompare {
|
|||
pub(crate) fn branch_set_upstream(
|
||||
repo: &Repository,
|
||||
branch_name: &str,
|
||||
remote: &str,
|
||||
) -> Result<()> {
|
||||
scope_time!("branch_set_upstream");
|
||||
|
||||
|
|
@ -205,7 +203,6 @@ 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 upstream_name = format!("{remote}/{branch_name}");
|
||||
branch.set_upstream(Some(upstream_name.as_str()))?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
//! credentials git helper
|
||||
|
||||
use super::{
|
||||
remotes::get_default_remote_in_repo, repository::repo, RepoPath,
|
||||
};
|
||||
use super::{repository::repo, RepoPath};
|
||||
use crate::error::{Error, Result};
|
||||
use git2::CredentialHelper;
|
||||
|
||||
|
|
@ -30,10 +28,12 @@ impl BasicAuthCredential {
|
|||
}
|
||||
|
||||
/// know if username and password are needed for this url
|
||||
pub fn need_username_password(repo_path: &RepoPath) -> Result<bool> {
|
||||
pub fn need_username_password(
|
||||
repo_path: &RepoPath,
|
||||
remote: &str,
|
||||
) -> Result<bool> {
|
||||
let repo = repo(repo_path)?;
|
||||
let remote =
|
||||
repo.find_remote(&get_default_remote_in_repo(&repo)?)?;
|
||||
let remote = repo.find_remote(remote)?;
|
||||
let url = remote
|
||||
.pushurl()
|
||||
.or_else(|| remote.url())
|
||||
|
|
@ -46,10 +46,11 @@ pub fn need_username_password(repo_path: &RepoPath) -> Result<bool> {
|
|||
/// extract username and password
|
||||
pub fn extract_username_password(
|
||||
repo_path: &RepoPath,
|
||||
remote: &str,
|
||||
) -> Result<BasicAuthCredential> {
|
||||
let repo = repo(repo_path)?;
|
||||
let url = repo
|
||||
.find_remote(&get_default_remote_in_repo(&repo)?)?
|
||||
.find_remote(remote)?
|
||||
.url()
|
||||
.ok_or(Error::UnknownRemote)?
|
||||
.to_owned();
|
||||
|
|
@ -175,7 +176,10 @@ mod tests {
|
|||
repo.remote(DEFAULT_REMOTE_NAME, "http://user@github.com")
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(need_username_password(repo_path).unwrap(), true);
|
||||
assert_eq!(
|
||||
need_username_password(repo_path, "origin").unwrap(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -189,7 +193,10 @@ mod tests {
|
|||
repo.remote(DEFAULT_REMOTE_NAME, "git@github.com:user/repo")
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(need_username_password(repo_path).unwrap(), false);
|
||||
assert_eq!(
|
||||
need_username_password(repo_path, "origin").unwrap(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -208,7 +215,10 @@ mod tests {
|
|||
)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(need_username_password(repo_path).unwrap(), false);
|
||||
assert_eq!(
|
||||
need_username_password(repo_path, "origin").unwrap(),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -221,7 +231,7 @@ mod tests {
|
|||
let repo_path: &RepoPath =
|
||||
&root.as_os_str().to_str().unwrap().into();
|
||||
|
||||
need_username_password(repo_path).unwrap();
|
||||
need_username_password(repo_path, "origin").unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -239,7 +249,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
extract_username_password(repo_path).unwrap(),
|
||||
extract_username_password(repo_path, "origin").unwrap(),
|
||||
BasicAuthCredential::new(
|
||||
Some("user".to_owned()),
|
||||
Some("pass".to_owned())
|
||||
|
|
@ -259,7 +269,7 @@ mod tests {
|
|||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
extract_username_password(repo_path).unwrap(),
|
||||
extract_username_password(repo_path, "origin").unwrap(),
|
||||
BasicAuthCredential::new(Some("user".to_owned()), None)
|
||||
);
|
||||
}
|
||||
|
|
@ -274,6 +284,6 @@ mod tests {
|
|||
let repo_path: &RepoPath =
|
||||
&root.as_os_str().to_str().unwrap().into();
|
||||
|
||||
extract_username_password(repo_path).unwrap();
|
||||
extract_username_password(repo_path, "origin").unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ pub use merge::{
|
|||
};
|
||||
pub use rebase::rebase_branch;
|
||||
pub use remotes::{
|
||||
get_default_remote, get_remotes, has_default_remote,
|
||||
get_remotes, get_single_remote, has_single_remote,
|
||||
push::AsyncProgress, tags::PushTagsProgress,
|
||||
};
|
||||
pub(crate) use repository::repo;
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
ProgressPercent,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use git2::{BranchType, FetchOptions, ProxyOptions, Repository};
|
||||
use git2::{BranchType, FetchOptions, ProxyOptions};
|
||||
use scopetime::scope_time;
|
||||
use utils::bytes2string;
|
||||
|
||||
|
|
@ -44,29 +44,11 @@ pub fn get_remotes(repo_path: &RepoPath) -> Result<Vec<String>> {
|
|||
Ok(remotes)
|
||||
}
|
||||
|
||||
/// tries to find origin or the only remote that is defined if any
|
||||
/// in case of multiple remotes and none named *origin* we fail
|
||||
pub fn get_default_remote(repo_path: &RepoPath) -> Result<String> {
|
||||
/// returns remote name if there is only one single remote
|
||||
pub fn get_single_remote(repo_path: &RepoPath) -> Result<String> {
|
||||
let repo = repo(repo_path)?;
|
||||
get_default_remote_in_repo(&repo)
|
||||
}
|
||||
|
||||
/// see `get_default_remote`
|
||||
pub(crate) fn get_default_remote_in_repo(
|
||||
repo: &Repository,
|
||||
) -> Result<String> {
|
||||
scope_time!("get_default_remote_in_repo");
|
||||
|
||||
let remotes = repo.remotes()?;
|
||||
|
||||
// if `origin` exists return that
|
||||
let found_origin = remotes.iter().any(|r| {
|
||||
r.map(|r| r == DEFAULT_REMOTE_NAME).unwrap_or_default()
|
||||
});
|
||||
if found_origin {
|
||||
return Ok(DEFAULT_REMOTE_NAME.into());
|
||||
}
|
||||
|
||||
//if only one remote exists pick that
|
||||
if remotes.len() == 1 {
|
||||
let first_remote = remotes
|
||||
|
|
@ -85,12 +67,10 @@ pub(crate) fn get_default_remote_in_repo(
|
|||
Err(Error::NoDefaultRemoteFound)
|
||||
}
|
||||
|
||||
/// returns true based on result of `get_default_remote_in_repo` being anything but `NoDefaultRemoteFound`
|
||||
pub fn has_default_remote(repo: &Repository) -> bool {
|
||||
!matches!(
|
||||
get_default_remote_in_repo(repo),
|
||||
Err(Error::NoDefaultRemoteFound)
|
||||
)
|
||||
/// returns true if there is only a single remote
|
||||
pub fn has_single_remote(repo_path: &RepoPath) -> Result<bool> {
|
||||
let repo = repo(repo_path)?;
|
||||
Ok(repo.remotes()?.len() == 1)
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -187,9 +167,7 @@ pub(crate) fn fetch(
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::sync::tests::{
|
||||
debug_cmd_print, repo_clone, repo_init,
|
||||
};
|
||||
use crate::sync::tests::{repo_clone, repo_init};
|
||||
|
||||
#[test]
|
||||
fn test_smoke() {
|
||||
|
|
@ -209,107 +187,4 @@ mod tests {
|
|||
|
||||
fetch(repo_path, "master", None, None).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_remote() {
|
||||
let (remote_dir, _remote) = repo_init().unwrap();
|
||||
let remote_path = remote_dir.path().to_str().unwrap();
|
||||
let (repo_dir, _repo) = repo_clone(remote_path).unwrap();
|
||||
let repo_path: &RepoPath = &repo_dir
|
||||
.into_path()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
debug_cmd_print(
|
||||
repo_path,
|
||||
&format!("git remote add second {remote_path}")[..],
|
||||
);
|
||||
|
||||
let remotes = get_remotes(repo_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
remotes,
|
||||
vec![String::from("origin"), String::from("second")]
|
||||
);
|
||||
|
||||
let first =
|
||||
get_default_remote_in_repo(&repo(repo_path).unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(first, String::from("origin"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_remote_out_of_order() {
|
||||
let (remote_dir, _remote) = repo_init().unwrap();
|
||||
let remote_path = remote_dir.path().to_str().unwrap();
|
||||
let (repo_dir, _repo) = repo_clone(remote_path).unwrap();
|
||||
let repo_path: &RepoPath = &repo_dir
|
||||
.into_path()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
debug_cmd_print(
|
||||
repo_path,
|
||||
"git remote rename origin alternate",
|
||||
);
|
||||
|
||||
debug_cmd_print(
|
||||
repo_path,
|
||||
&format!("git remote add origin {remote_path}")[..],
|
||||
);
|
||||
|
||||
//NOTE: aparently remotes are not chronolically sorted but alphabetically
|
||||
let remotes = get_remotes(repo_path).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
remotes,
|
||||
vec![String::from("alternate"), String::from("origin")]
|
||||
);
|
||||
|
||||
let first =
|
||||
get_default_remote_in_repo(&repo(repo_path).unwrap())
|
||||
.unwrap();
|
||||
assert_eq!(first, String::from("origin"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_remote_inconclusive() {
|
||||
let (remote_dir, _remote) = repo_init().unwrap();
|
||||
let remote_path = remote_dir.path().to_str().unwrap();
|
||||
let (repo_dir, _repo) = repo_clone(remote_path).unwrap();
|
||||
let repo_path: &RepoPath = &repo_dir
|
||||
.into_path()
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.into();
|
||||
|
||||
debug_cmd_print(
|
||||
repo_path,
|
||||
"git remote rename origin alternate",
|
||||
);
|
||||
|
||||
debug_cmd_print(
|
||||
repo_path,
|
||||
&format!("git remote add someremote {remote_path}")[..],
|
||||
);
|
||||
|
||||
let remotes = get_remotes(repo_path).unwrap();
|
||||
assert_eq!(
|
||||
remotes,
|
||||
vec![
|
||||
String::from("alternate"),
|
||||
String::from("someremote")
|
||||
]
|
||||
);
|
||||
|
||||
let res =
|
||||
get_default_remote_in_repo(&repo(repo_path).unwrap());
|
||||
assert_eq!(res.is_err(), true);
|
||||
assert!(matches!(res, Err(Error::NoDefaultRemoteFound)));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,8 @@ pub fn push_raw(
|
|||
scope_time!("push");
|
||||
|
||||
let repo = repo(repo_path)?;
|
||||
let mut remote = repo.find_remote(remote)?;
|
||||
let remote_name = remote;
|
||||
let mut remote = repo.find_remote(remote_name)?;
|
||||
|
||||
let mut options = PushOptions::new();
|
||||
options.proxy_options(proxy_auto());
|
||||
|
|
@ -176,7 +177,7 @@ pub fn push_raw(
|
|||
}
|
||||
|
||||
if !delete {
|
||||
branch_set_upstream(&repo, branch)?;
|
||||
branch_set_upstream(&repo, branch, remote_name)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
47
src/app.rs
47
src/app.rs
|
|
@ -19,7 +19,8 @@ use crate::{
|
|||
options::{Options, SharedOptions},
|
||||
popup_stack::PopupStack,
|
||||
queue::{
|
||||
Action, InternalEvent, NeedsUpdate, Queue, StackablePopupOpen,
|
||||
Action, InternalEvent, NeedsUpdate, PushDetails, Queue,
|
||||
StackablePopupOpen,
|
||||
},
|
||||
setup_popups,
|
||||
strings::{self, ellipsis_trim_start, order},
|
||||
|
|
@ -859,9 +860,8 @@ impl App {
|
|||
self.file_to_open = path;
|
||||
flags.insert(NeedsUpdate::COMMANDS);
|
||||
}
|
||||
InternalEvent::Push(branch, push_type, force, delete) => {
|
||||
self.push_popup
|
||||
.push(branch, push_type, force, delete)?;
|
||||
InternalEvent::Push(details) => {
|
||||
self.push_popup.push(details)?;
|
||||
flags.insert(NeedsUpdate::ALL);
|
||||
}
|
||||
InternalEvent::Pull(branch) => {
|
||||
|
|
@ -1005,12 +1005,14 @@ impl App {
|
|||
))
|
||||
},
|
||||
|name| {
|
||||
InternalEvent::Push(
|
||||
InternalEvent::Push(PushDetails::new(
|
||||
name.to_string(),
|
||||
//TODO:
|
||||
String::new(),
|
||||
PushType::Branch,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
))
|
||||
},
|
||||
),
|
||||
);
|
||||
|
|
@ -1025,32 +1027,39 @@ impl App {
|
|||
error.to_string(),
|
||||
));
|
||||
} else {
|
||||
let remote = sync::get_default_remote(
|
||||
&self.repo.borrow(),
|
||||
)?;
|
||||
//TODO:
|
||||
let remote =
|
||||
sync::get_single_remote(&self.repo.borrow())?;
|
||||
|
||||
self.queue.push(InternalEvent::ConfirmAction(
|
||||
Action::DeleteRemoteTag(tag_name, remote),
|
||||
Action::DeleteRemoteTag { tag_name, remote },
|
||||
));
|
||||
|
||||
flags.insert(NeedsUpdate::ALL);
|
||||
self.tags_popup.update_tags()?;
|
||||
}
|
||||
}
|
||||
Action::DeleteRemoteTag(tag_name, _remote) => {
|
||||
Action::DeleteRemoteTag { tag_name, remote } => {
|
||||
self.queue.push(InternalEvent::Push(
|
||||
tag_name,
|
||||
PushType::Tag,
|
||||
false,
|
||||
true,
|
||||
PushDetails::new(
|
||||
tag_name,
|
||||
remote,
|
||||
PushType::Tag,
|
||||
false,
|
||||
true,
|
||||
),
|
||||
));
|
||||
}
|
||||
Action::ForcePush(branch, force) => {
|
||||
self.queue.push(InternalEvent::Push(
|
||||
branch,
|
||||
PushType::Branch,
|
||||
force,
|
||||
false,
|
||||
PushDetails::new(
|
||||
branch,
|
||||
//TODO:
|
||||
String::new(),
|
||||
PushType::Branch,
|
||||
force,
|
||||
false,
|
||||
),
|
||||
));
|
||||
}
|
||||
Action::PullMerge { rebase, .. } => {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
CommandInfo, Component, DrawableComponent, EventState,
|
||||
},
|
||||
keys::{key_match, SharedKeyConfig},
|
||||
queue::{InternalEvent, Queue},
|
||||
queue::{InternalEvent, PushDetails, Queue},
|
||||
strings,
|
||||
ui::{self, style::SharedTheme},
|
||||
};
|
||||
|
|
@ -15,10 +15,10 @@ use asyncgit::{
|
|||
extract_username_password, need_username_password,
|
||||
BasicAuthCredential,
|
||||
},
|
||||
get_branch_remote, get_default_remote, RepoPathRef,
|
||||
RepoPathRef,
|
||||
},
|
||||
AsyncGitNotification, AsyncPush, PushRequest, PushType,
|
||||
RemoteProgress, RemoteProgressState,
|
||||
AsyncGitNotification, AsyncPush, PushRequest, RemoteProgress,
|
||||
RemoteProgressState,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use crossterm::event::Event;
|
||||
|
|
@ -52,12 +52,11 @@ impl PushComponentModifier {
|
|||
pub struct PushComponent {
|
||||
repo: RepoPathRef,
|
||||
modifier: PushComponentModifier,
|
||||
details: Option<PushDetails>,
|
||||
visible: bool,
|
||||
git_push: AsyncPush,
|
||||
progress: Option<RemoteProgress>,
|
||||
pending: bool,
|
||||
branch: String,
|
||||
push_type: PushType,
|
||||
queue: Queue,
|
||||
theme: SharedTheme,
|
||||
key_config: SharedKeyConfig,
|
||||
|
|
@ -79,8 +78,7 @@ impl PushComponent {
|
|||
modifier: PushComponentModifier::None,
|
||||
pending: false,
|
||||
visible: false,
|
||||
branch: String::new(),
|
||||
push_type: PushType::Branch,
|
||||
details: None,
|
||||
git_push: AsyncPush::new(repo.borrow().clone(), sender),
|
||||
progress: None,
|
||||
input_cred: CredComponent::new(
|
||||
|
|
@ -93,16 +91,9 @@ impl PushComponent {
|
|||
}
|
||||
|
||||
///
|
||||
pub fn push(
|
||||
&mut self,
|
||||
branch: String,
|
||||
push_type: PushType,
|
||||
force: bool,
|
||||
delete: bool,
|
||||
) -> Result<()> {
|
||||
self.branch = branch;
|
||||
self.push_type = push_type;
|
||||
self.modifier = match (force, delete) {
|
||||
pub fn push(&mut self, details: PushDetails) -> Result<()> {
|
||||
self.details = Some(details.clone());
|
||||
self.modifier = match (details.force, details.delete) {
|
||||
(true, true) => PushComponentModifier::ForceDelete,
|
||||
(false, true) => PushComponentModifier::Delete,
|
||||
(true, false) => PushComponentModifier::Force,
|
||||
|
|
@ -113,19 +104,23 @@ impl PushComponent {
|
|||
|
||||
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(
|
||||
&self.repo.borrow(),
|
||||
&details.remote,
|
||||
)? {
|
||||
let cred = extract_username_password(
|
||||
&self.repo.borrow(),
|
||||
&details.remote,
|
||||
)
|
||||
.unwrap_or_else(|_| BasicAuthCredential::new(None, None));
|
||||
if cred.is_complete() {
|
||||
self.push_to_remote(Some(cred), force)
|
||||
self.push_to_remote(Some(cred), details.force)
|
||||
} else {
|
||||
self.input_cred.set_cred(cred);
|
||||
self.input_cred.show()
|
||||
}
|
||||
} else {
|
||||
self.push_to_remote(None, force)
|
||||
self.push_to_remote(None, details.force)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -134,32 +129,35 @@ impl PushComponent {
|
|||
cred: Option<BasicAuthCredential>,
|
||||
force: bool,
|
||||
) -> Result<()> {
|
||||
let remote = if let Ok(Some(remote)) =
|
||||
get_branch_remote(&self.repo.borrow(), &self.branch)
|
||||
{
|
||||
log::info!("push: branch '{}' has upstream for remote '{}' - using that",self.branch,remote);
|
||||
remote
|
||||
} else {
|
||||
log::info!("push: branch '{}' has no upstream - looking up default remote",self.branch);
|
||||
let remote = get_default_remote(&self.repo.borrow())?;
|
||||
log::info!(
|
||||
"push: branch '{}' to remote '{}'",
|
||||
self.branch,
|
||||
remote
|
||||
);
|
||||
remote
|
||||
};
|
||||
if let Some(details) = &self.details {
|
||||
// let remote = if let Ok(Some(remote)) = get_branch_remote(
|
||||
// &self.repo.borrow(),
|
||||
// &details.branch,
|
||||
// ) {
|
||||
// log::info!("push: branch '{}' has upstream for remote '{}' - using that",details.branch,remote);
|
||||
// remote
|
||||
// } else {
|
||||
// log::info!("push: branch '{}' has no upstream - looking up default remote",details.branch);
|
||||
// let remote = get_default_remote(&self.repo.borrow())?;
|
||||
// log::info!(
|
||||
// "push: branch '{}' to remote '{}'",
|
||||
// details.branch,
|
||||
// remote
|
||||
// );
|
||||
// remote
|
||||
// };
|
||||
|
||||
self.pending = true;
|
||||
self.progress = None;
|
||||
self.git_push.request(PushRequest {
|
||||
remote,
|
||||
branch: self.branch.clone(),
|
||||
push_type: self.push_type,
|
||||
force,
|
||||
delete: self.modifier.delete(),
|
||||
basic_credential: cred,
|
||||
})?;
|
||||
self.pending = true;
|
||||
self.progress = None;
|
||||
self.git_push.request(PushRequest {
|
||||
remote: details.remote.clone(),
|
||||
branch: details.branch.clone(),
|
||||
push_type: details.push_type,
|
||||
force,
|
||||
delete: self.modifier.delete(),
|
||||
basic_credential: cred,
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -333,6 +331,7 @@ impl Component for PushComponent {
|
|||
|
||||
fn hide(&mut self) {
|
||||
self.visible = false;
|
||||
self.details = None;
|
||||
}
|
||||
|
||||
fn show(&mut self) -> Result<()> {
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ impl ConfirmComponent {
|
|||
tag_name,
|
||||
),
|
||||
),
|
||||
Action::DeleteRemoteTag(_tag_name,remote) => (
|
||||
Action::DeleteRemoteTag{remote,..} => (
|
||||
strings::confirm_title_delete_tag_remote(),
|
||||
strings::confirm_msg_delete_tag_remote(remote),
|
||||
),
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ struct OptionsData {
|
|||
pub diff: DiffOptions,
|
||||
pub status_show_untracked: Option<ShowUntrackedFilesConfig>,
|
||||
pub commit_msgs: Vec<String>,
|
||||
pub default_remote: Option<String>,
|
||||
}
|
||||
|
||||
const COMMIT_MSG_HISTRY_LENGTH: usize = 20;
|
||||
|
|
@ -125,6 +126,10 @@ impl Options {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn default_remote(&self) -> Option<String> {
|
||||
self.data.default_remote.clone()
|
||||
}
|
||||
|
||||
fn save(&self) {
|
||||
if let Err(e) = self.save_failable() {
|
||||
log::error!("options save error: {}", e);
|
||||
|
|
|
|||
31
src/queue.rs
31
src/queue.rs
|
|
@ -46,7 +46,7 @@ pub enum Action {
|
|||
DeleteLocalBranch(String),
|
||||
DeleteRemoteBranch(String),
|
||||
DeleteTag(String),
|
||||
DeleteRemoteTag(String, String),
|
||||
DeleteRemoteTag { tag_name: String, remote: String },
|
||||
ForcePush(String, bool),
|
||||
PullMerge { incoming: usize, rebase: bool },
|
||||
AbortMerge,
|
||||
|
|
@ -68,6 +68,33 @@ pub enum StackablePopupOpen {
|
|||
CompareCommits(InspectCommitOpen),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PushDetails {
|
||||
pub branch: String,
|
||||
pub remote: String,
|
||||
pub push_type: PushType,
|
||||
pub force: bool,
|
||||
pub delete: bool,
|
||||
}
|
||||
|
||||
impl PushDetails {
|
||||
pub fn new(
|
||||
branch: String,
|
||||
remote: String,
|
||||
push_type: PushType,
|
||||
force: bool,
|
||||
delete: bool,
|
||||
) -> Self {
|
||||
Self {
|
||||
branch,
|
||||
remote,
|
||||
push_type,
|
||||
force,
|
||||
delete,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub enum InternalEvent {
|
||||
///
|
||||
|
|
@ -103,7 +130,7 @@ pub enum InternalEvent {
|
|||
///
|
||||
OpenExternalEditor(Option<String>),
|
||||
///
|
||||
Push(String, PushType, bool, bool),
|
||||
Push(PushDetails),
|
||||
///
|
||||
Pull(String),
|
||||
///
|
||||
|
|
|
|||
|
|
@ -8,18 +8,23 @@ use crate::{
|
|||
},
|
||||
keys::{key_match, SharedKeyConfig},
|
||||
options::SharedOptions,
|
||||
queue::{Action, InternalEvent, NeedsUpdate, Queue, ResetItem},
|
||||
queue::{
|
||||
Action, InternalEvent, NeedsUpdate, PushDetails, Queue,
|
||||
ResetItem,
|
||||
},
|
||||
strings, try_or_popup,
|
||||
ui::style::SharedTheme,
|
||||
};
|
||||
use anyhow::Result;
|
||||
use anyhow::{Ok, Result};
|
||||
use asyncgit::{
|
||||
asyncjob::AsyncSingleJob,
|
||||
cached,
|
||||
sync::{
|
||||
self, status::StatusType, RepoPath, RepoPathRef, RepoState,
|
||||
},
|
||||
sync::{BranchCompare, CommitId},
|
||||
sync::{
|
||||
get_single_remote, has_single_remote, BranchCompare, CommitId,
|
||||
},
|
||||
AsyncBranchesJob, AsyncDiff, AsyncGitNotification, AsyncStatus,
|
||||
DiffParams, DiffType, PushType, StatusItem, StatusParams,
|
||||
};
|
||||
|
|
@ -584,10 +589,13 @@ impl Status {
|
|||
));
|
||||
} else {
|
||||
self.queue.push(InternalEvent::Push(
|
||||
branch,
|
||||
PushType::Branch,
|
||||
force,
|
||||
false,
|
||||
PushDetails::new(
|
||||
branch,
|
||||
String::new(),
|
||||
PushType::Branch,
|
||||
force,
|
||||
false,
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -989,3 +997,23 @@ impl Component for Status {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_remote(
|
||||
repo: &RepoPath,
|
||||
options: &SharedOptions,
|
||||
queue: &Queue,
|
||||
) -> Result<Option<String>> {
|
||||
if let Some(default_remote) = options.borrow().default_remote() {
|
||||
return Ok(Some(default_remote));
|
||||
}
|
||||
|
||||
if has_single_remote(repo)? {
|
||||
return Ok(Some(get_single_remote(repo)?));
|
||||
}
|
||||
|
||||
queue.push(InternalEvent::ShowErrorMsg(String::from(
|
||||
"no default remote found, please configure",
|
||||
)));
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue