Skip to content

Commit 59acccc

Browse files
author
Stephan Dilly
committed
split up stuff into new remote mod
1 parent a53ec16 commit 59acccc

File tree

5 files changed

+205
-184
lines changed

5 files changed

+205
-184
lines changed

asyncgit/src/cached/branchname.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{error::Result, sync};
1+
use crate::{
2+
error::Result,
3+
sync::{self, branch::get_branch_name},
4+
};
25
use sync::Head;
36

47
///
@@ -38,7 +41,7 @@ impl BranchName {
3841
}
3942

4043
fn fetch(&mut self, head: Head) -> Result<String> {
41-
let name = sync::get_branch_name(self.repo_path.as_str())?;
44+
let name = get_branch_name(self.repo_path.as_str())?;
4245
self.last_result = Some((head, name.clone()));
4346
Ok(name)
4447
}

asyncgit/src/push.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
use crate::sync::cred::BasicAuthCredential;
21
use crate::{
32
error::{Error, Result},
4-
sync, AsyncNotification, CWD,
3+
sync::{
4+
cred::BasicAuthCredential, remotes::push::push,
5+
remotes::push::ProgressNotification,
6+
},
7+
AsyncNotification, CWD,
58
};
69
use crossbeam_channel::{unbounded, Receiver, Sender};
710
use git2::PackBuilderStage;
@@ -11,7 +14,6 @@ use std::{
1114
thread,
1215
time::Duration,
1316
};
14-
use sync::ProgressNotification;
1517
use thread::JoinHandle;
1618

1719
///
@@ -162,7 +164,7 @@ impl AsyncPush {
162164
arc_progress,
163165
);
164166

165-
let res = sync::push(
167+
let res = push(
166168
CWD,
167169
params.remote.as_str(),
168170
params.branch.as_str(),

asyncgit/src/sync/mod.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//TODO: remove once we have this activated on the toplevel
44
#![deny(clippy::expect_used)]
55

6-
mod branch;
6+
pub mod branch;
77
mod commit;
88
mod commit_details;
99
mod commit_files;
@@ -14,14 +14,13 @@ mod hooks;
1414
mod hunks;
1515
mod ignore;
1616
mod logwalker;
17-
mod remotes;
17+
pub mod remotes;
1818
mod reset;
1919
mod stash;
2020
pub mod status;
2121
mod tags;
2222
pub mod utils;
2323

24-
pub(crate) use branch::get_branch_name;
2524
pub use branch::{
2625
branch_compare_upstream, checkout_branch, create_branch,
2726
delete_branch, get_branches_to_display, rename_branch,
@@ -40,10 +39,7 @@ pub use hooks::{
4039
pub use hunks::{reset_hunk, stage_hunk, unstage_hunk};
4140
pub use ignore::add_to_ignore;
4241
pub use logwalker::LogWalker;
43-
pub use remotes::{
44-
fetch_origin, get_default_remote, get_remotes, push,
45-
ProgressNotification,
46-
};
42+
pub use remotes::{fetch_origin, get_default_remote, get_remotes};
4743
pub use reset::{reset_stage, reset_workdir};
4844
pub use stash::{get_stashes, stash_apply, stash_drop, stash_save};
4945
pub use tags::{get_tags, CommitTags, Tags};

asyncgit/src/sync/remotes/mod.rs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
//!
2+
3+
pub(crate) mod push;
4+
5+
use crate::{
6+
error::{Error, Result},
7+
sync::utils,
8+
};
9+
use git2::{FetchOptions, Repository};
10+
use push::remote_callbacks;
11+
use scopetime::scope_time;
12+
13+
/// origin
14+
pub const DEFAULT_REMOTE_NAME: &str = "origin";
15+
16+
///
17+
pub fn get_remotes(repo_path: &str) -> Result<Vec<String>> {
18+
scope_time!("get_remotes");
19+
20+
let repo = utils::repo(repo_path)?;
21+
let remotes = repo.remotes()?;
22+
let remotes: Vec<String> =
23+
remotes.iter().flatten().map(String::from).collect();
24+
25+
Ok(remotes)
26+
}
27+
28+
/// tries to find origin or the only remote that is defined if any
29+
/// in case of multiple remotes and none named *origin* we fail
30+
pub fn get_default_remote(repo_path: &str) -> Result<String> {
31+
let repo = utils::repo(repo_path)?;
32+
get_default_remote_in_repo(&repo)
33+
}
34+
35+
/// see `get_default_remote`
36+
pub(crate) fn get_default_remote_in_repo(
37+
repo: &Repository,
38+
) -> Result<String> {
39+
scope_time!("get_default_remote_in_repo");
40+
41+
let remotes = repo.remotes()?;
42+
43+
// if `origin` exists return that
44+
let found_origin = remotes.iter().any(|r| {
45+
r.map(|r| r == DEFAULT_REMOTE_NAME).unwrap_or_default()
46+
});
47+
if found_origin {
48+
return Ok(DEFAULT_REMOTE_NAME.into());
49+
}
50+
51+
//if only one remote exists pick that
52+
if remotes.len() == 1 {
53+
let first_remote = remotes
54+
.iter()
55+
.next()
56+
.flatten()
57+
.map(String::from)
58+
.ok_or_else(|| {
59+
Error::Generic("no remote found".into())
60+
})?;
61+
62+
return Ok(first_remote);
63+
}
64+
65+
//inconclusive
66+
Err(Error::NoDefaultRemoteFound)
67+
}
68+
69+
///
70+
pub fn fetch_origin(repo_path: &str, branch: &str) -> Result<usize> {
71+
scope_time!("fetch_origin");
72+
73+
let repo = utils::repo(repo_path)?;
74+
let mut remote =
75+
repo.find_remote(&get_default_remote_in_repo(&repo)?)?;
76+
77+
let mut options = FetchOptions::new();
78+
options.remote_callbacks(remote_callbacks(None, None));
79+
80+
remote.fetch(&[branch], Some(&mut options), None)?;
81+
82+
Ok(remote.stats().received_bytes())
83+
}
84+
85+
#[cfg(test)]
86+
mod tests {
87+
use super::*;
88+
use crate::sync::tests::debug_cmd_print;
89+
use tempfile::TempDir;
90+
91+
#[test]
92+
fn test_smoke() {
93+
let td = TempDir::new().unwrap();
94+
95+
debug_cmd_print(
96+
td.path().as_os_str().to_str().unwrap(),
97+
"git clone https://github.com/extrawurst/brewdump.git",
98+
);
99+
100+
let repo_path = td.path().join("brewdump");
101+
let repo_path = repo_path.as_os_str().to_str().unwrap();
102+
103+
let remotes = get_remotes(repo_path).unwrap();
104+
105+
assert_eq!(remotes, vec![String::from("origin")]);
106+
107+
fetch_origin(repo_path, "master").unwrap();
108+
}
109+
110+
#[test]
111+
fn test_default_remote() {
112+
let td = TempDir::new().unwrap();
113+
114+
debug_cmd_print(
115+
td.path().as_os_str().to_str().unwrap(),
116+
"git clone https://github.com/extrawurst/brewdump.git",
117+
);
118+
119+
debug_cmd_print(
120+
td.path().as_os_str().to_str().unwrap(),
121+
"cd brewdump && git remote add second https://github.com/extrawurst/brewdump.git",
122+
);
123+
124+
let repo_path = td.path().join("brewdump");
125+
let repo_path = repo_path.as_os_str().to_str().unwrap();
126+
127+
let remotes = get_remotes(repo_path).unwrap();
128+
129+
assert_eq!(
130+
remotes,
131+
vec![String::from("origin"), String::from("second")]
132+
);
133+
134+
let first = get_default_remote_in_repo(
135+
&utils::repo(repo_path).unwrap(),
136+
)
137+
.unwrap();
138+
assert_eq!(first, String::from("origin"));
139+
}
140+
141+
#[test]
142+
fn test_default_remote_out_of_order() {
143+
let td = TempDir::new().unwrap();
144+
145+
debug_cmd_print(
146+
td.path().as_os_str().to_str().unwrap(),
147+
"git clone https://github.com/extrawurst/brewdump.git",
148+
);
149+
150+
debug_cmd_print(
151+
td.path().as_os_str().to_str().unwrap(),
152+
"cd brewdump && git remote rename origin alternate",
153+
);
154+
155+
debug_cmd_print(
156+
td.path().as_os_str().to_str().unwrap(),
157+
"cd brewdump && git remote add origin https://github.com/extrawurst/brewdump.git",
158+
);
159+
160+
let repo_path = td.path().join("brewdump");
161+
let repo_path = repo_path.as_os_str().to_str().unwrap();
162+
163+
//NOTE: aparently remotes are not chronolically sorted but alphabetically
164+
let remotes = get_remotes(repo_path).unwrap();
165+
166+
assert_eq!(
167+
remotes,
168+
vec![String::from("alternate"), String::from("origin")]
169+
);
170+
171+
let first = get_default_remote_in_repo(
172+
&utils::repo(repo_path).unwrap(),
173+
)
174+
.unwrap();
175+
assert_eq!(first, String::from("origin"));
176+
}
177+
}

0 commit comments

Comments
 (0)