Skip to content

Commit 9c06fa8

Browse files
committed
Get default fetch remote from configuration
1 parent 64a1e38 commit 9c06fa8

File tree

5 files changed

+115
-23
lines changed

5 files changed

+115
-23
lines changed

asyncgit/src/sync/cred.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use super::{
44
remotes::{
5+
get_default_remote_for_fetch_in_repo,
56
get_default_remote_for_push_in_repo,
67
get_default_remote_in_repo,
78
},
@@ -48,6 +49,22 @@ pub fn need_username_password(repo_path: &RepoPath) -> Result<bool> {
4849
Ok(is_http)
4950
}
5051

52+
/// know if username and password are needed for this url
53+
pub fn need_username_password_for_fetch(
54+
repo_path: &RepoPath,
55+
) -> Result<bool> {
56+
let repo = repo(repo_path)?;
57+
let remote = repo
58+
.find_remote(&get_default_remote_for_fetch_in_repo(&repo)?)?;
59+
let url = remote
60+
.url()
61+
.or_else(|| remote.url())
62+
.ok_or(Error::UnknownRemote)?
63+
.to_owned();
64+
let is_http = url.starts_with("http");
65+
Ok(is_http)
66+
}
67+
5168
/// know if username and password are needed for this url
5269
pub fn need_username_password_for_push(
5370
repo_path: &RepoPath,
@@ -92,6 +109,34 @@ pub fn extract_username_password(
92109
})
93110
}
94111

112+
/// extract username and password
113+
pub fn extract_username_password_for_fetch(
114+
repo_path: &RepoPath,
115+
) -> Result<BasicAuthCredential> {
116+
let repo = repo(repo_path)?;
117+
let url = repo
118+
.find_remote(&get_default_remote_for_fetch_in_repo(&repo)?)?
119+
.url()
120+
.ok_or(Error::UnknownRemote)?
121+
.to_owned();
122+
let mut helper = CredentialHelper::new(&url);
123+
124+
//TODO: look at Cred::credential_helper,
125+
//if the username is in the url we need to set it here,
126+
//I dont think `config` will pick it up
127+
128+
if let Ok(config) = repo.config() {
129+
helper.config(&config);
130+
}
131+
132+
Ok(match helper.execute() {
133+
Some((username, password)) => {
134+
BasicAuthCredential::new(Some(username), Some(password))
135+
}
136+
None => extract_cred_from_url(&url),
137+
})
138+
}
139+
95140
/// extract username and password
96141
pub fn extract_username_password_for_push(
97142
repo_path: &RepoPath,

asyncgit/src/sync/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,9 @@ pub use merge::{
7979
};
8080
pub use rebase::rebase_branch;
8181
pub use remotes::{
82-
get_default_remote, get_default_remote_for_push, get_remotes,
83-
push::AsyncProgress, tags::PushTagsProgress,
82+
get_default_remote, get_default_remote_for_fetch,
83+
get_default_remote_for_push, get_remotes, push::AsyncProgress,
84+
tags::PushTagsProgress,
8485
};
8586
pub(crate) use repository::repo;
8687
pub use repository::{RepoPath, RepoPathRef};

asyncgit/src/sync/remotes/mod.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,46 @@ fn get_current_branch(
6666
Ok(None)
6767
}
6868

69+
/// Tries to find the default repo to fetch from based on configuration.
70+
///
71+
/// > branch.<name>.remote
72+
/// >
73+
/// > When on branch `<name>`, it tells `git fetch` and `git push` which remote to fetch from or
74+
/// > push to. [...] If no remote is configured, or if you are not on any branch and there is more
75+
/// > than one remote defined in the repository, it defaults to `origin` for fetching [...].
76+
///
77+
/// [git-config-branch-name-remote]: https://git-scm.com/docs/git-config#Documentation/git-config.txt-branchltnamegtremote
78+
///
79+
/// Falls back to `get_default_remote_in_repo`.
80+
pub fn get_default_remote_for_fetch(
81+
repo_path: &RepoPath,
82+
) -> Result<String> {
83+
let repo = repo(repo_path)?;
84+
get_default_remote_for_fetch_in_repo(&repo)
85+
}
86+
87+
pub(crate) fn get_default_remote_for_fetch_in_repo(
88+
repo: &Repository,
89+
) -> Result<String> {
90+
scope_time!("get_default_remote_for_fetch_in_repo");
91+
92+
let config = repo.config()?;
93+
94+
let branch = get_current_branch(repo)?;
95+
96+
if let Some(branch) = branch {
97+
let remote_name = bytes2string(branch.name_bytes()?)?;
98+
99+
let entry_name = format!("branch.{}.remote", &remote_name);
100+
101+
if let Ok(entry) = config.get_entry(&entry_name) {
102+
return bytes2string(entry.value_bytes());
103+
}
104+
}
105+
106+
get_default_remote_in_repo(repo)
107+
}
108+
69109
/// Tries to find the default repo to push to based on configuration.
70110
///
71111
/// > remote.pushDefault

src/popups/pull.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ use asyncgit::{
1515
sync::{
1616
self,
1717
cred::{
18-
extract_username_password, need_username_password,
19-
BasicAuthCredential,
18+
extract_username_password_for_fetch,
19+
need_username_password_for_fetch, BasicAuthCredential,
2020
},
21-
get_default_remote, RepoPathRef,
21+
remotes::get_default_remote_for_fetch,
22+
RepoPathRef,
2223
},
2324
AsyncGitNotification, AsyncPull, FetchRequest, RemoteProgress,
2425
};
@@ -69,11 +70,11 @@ impl PullPopup {
6970
pub fn fetch(&mut self, branch: String) -> Result<()> {
7071
self.branch = branch;
7172
self.show()?;
72-
if need_username_password(&self.repo.borrow())? {
73-
let cred = extract_username_password(&self.repo.borrow())
74-
.unwrap_or_else(|_| {
75-
BasicAuthCredential::new(None, None)
76-
});
73+
if need_username_password_for_fetch(&self.repo.borrow())? {
74+
let cred = extract_username_password_for_fetch(
75+
&self.repo.borrow(),
76+
)
77+
.unwrap_or_else(|_| BasicAuthCredential::new(None, None));
7778
if cred.is_complete() {
7879
self.fetch_from_remote(Some(cred))
7980
} else {
@@ -92,7 +93,9 @@ impl PullPopup {
9293
self.pending = true;
9394
self.progress = None;
9495
self.git_fetch.request(FetchRequest {
95-
remote: get_default_remote(&self.repo.borrow())?,
96+
remote: get_default_remote_for_fetch(
97+
&self.repo.borrow(),
98+
)?,
9699
branch: self.branch.clone(),
97100
basic_credential: cred,
98101
})?;

src/tabs/status.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ enum DiffTarget {
5858
}
5959

6060
struct RemoteStatus {
61-
has_remotes: bool,
61+
has_remote_for_fetch: bool,
6262
has_remote_for_push: bool,
6363
}
6464

@@ -161,7 +161,7 @@ impl Status {
161161
queue: env.queue.clone(),
162162
visible: true,
163163
remotes: RemoteStatus {
164-
has_remotes: false,
164+
has_remote_for_fetch: false,
165165
has_remote_for_push: false,
166166
},
167167
git_state: RepoState::Clean,
@@ -415,9 +415,11 @@ impl Status {
415415
}
416416

417417
fn check_remotes(&mut self) {
418-
self.remotes.has_remotes =
419-
sync::get_default_remote(&self.repo.borrow().clone())
420-
.is_ok();
418+
self.remotes.has_remote_for_fetch =
419+
sync::get_default_remote_for_fetch(
420+
&self.repo.borrow().clone(),
421+
)
422+
.is_ok();
421423
self.remotes.has_remote_for_push =
422424
sync::get_default_remote_for_push(
423425
&self.repo.borrow().clone(),
@@ -580,7 +582,7 @@ impl Status {
580582
}
581583

582584
fn fetch(&self) {
583-
if self.can_pull() {
585+
if self.can_fetch() {
584586
self.queue.push(InternalEvent::FetchRemotes);
585587
}
586588
}
@@ -616,8 +618,9 @@ impl Status {
616618
is_ahead && self.remotes.has_remote_for_push
617619
}
618620

619-
const fn can_pull(&self) -> bool {
620-
self.remotes.has_remotes && self.git_branch_state.is_some()
621+
const fn can_fetch(&self) -> bool {
622+
self.remotes.has_remote_for_fetch
623+
&& self.git_branch_state.is_some()
621624
}
622625

623626
fn can_abort_merge(&self) -> bool {
@@ -754,12 +757,12 @@ impl Component for Status {
754757

755758
out.push(CommandInfo::new(
756759
strings::commands::status_fetch(&self.key_config),
757-
self.can_pull(),
760+
self.can_fetch(),
758761
!focus_on_diff,
759762
));
760763
out.push(CommandInfo::new(
761764
strings::commands::status_pull(&self.key_config),
762-
self.can_pull(),
765+
self.can_fetch(),
763766
!focus_on_diff,
764767
));
765768

@@ -881,13 +884,13 @@ impl Component for Status {
881884
Ok(EventState::Consumed)
882885
} else if key_match(k, self.key_config.keys.fetch)
883886
&& !self.is_focus_on_diff()
884-
&& self.can_pull()
887+
&& self.can_fetch()
885888
{
886889
self.fetch();
887890
Ok(EventState::Consumed)
888891
} else if key_match(k, self.key_config.keys.pull)
889892
&& !self.is_focus_on_diff()
890-
&& self.can_pull()
893+
&& self.can_fetch()
891894
{
892895
self.pull();
893896
Ok(EventState::Consumed)

0 commit comments

Comments
 (0)