Skip to content

Commit 92f63d1

Browse files
committed
support fetching branch_infos async
1 parent 3fee481 commit 92f63d1

File tree

5 files changed

+129
-17
lines changed

5 files changed

+129
-17
lines changed

asyncgit/src/branches.rs

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use crate::{
2+
asyncjob::{AsyncJob, RunParams},
3+
error::Result,
4+
sync::{branch::get_branches_info, BranchInfo, RepoPath},
5+
AsyncGitNotification,
6+
};
7+
use std::sync::{Arc, Mutex};
8+
9+
enum JobState {
10+
Request {
11+
local_branches: bool,
12+
repo: RepoPath,
13+
},
14+
Response(Result<Vec<BranchInfo>>),
15+
}
16+
17+
///
18+
#[derive(Clone, Default)]
19+
pub struct AsyncBranchesJob {
20+
state: Arc<Mutex<Option<JobState>>>,
21+
}
22+
23+
///
24+
impl AsyncBranchesJob {
25+
///
26+
pub fn new(repo: RepoPath, local_branches: bool) -> Self {
27+
Self {
28+
state: Arc::new(Mutex::new(Some(JobState::Request {
29+
repo,
30+
local_branches,
31+
}))),
32+
}
33+
}
34+
35+
///
36+
pub fn result(&self) -> Option<Result<Vec<BranchInfo>>> {
37+
if let Ok(mut state) = self.state.lock() {
38+
if let Some(state) = state.take() {
39+
return match state {
40+
JobState::Request { .. } => None,
41+
JobState::Response(result) => Some(result),
42+
};
43+
}
44+
}
45+
46+
None
47+
}
48+
}
49+
50+
impl AsyncJob for AsyncBranchesJob {
51+
type Notification = AsyncGitNotification;
52+
type Progress = ();
53+
54+
fn run(
55+
&mut self,
56+
_params: RunParams<Self::Notification, Self::Progress>,
57+
) -> Result<Self::Notification> {
58+
if let Ok(mut state) = self.state.lock() {
59+
*state = state.take().map(|state| match state {
60+
JobState::Request {
61+
local_branches,
62+
repo,
63+
} => {
64+
let branches =
65+
get_branches_info(&repo, local_branches);
66+
67+
JobState::Response(branches)
68+
}
69+
JobState::Response(result) => {
70+
JobState::Response(result)
71+
}
72+
});
73+
}
74+
75+
Ok(AsyncGitNotification::Branches)
76+
}
77+
}

asyncgit/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
pub mod asyncjob;
2626
mod blame;
27+
mod branches;
2728
pub mod cached;
2829
mod commit_files;
2930
mod diff;
@@ -42,6 +43,7 @@ mod tags;
4243

4344
pub use crate::{
4445
blame::{AsyncBlame, BlameParams},
46+
branches::AsyncBranchesJob,
4547
commit_files::{AsyncCommitFiles, CommitFilesParams},
4648
diff::{AsyncDiff, DiffParams, DiffType},
4749
error::{Error, Result},
@@ -95,6 +97,8 @@ pub enum AsyncGitNotification {
9597
RemoteTags,
9698
///
9799
Fetch,
100+
///
101+
Branches,
98102
}
99103

100104
/// helper function to calculate the hash of an arbitrary type that implements the `Hash` trait

src/components/branchlist.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,7 @@ impl BranchListComponent {
364364
}
365365

366366
fn check_remotes(&mut self) {
367-
if !self.local {
367+
if !self.local && self.visible {
368368
self.has_remotes =
369369
get_branches_info(&self.repo.borrow(), false)
370370
.map(|branches| !branches.is_empty())

src/tabs/revlog.rs

+28-8
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use crate::{
1212
};
1313
use anyhow::Result;
1414
use asyncgit::{
15-
sync::{self, get_branches_info, CommitId, RepoPathRef},
16-
AsyncGitNotification, AsyncLog, AsyncTags, CommitFilesParams,
17-
FetchStatus,
15+
asyncjob::AsyncSingleJob,
16+
sync::{self, CommitId, RepoPathRef},
17+
AsyncBranchesJob, AsyncGitNotification, AsyncLog, AsyncTags,
18+
CommitFilesParams, FetchStatus,
1819
};
1920
use crossbeam_channel::Sender;
2021
use crossterm::event::Event;
@@ -35,6 +36,7 @@ pub struct Revlog {
3536
list: CommitList,
3637
git_log: AsyncLog,
3738
git_tags: AsyncTags,
39+
git_branches: AsyncSingleJob<AsyncBranchesJob>,
3840
queue: Queue,
3941
visible: bool,
4042
key_config: SharedKeyConfig,
@@ -71,6 +73,7 @@ impl Revlog {
7173
None,
7274
),
7375
git_tags: AsyncTags::new(repo.borrow().clone(), sender),
76+
git_branches: AsyncSingleJob::new(sender.clone()),
7477
visible: false,
7578
key_config,
7679
}
@@ -80,6 +83,7 @@ impl Revlog {
8083
pub fn any_work_pending(&self) -> bool {
8184
self.git_log.is_pending()
8285
|| self.git_tags.is_pending()
86+
|| self.git_branches.is_pending()
8387
|| self.commit_details.any_work_pending()
8488
}
8589

@@ -101,11 +105,6 @@ impl Revlog {
101105

102106
self.git_tags.request(Duration::from_secs(3), false)?;
103107

104-
self.list.set_branches(get_branches_info(
105-
&self.repo.borrow(),
106-
true,
107-
)?);
108-
109108
if self.commit_details.is_visible() {
110109
let commit = self.selected_commit();
111110
let tags = self.selected_commit_tags(&commit);
@@ -135,6 +134,21 @@ impl Revlog {
135134
self.update()?;
136135
}
137136
}
137+
AsyncGitNotification::Branches => {
138+
if let Some(branches) =
139+
self.git_branches.take_last()
140+
{
141+
if let Some(Ok(branches)) = branches.result()
142+
{
143+
log::info!(
144+
"branches: {}",
145+
branches.len()
146+
);
147+
self.list.set_branches(branches);
148+
self.update()?;
149+
}
150+
}
151+
}
138152
_ => (),
139153
}
140154
}
@@ -447,6 +461,12 @@ impl Component for Revlog {
447461
fn show(&mut self) -> Result<()> {
448462
self.visible = true;
449463
self.list.clear();
464+
465+
self.git_branches.spawn(AsyncBranchesJob::new(
466+
self.repo.borrow().clone(),
467+
true,
468+
));
469+
450470
self.update()?;
451471

452472
Ok(())

src/tabs/status.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ use crate::{
1414
};
1515
use anyhow::Result;
1616
use asyncgit::{
17+
asyncjob::AsyncSingleJob,
1718
cached,
1819
sync::{
1920
self, status::StatusType, RepoPath, RepoPathRef, RepoState,
2021
},
2122
sync::{BranchCompare, CommitId},
22-
AsyncDiff, AsyncGitNotification, AsyncStatus, DiffParams,
23-
DiffType, PushType, StatusParams,
23+
AsyncBranchesJob, AsyncDiff, AsyncGitNotification, AsyncStatus,
24+
DiffParams, DiffType, PushType, StatusParams,
2425
};
2526
use crossbeam_channel::Sender;
2627
use crossterm::event::Event;
@@ -73,6 +74,7 @@ pub struct Status {
7374
git_status_stage: AsyncStatus,
7475
git_branch_state: Option<BranchCompare>,
7576
git_branch_name: cached::BranchName,
77+
git_branches: AsyncSingleJob<AsyncBranchesJob>,
7678
queue: Queue,
7779
git_action_executed: bool,
7880
options: SharedOptions,
@@ -203,6 +205,7 @@ impl Status {
203205
repo_clone,
204206
sender.clone(),
205207
),
208+
git_branches: AsyncSingleJob::new(sender.clone()),
206209
git_action_executed: false,
207210
git_branch_state: None,
208211
git_branch_name: cached::BranchName::new(repo.clone()),
@@ -424,14 +427,22 @@ impl Status {
424427
self.git_diff.is_pending()
425428
|| self.git_status_stage.is_pending()
426429
|| self.git_status_workdir.is_pending()
430+
|| self.git_branches.is_pending()
427431
}
428432

429433
fn check_remotes(&mut self) {
430-
//TODO: make get_branches_info async
431-
self.has_remotes =
432-
sync::get_branches_info(&self.repo.borrow(), false)
433-
.map(|branches| !branches.is_empty())
434-
.unwrap_or(false);
434+
self.has_remotes = false;
435+
436+
if let Some(result) = self.git_branches.take_last() {
437+
if let Some(Ok(branches)) = result.result() {
438+
self.has_remotes = !branches.is_empty();
439+
}
440+
} else {
441+
self.git_branches.spawn(AsyncBranchesJob::new(
442+
self.repo.borrow().clone(),
443+
false,
444+
));
445+
}
435446
}
436447

437448
///
@@ -442,6 +453,7 @@ impl Status {
442453
match ev {
443454
AsyncGitNotification::Diff => self.update_diff()?,
444455
AsyncGitNotification::Status => self.update_status()?,
456+
AsyncGitNotification::Branches => self.check_remotes(),
445457
AsyncGitNotification::Push
446458
| AsyncGitNotification::Pull
447459
| AsyncGitNotification::CommitFiles => {
@@ -461,7 +473,6 @@ impl Status {
461473
self.index_wd.set_items(&workdir_status.items)?;
462474

463475
self.update_diff()?;
464-
self.check_remotes();
465476

466477
if self.git_action_executed {
467478
self.git_action_executed = false;

0 commit comments

Comments
 (0)