mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 17:08:21 +00:00
support fetching branch_infos async
This commit is contained in:
parent
3fee481e8d
commit
92f63d107c
5 changed files with 129 additions and 17 deletions
77
asyncgit/src/branches.rs
Normal file
77
asyncgit/src/branches.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
use crate::{
|
||||
asyncjob::{AsyncJob, RunParams},
|
||||
error::Result,
|
||||
sync::{branch::get_branches_info, BranchInfo, RepoPath},
|
||||
AsyncGitNotification,
|
||||
};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
enum JobState {
|
||||
Request {
|
||||
local_branches: bool,
|
||||
repo: RepoPath,
|
||||
},
|
||||
Response(Result<Vec<BranchInfo>>),
|
||||
}
|
||||
|
||||
///
|
||||
#[derive(Clone, Default)]
|
||||
pub struct AsyncBranchesJob {
|
||||
state: Arc<Mutex<Option<JobState>>>,
|
||||
}
|
||||
|
||||
///
|
||||
impl AsyncBranchesJob {
|
||||
///
|
||||
pub fn new(repo: RepoPath, local_branches: bool) -> Self {
|
||||
Self {
|
||||
state: Arc::new(Mutex::new(Some(JobState::Request {
|
||||
repo,
|
||||
local_branches,
|
||||
}))),
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
pub fn result(&self) -> Option<Result<Vec<BranchInfo>>> {
|
||||
if let Ok(mut state) = self.state.lock() {
|
||||
if let Some(state) = state.take() {
|
||||
return match state {
|
||||
JobState::Request { .. } => None,
|
||||
JobState::Response(result) => Some(result),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncJob for AsyncBranchesJob {
|
||||
type Notification = AsyncGitNotification;
|
||||
type Progress = ();
|
||||
|
||||
fn run(
|
||||
&mut self,
|
||||
_params: RunParams<Self::Notification, Self::Progress>,
|
||||
) -> Result<Self::Notification> {
|
||||
if let Ok(mut state) = self.state.lock() {
|
||||
*state = state.take().map(|state| match state {
|
||||
JobState::Request {
|
||||
local_branches,
|
||||
repo,
|
||||
} => {
|
||||
let branches =
|
||||
get_branches_info(&repo, local_branches);
|
||||
|
||||
JobState::Response(branches)
|
||||
}
|
||||
JobState::Response(result) => {
|
||||
JobState::Response(result)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Ok(AsyncGitNotification::Branches)
|
||||
}
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
pub mod asyncjob;
|
||||
mod blame;
|
||||
mod branches;
|
||||
pub mod cached;
|
||||
mod commit_files;
|
||||
mod diff;
|
||||
|
|
@ -42,6 +43,7 @@ mod tags;
|
|||
|
||||
pub use crate::{
|
||||
blame::{AsyncBlame, BlameParams},
|
||||
branches::AsyncBranchesJob,
|
||||
commit_files::{AsyncCommitFiles, CommitFilesParams},
|
||||
diff::{AsyncDiff, DiffParams, DiffType},
|
||||
error::{Error, Result},
|
||||
|
|
@ -95,6 +97,8 @@ pub enum AsyncGitNotification {
|
|||
RemoteTags,
|
||||
///
|
||||
Fetch,
|
||||
///
|
||||
Branches,
|
||||
}
|
||||
|
||||
/// helper function to calculate the hash of an arbitrary type that implements the `Hash` trait
|
||||
|
|
|
|||
|
|
@ -364,7 +364,7 @@ impl BranchListComponent {
|
|||
}
|
||||
|
||||
fn check_remotes(&mut self) {
|
||||
if !self.local {
|
||||
if !self.local && self.visible {
|
||||
self.has_remotes =
|
||||
get_branches_info(&self.repo.borrow(), false)
|
||||
.map(|branches| !branches.is_empty())
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ use crate::{
|
|||
};
|
||||
use anyhow::Result;
|
||||
use asyncgit::{
|
||||
sync::{self, get_branches_info, CommitId, RepoPathRef},
|
||||
AsyncGitNotification, AsyncLog, AsyncTags, CommitFilesParams,
|
||||
FetchStatus,
|
||||
asyncjob::AsyncSingleJob,
|
||||
sync::{self, CommitId, RepoPathRef},
|
||||
AsyncBranchesJob, AsyncGitNotification, AsyncLog, AsyncTags,
|
||||
CommitFilesParams, FetchStatus,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use crossterm::event::Event;
|
||||
|
|
@ -35,6 +36,7 @@ pub struct Revlog {
|
|||
list: CommitList,
|
||||
git_log: AsyncLog,
|
||||
git_tags: AsyncTags,
|
||||
git_branches: AsyncSingleJob<AsyncBranchesJob>,
|
||||
queue: Queue,
|
||||
visible: bool,
|
||||
key_config: SharedKeyConfig,
|
||||
|
|
@ -71,6 +73,7 @@ impl Revlog {
|
|||
None,
|
||||
),
|
||||
git_tags: AsyncTags::new(repo.borrow().clone(), sender),
|
||||
git_branches: AsyncSingleJob::new(sender.clone()),
|
||||
visible: false,
|
||||
key_config,
|
||||
}
|
||||
|
|
@ -80,6 +83,7 @@ impl Revlog {
|
|||
pub fn any_work_pending(&self) -> bool {
|
||||
self.git_log.is_pending()
|
||||
|| self.git_tags.is_pending()
|
||||
|| self.git_branches.is_pending()
|
||||
|| self.commit_details.any_work_pending()
|
||||
}
|
||||
|
||||
|
|
@ -101,11 +105,6 @@ impl Revlog {
|
|||
|
||||
self.git_tags.request(Duration::from_secs(3), false)?;
|
||||
|
||||
self.list.set_branches(get_branches_info(
|
||||
&self.repo.borrow(),
|
||||
true,
|
||||
)?);
|
||||
|
||||
if self.commit_details.is_visible() {
|
||||
let commit = self.selected_commit();
|
||||
let tags = self.selected_commit_tags(&commit);
|
||||
|
|
@ -135,6 +134,21 @@ impl Revlog {
|
|||
self.update()?;
|
||||
}
|
||||
}
|
||||
AsyncGitNotification::Branches => {
|
||||
if let Some(branches) =
|
||||
self.git_branches.take_last()
|
||||
{
|
||||
if let Some(Ok(branches)) = branches.result()
|
||||
{
|
||||
log::info!(
|
||||
"branches: {}",
|
||||
branches.len()
|
||||
);
|
||||
self.list.set_branches(branches);
|
||||
self.update()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
|
@ -447,6 +461,12 @@ impl Component for Revlog {
|
|||
fn show(&mut self) -> Result<()> {
|
||||
self.visible = true;
|
||||
self.list.clear();
|
||||
|
||||
self.git_branches.spawn(AsyncBranchesJob::new(
|
||||
self.repo.borrow().clone(),
|
||||
true,
|
||||
));
|
||||
|
||||
self.update()?;
|
||||
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@ use crate::{
|
|||
};
|
||||
use anyhow::Result;
|
||||
use asyncgit::{
|
||||
asyncjob::AsyncSingleJob,
|
||||
cached,
|
||||
sync::{
|
||||
self, status::StatusType, RepoPath, RepoPathRef, RepoState,
|
||||
},
|
||||
sync::{BranchCompare, CommitId},
|
||||
AsyncDiff, AsyncGitNotification, AsyncStatus, DiffParams,
|
||||
DiffType, PushType, StatusParams,
|
||||
AsyncBranchesJob, AsyncDiff, AsyncGitNotification, AsyncStatus,
|
||||
DiffParams, DiffType, PushType, StatusParams,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use crossterm::event::Event;
|
||||
|
|
@ -73,6 +74,7 @@ pub struct Status {
|
|||
git_status_stage: AsyncStatus,
|
||||
git_branch_state: Option<BranchCompare>,
|
||||
git_branch_name: cached::BranchName,
|
||||
git_branches: AsyncSingleJob<AsyncBranchesJob>,
|
||||
queue: Queue,
|
||||
git_action_executed: bool,
|
||||
options: SharedOptions,
|
||||
|
|
@ -203,6 +205,7 @@ impl Status {
|
|||
repo_clone,
|
||||
sender.clone(),
|
||||
),
|
||||
git_branches: AsyncSingleJob::new(sender.clone()),
|
||||
git_action_executed: false,
|
||||
git_branch_state: None,
|
||||
git_branch_name: cached::BranchName::new(repo.clone()),
|
||||
|
|
@ -424,14 +427,22 @@ impl Status {
|
|||
self.git_diff.is_pending()
|
||||
|| self.git_status_stage.is_pending()
|
||||
|| self.git_status_workdir.is_pending()
|
||||
|| self.git_branches.is_pending()
|
||||
}
|
||||
|
||||
fn check_remotes(&mut self) {
|
||||
//TODO: make get_branches_info async
|
||||
self.has_remotes =
|
||||
sync::get_branches_info(&self.repo.borrow(), false)
|
||||
.map(|branches| !branches.is_empty())
|
||||
.unwrap_or(false);
|
||||
self.has_remotes = false;
|
||||
|
||||
if let Some(result) = self.git_branches.take_last() {
|
||||
if let Some(Ok(branches)) = result.result() {
|
||||
self.has_remotes = !branches.is_empty();
|
||||
}
|
||||
} else {
|
||||
self.git_branches.spawn(AsyncBranchesJob::new(
|
||||
self.repo.borrow().clone(),
|
||||
false,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
|
|
@ -442,6 +453,7 @@ impl Status {
|
|||
match ev {
|
||||
AsyncGitNotification::Diff => self.update_diff()?,
|
||||
AsyncGitNotification::Status => self.update_status()?,
|
||||
AsyncGitNotification::Branches => self.check_remotes(),
|
||||
AsyncGitNotification::Push
|
||||
| AsyncGitNotification::Pull
|
||||
| AsyncGitNotification::CommitFiles => {
|
||||
|
|
@ -461,7 +473,6 @@ impl Status {
|
|||
self.index_wd.set_items(&workdir_status.items)?;
|
||||
|
||||
self.update_diff()?;
|
||||
self.check_remotes();
|
||||
|
||||
if self.git_action_executed {
|
||||
self.git_action_executed = false;
|
||||
|
|
|
|||
Loading…
Reference in a new issue