Skip to content

Commit a53ec16

Browse files
author
Stephan Dilly
authored
prefer 'origin' as default remote if it exists (#544)
closes #494
1 parent db52248 commit a53ec16

File tree

7 files changed

+98
-35
lines changed

7 files changed

+98
-35
lines changed

CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- support mouse scrolling [[@WizardOhio24](https://github.com/WizardOhio24)] ([#306](https://github.com/extrawurst/gitui/issues/306))
1313
- show used char count in input texts ([#466](https://github.com/extrawurst/gitui/issues/466))
1414

15-
![push](assets/char_count.gif)
15+
![charcount](assets/char_count.gif)
1616

1717
### Fixed
18+
- push defaults to 'origin' remote if it exists ([#494](https://github.com/extrawurst/gitui/issues/494))
1819
- support missing pageUp/down support in branchlist ([#519](https://github.com/extrawurst/gitui/issues/519))
1920
- don't hide branch name while in commit dialog ([#529](https://github.com/extrawurst/gitui/issues/529))
2021
- don't discard commit message without confirmation ([#530](https://github.com/extrawurst/gitui/issues/530))

asyncgit/src/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ pub enum Error {
1212
#[error("git: remote url not found")]
1313
UnknownRemote,
1414

15+
#[error("git: inconclusive remotes")]
16+
NoDefaultRemoteFound,
17+
1518
#[error("git: work dir error")]
1619
NoWorkDir,
1720

asyncgit/src/sync/branch.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//!
22
3-
use super::{remotes::get_first_remote_in_repo, utils::bytes2string};
3+
use super::{
4+
remotes::get_default_remote_in_repo, utils::bytes2string,
5+
};
46
use crate::{
57
error::{Error, Result},
68
sync::{utils, CommitId},
@@ -97,7 +99,7 @@ pub(crate) fn branch_set_upstream(
9799
repo.find_branch(branch_name, BranchType::Local)?;
98100

99101
if branch.upstream().is_err() {
100-
let remote = get_first_remote_in_repo(repo)?;
102+
let remote = get_default_remote_in_repo(repo)?;
101103
let upstream_name = format!("{}/{}", remote, branch_name);
102104
branch.set_upstream(Some(upstream_name.as_str()))?;
103105
}

asyncgit/src/sync/cred.rs

+14-13
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
//! credentials git helper
22
3+
use super::remotes::get_default_remote_in_repo;
4+
use crate::{
5+
error::{Error, Result},
6+
CWD,
7+
};
38
use git2::{Config, CredentialHelper};
49

5-
use crate::error::{Error, Result};
6-
use crate::CWD;
7-
8-
use super::remotes::get_first_remote_in_repo;
9-
1010
/// basic Authentication Credentials
1111
#[derive(Debug, Clone, Default, PartialEq)]
1212
pub struct BasicAuthCredential {
@@ -34,7 +34,7 @@ impl BasicAuthCredential {
3434
pub fn need_username_password() -> Result<bool> {
3535
let repo = crate::sync::utils::repo(CWD)?;
3636
let url = repo
37-
.find_remote(&get_first_remote_in_repo(&repo)?)?
37+
.find_remote(&get_default_remote_in_repo(&repo)?)?
3838
.url()
3939
.ok_or(Error::UnknownRemote)?
4040
.to_owned();
@@ -46,7 +46,7 @@ pub fn need_username_password() -> Result<bool> {
4646
pub fn extract_username_password() -> Result<BasicAuthCredential> {
4747
let repo = crate::sync::utils::repo(CWD)?;
4848
let url = repo
49-
.find_remote(&get_first_remote_in_repo(&repo)?)?
49+
.find_remote(&get_default_remote_in_repo(&repo)?)?
5050
.url()
5151
.ok_or(Error::UnknownRemote)?
5252
.to_owned();
@@ -81,16 +81,17 @@ pub fn extract_cred_from_url(url: &str) -> BasicAuthCredential {
8181

8282
#[cfg(test)]
8383
mod tests {
84-
use crate::sync::cred::{
85-
extract_cred_from_url, extract_username_password,
86-
need_username_password, BasicAuthCredential,
84+
use crate::sync::{
85+
cred::{
86+
extract_cred_from_url, extract_username_password,
87+
need_username_password, BasicAuthCredential,
88+
},
89+
remotes::DEFAULT_REMOTE_NAME,
90+
tests::repo_init,
8791
};
88-
use crate::sync::tests::repo_init;
8992
use serial_test::serial;
9093
use std::env;
9194

92-
const DEFAULT_REMOTE_NAME: &str = "origin";
93-
9495
#[test]
9596
fn test_credential_complete() {
9697
assert_eq!(

asyncgit/src/sync/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub use hunks::{reset_hunk, stage_hunk, unstage_hunk};
4141
pub use ignore::add_to_ignore;
4242
pub use logwalker::LogWalker;
4343
pub use remotes::{
44-
fetch_origin, get_first_remote, get_remotes, push,
44+
fetch_origin, get_default_remote, get_remotes, push,
4545
ProgressNotification,
4646
};
4747
pub use reset::{reset_stage, reset_workdir};

asyncgit/src/sync/remotes.rs

+72-16
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use git2::{
1313
};
1414
use scopetime::scope_time;
1515

16+
pub const DEFAULT_REMOTE_NAME: &str = "origin";
17+
1618
///
1719
#[derive(Debug, Clone)]
1820
pub enum ProgressNotification {
@@ -66,28 +68,45 @@ pub fn get_remotes(repo_path: &str) -> Result<Vec<String>> {
6668
Ok(remotes)
6769
}
6870

69-
///
70-
pub fn get_first_remote(repo_path: &str) -> Result<String> {
71+
/// tries to find origin or the only remote that is defined if any
72+
/// in case of multiple remotes and none named *origin* we fail
73+
pub fn get_default_remote(repo_path: &str) -> Result<String> {
7174
let repo = utils::repo(repo_path)?;
72-
get_first_remote_in_repo(&repo)
75+
get_default_remote_in_repo(&repo)
7376
}
7477

75-
///
76-
pub(crate) fn get_first_remote_in_repo(
78+
/// see `get_default_remote`
79+
pub(crate) fn get_default_remote_in_repo(
7780
repo: &Repository,
7881
) -> Result<String> {
79-
scope_time!("get_remotes");
82+
scope_time!("get_default_remote_in_repo");
8083

8184
let remotes = repo.remotes()?;
8285

83-
let first_remote = remotes
84-
.iter()
85-
.next()
86-
.flatten()
87-
.map(String::from)
88-
.ok_or_else(|| Error::Generic("no remote found".into()))?;
86+
// if `origin` exists return that
87+
let found_origin = remotes.iter().any(|r| {
88+
r.map(|r| r == DEFAULT_REMOTE_NAME).unwrap_or_default()
89+
});
90+
if found_origin {
91+
return Ok(DEFAULT_REMOTE_NAME.into());
92+
}
8993

90-
Ok(first_remote)
94+
//if only one remote exists pick that
95+
if remotes.len() == 1 {
96+
let first_remote = remotes
97+
.iter()
98+
.next()
99+
.flatten()
100+
.map(String::from)
101+
.ok_or_else(|| {
102+
Error::Generic("no remote found".into())
103+
})?;
104+
105+
return Ok(first_remote);
106+
}
107+
108+
//inconclusive
109+
Err(Error::NoDefaultRemoteFound)
91110
}
92111

93112
///
@@ -96,7 +115,7 @@ pub fn fetch_origin(repo_path: &str, branch: &str) -> Result<usize> {
96115

97116
let repo = utils::repo(repo_path)?;
98117
let mut remote =
99-
repo.find_remote(&get_first_remote_in_repo(&repo)?)?;
118+
repo.find_remote(&get_default_remote_in_repo(&repo)?)?;
100119

101120
let mut options = FetchOptions::new();
102121
options.remote_callbacks(remote_callbacks(None, None));
@@ -288,7 +307,7 @@ mod tests {
288307
}
289308

290309
#[test]
291-
fn test_first_remote() {
310+
fn test_default_remote() {
292311
let td = TempDir::new().unwrap();
293312

294313
debug_cmd_print(
@@ -311,7 +330,44 @@ mod tests {
311330
vec![String::from("origin"), String::from("second")]
312331
);
313332

314-
let first = get_first_remote_in_repo(
333+
let first = get_default_remote_in_repo(
334+
&utils::repo(repo_path).unwrap(),
335+
)
336+
.unwrap();
337+
assert_eq!(first, String::from("origin"));
338+
}
339+
340+
#[test]
341+
fn test_default_remote_out_of_order() {
342+
let td = TempDir::new().unwrap();
343+
344+
debug_cmd_print(
345+
td.path().as_os_str().to_str().unwrap(),
346+
"git clone https://github.com/extrawurst/brewdump.git",
347+
);
348+
349+
debug_cmd_print(
350+
td.path().as_os_str().to_str().unwrap(),
351+
"cd brewdump && git remote rename origin alternate",
352+
);
353+
354+
debug_cmd_print(
355+
td.path().as_os_str().to_str().unwrap(),
356+
"cd brewdump && git remote add origin https://github.com/extrawurst/brewdump.git",
357+
);
358+
359+
let repo_path = td.path().join("brewdump");
360+
let repo_path = repo_path.as_os_str().to_str().unwrap();
361+
362+
//NOTE: aparently remotes are not chronolically sorted but alphabetically
363+
let remotes = get_remotes(repo_path).unwrap();
364+
365+
assert_eq!(
366+
remotes,
367+
vec![String::from("alternate"), String::from("origin")]
368+
);
369+
370+
let first = get_default_remote_in_repo(
315371
&utils::repo(repo_path).unwrap(),
316372
)
317373
.unwrap();

src/components/push.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use asyncgit::{
1515
extract_username_password, need_username_password,
1616
BasicAuthCredential,
1717
},
18-
get_first_remote,
18+
get_default_remote,
1919
},
2020
AsyncNotification, AsyncPush, PushProgress, PushProgressState,
2121
PushRequest, CWD,
@@ -102,7 +102,7 @@ impl PushComponent {
102102
self.pending = true;
103103
self.progress = None;
104104
self.git_push.request(PushRequest {
105-
remote: get_first_remote(CWD)?,
105+
remote: get_default_remote(CWD)?,
106106
branch: self.branch.clone(),
107107
force,
108108
basic_credential: cred,

0 commit comments

Comments
 (0)