Skip to content

Commit 17de5a9

Browse files
author
Stephan Dilly
authored
Test push progress (#272)
1 parent 56959e6 commit 17de5a9

File tree

15 files changed

+392
-76
lines changed

15 files changed

+392
-76
lines changed

Cargo.lock

Lines changed: 2 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

asyncgit/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ keywords = ["git"]
1313

1414
[dependencies]
1515
scopetime = { path = "../scopetime", version = "0.1" }
16-
git2 = { version = "0.13", features = ["vendored-openssl"] }
16+
# git2 = { version = "0.13", features = ["vendored-openssl"] }
17+
git2 = { git="https://github.com/rust-lang/git2-rs.git", rev="5fddf7e04dc76e70873569ca9f1de3287ec3edda", features = ["vendored-openssl"] }
1718
rayon-core = "1.8"
1819
crossbeam-channel = "0.4"
1920
log = "0.4"

asyncgit/src/diff.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ pub struct AsyncDiff {
5252

5353
impl AsyncDiff {
5454
///
55-
pub fn new(sender: Sender<AsyncNotification>) -> Self {
55+
pub fn new(sender: &Sender<AsyncNotification>) -> Self {
5656
Self {
5757
current: Arc::new(Mutex::new(Request(0, None))),
5858
last: Arc::new(Mutex::new(None)),
59-
sender,
59+
sender: sender.clone(),
6060
pending: Arc::new(AtomicUsize::new(0)),
6161
}
6262
}

asyncgit/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub mod cached;
1111
mod commit_files;
1212
mod diff;
1313
mod error;
14+
mod push;
1415
mod revlog;
1516
mod status;
1617
pub mod sync;
@@ -19,6 +20,7 @@ mod tags;
1920
pub use crate::{
2021
commit_files::AsyncCommitFiles,
2122
diff::{AsyncDiff, DiffParams, DiffType},
23+
push::{AsyncPush, PushRequest},
2224
revlog::{AsyncLog, FetchStatus},
2325
status::{AsyncStatus, StatusParams},
2426
sync::{
@@ -47,6 +49,8 @@ pub enum AsyncNotification {
4749
CommitFiles,
4850
///
4951
Tags,
52+
///
53+
Push,
5054
}
5155

5256
/// current working director `./`

asyncgit/src/push.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use crate::{
2+
error::{Error, Result},
3+
sync, AsyncNotification, CWD,
4+
};
5+
use crossbeam_channel::Sender;
6+
use std::sync::{Arc, Mutex};
7+
8+
#[derive(Clone, Debug)]
9+
enum PushStates {
10+
None,
11+
// Packing,
12+
// Pushing(usize, usize),
13+
}
14+
15+
impl Default for PushStates {
16+
fn default() -> Self {
17+
PushStates::None
18+
}
19+
}
20+
21+
///
22+
#[derive(Default, Clone, Debug)]
23+
pub struct PushRequest {
24+
///
25+
pub remote: String,
26+
///
27+
pub branch: String,
28+
}
29+
30+
#[derive(Default, Clone, Debug)]
31+
struct PushState {
32+
request: PushRequest,
33+
state: PushStates,
34+
}
35+
36+
///
37+
pub struct AsyncPush {
38+
state: Arc<Mutex<Option<PushState>>>,
39+
last_result: Arc<Mutex<Option<String>>>,
40+
sender: Sender<AsyncNotification>,
41+
}
42+
43+
impl AsyncPush {
44+
///
45+
pub fn new(sender: &Sender<AsyncNotification>) -> Self {
46+
Self {
47+
state: Arc::new(Mutex::new(None)),
48+
last_result: Arc::new(Mutex::new(None)),
49+
sender: sender.clone(),
50+
}
51+
}
52+
53+
///
54+
pub fn is_pending(&self) -> Result<bool> {
55+
let state = self.state.lock()?;
56+
Ok(state.is_some())
57+
}
58+
59+
///
60+
pub fn last_result(&self) -> Result<Option<String>> {
61+
let res = self.last_result.lock()?;
62+
Ok(res.clone())
63+
}
64+
65+
///
66+
pub fn request(&mut self, params: PushRequest) -> Result<()> {
67+
log::trace!("request");
68+
69+
if self.is_pending()? {
70+
return Ok(());
71+
}
72+
73+
self.set_request(&params)?;
74+
75+
let arc_state = Arc::clone(&self.state);
76+
let arc_res = Arc::clone(&self.last_result);
77+
let sender = self.sender.clone();
78+
79+
rayon_core::spawn(move || {
80+
//TODO: use channels to communicate progress
81+
let res = sync::push_origin(
82+
CWD,
83+
params.remote.as_str(),
84+
params.branch.as_str(),
85+
);
86+
87+
Self::set_result(arc_res, res).expect("result error");
88+
89+
Self::clear_request(arc_state).expect("clear error");
90+
91+
sender
92+
.send(AsyncNotification::Push)
93+
.expect("error sending push");
94+
});
95+
96+
Ok(())
97+
}
98+
99+
fn set_request(&self, params: &PushRequest) -> Result<()> {
100+
let mut state = self.state.lock()?;
101+
102+
if state.is_some() {
103+
return Err(Error::Generic("pending request".into()));
104+
}
105+
106+
*state = Some(PushState {
107+
request: params.clone(),
108+
..PushState::default()
109+
});
110+
111+
Ok(())
112+
}
113+
114+
fn clear_request(
115+
state: Arc<Mutex<Option<PushState>>>,
116+
) -> Result<()> {
117+
let mut state = state.lock()?;
118+
119+
*state = None;
120+
121+
Ok(())
122+
}
123+
124+
fn set_result(
125+
arc_result: Arc<Mutex<Option<String>>>,
126+
res: Result<()>,
127+
) -> Result<()> {
128+
let mut last_res = arc_result.lock()?;
129+
130+
*last_res = match res {
131+
Ok(_) => None,
132+
Err(e) => {
133+
log::error!("push error: {}", e);
134+
Some(e.to_string())
135+
}
136+
};
137+
138+
Ok(())
139+
}
140+
}

asyncgit/src/sync/mod.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ pub use hooks::{hooks_commit_msg, hooks_post_commit, HookResult};
3030
pub use hunks::{reset_hunk, stage_hunk, unstage_hunk};
3131
pub use ignore::add_to_ignore;
3232
pub use logwalker::LogWalker;
33-
pub use remotes::{
34-
fetch_origin, get_remotes, push_origin, remote_push_master,
35-
};
33+
pub use remotes::{fetch_origin, get_remotes, push_origin};
3634
pub use reset::{reset_stage, reset_workdir};
3735
pub use stash::{get_stashes, stash_apply, stash_drop, stash_save};
3836
pub use tags::{get_tags, CommitTags, Tags};

asyncgit/src/sync/remotes.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,6 @@ pub fn get_remotes(repo_path: &str) -> Result<Vec<String>> {
1616
Ok(remotes)
1717
}
1818

19-
///
20-
pub fn remote_push_master(repo_path: &str) -> Result<()> {
21-
scope_time!("remote_push_master");
22-
23-
let repo = utils::repo(repo_path)?;
24-
let mut remote = repo.find_remote("origin")?;
25-
26-
remote.push(&["refs/heads/master"], None)?;
27-
28-
Ok(())
29-
}
30-
3119
///
3220
pub fn fetch_origin(repo_path: &str, branch: &str) -> Result<usize> {
3321
scope_time!("remote_fetch_master");
@@ -44,14 +32,19 @@ pub fn fetch_origin(repo_path: &str, branch: &str) -> Result<usize> {
4432
}
4533

4634
///
47-
pub fn push_origin(repo_path: &str, branch: &str) -> Result<()> {
35+
pub fn push_origin(
36+
repo_path: &str,
37+
remote: &str,
38+
branch: &str,
39+
) -> Result<()> {
4840
scope_time!("push_origin");
4941

5042
let repo = utils::repo(repo_path)?;
51-
let mut remote = repo.find_remote("origin")?;
43+
let mut remote = repo.find_remote(remote)?;
5244

5345
let mut options = PushOptions::new();
5446
options.remote_callbacks(remote_callbacks());
47+
options.packbuilder_parallelism(0);
5548

5649
remote.push(&[branch], Some(&mut options))?;
5750

@@ -60,6 +53,17 @@ pub fn push_origin(repo_path: &str, branch: &str) -> Result<()> {
6053

6154
fn remote_callbacks<'a>() -> RemoteCallbacks<'a> {
6255
let mut callbacks = RemoteCallbacks::new();
56+
callbacks.push_transfer_progress(|progress, total, bytes| {
57+
log::debug!(
58+
"progress: {}/{} ({} B)",
59+
progress,
60+
total,
61+
bytes,
62+
);
63+
});
64+
callbacks.pack_progress(|stage, current, total| {
65+
log::debug!("packing: {:?} - {}/{}", stage, current, total);
66+
});
6367
callbacks.credentials(|url, username_from_url, allowed_types| {
6468
log::debug!(
6569
"creds: '{}' {:?} ({:?})",

0 commit comments

Comments
 (0)