mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 08:58:21 +00:00
visualize outgoing/incoming changes (#364)
This commit is contained in:
parent
a2b26c30dc
commit
4ee4432f16
4 changed files with 91 additions and 9 deletions
|
|
@ -12,11 +12,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- added gitui to [chocolatey](https://chocolatey.org/packages/gitui) on windows by [@nils-a](https://github.com/nils-a)
|
||||
- push to remote ([#265](https://github.com/extrawurst/gitui/issues/265)) ([#267](https://github.com/extrawurst/gitui/issues/267))
|
||||
|
||||

|
||||

|
||||
|
||||
- incoming/outgoing commits to upstream ([#362](https://github.com/extrawurst/gitui/issues/362))
|
||||
- new branch list popup incl. checkout/delete/rename [[@WizardOhio24](https://github.com/WizardOhio24)] ([#303](https://github.com/extrawurst/gitui/issues/303)) ([#323](https://github.com/extrawurst/gitui/issues/323))
|
||||
|
||||

|
||||

|
||||
|
||||
- scrollbar in long commit messages [[@timaliberdov](https://github.com/timaliberdov)] ([#308](https://github.com/extrawurst/gitui/issues/308))
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@
|
|||
|
||||
use crate::{
|
||||
error::{Error, Result},
|
||||
sync::utils,
|
||||
sync::{utils, CommitId},
|
||||
};
|
||||
use git2::BranchType;
|
||||
use scopetime::scope_time;
|
||||
use utils::get_head_repo;
|
||||
|
||||
use super::CommitId;
|
||||
|
||||
/// returns the branch-name head is currently pointing to
|
||||
/// this might be expensive, see `cached::BranchName`
|
||||
pub(crate) fn get_branch_name(repo_path: &str) -> Result<String> {
|
||||
|
|
@ -79,6 +77,39 @@ pub fn get_branches_to_display(
|
|||
Ok(branches_for_display)
|
||||
}
|
||||
|
||||
///
|
||||
#[derive(Debug, Default)]
|
||||
pub struct BranchCompare {
|
||||
///
|
||||
pub ahead: usize,
|
||||
///
|
||||
pub behind: usize,
|
||||
}
|
||||
|
||||
///
|
||||
pub fn branch_compare_upstream(
|
||||
repo_path: &str,
|
||||
branch: &str,
|
||||
) -> Result<BranchCompare> {
|
||||
scope_time!("branch_compare_upstream");
|
||||
|
||||
let repo = utils::repo(repo_path)?;
|
||||
|
||||
let branch = repo.find_branch(branch, BranchType::Local)?;
|
||||
let upstream = branch.upstream()?;
|
||||
|
||||
let branch_commit =
|
||||
branch.into_reference().peel_to_commit()?.id();
|
||||
|
||||
let upstream_commit =
|
||||
upstream.into_reference().peel_to_commit()?.id();
|
||||
|
||||
let (ahead, behind) =
|
||||
repo.graph_ahead_behind(branch_commit, upstream_commit)?;
|
||||
|
||||
Ok(BranchCompare { ahead, behind })
|
||||
}
|
||||
|
||||
/// Modify HEAD to point to a branch then checkout head, does not work if there are uncommitted changes
|
||||
pub fn checkout_branch(
|
||||
repo_path: &str,
|
||||
|
|
|
|||
|
|
@ -20,8 +20,9 @@ pub mod utils;
|
|||
|
||||
pub(crate) use branch::get_branch_name;
|
||||
pub use branch::{
|
||||
checkout_branch, create_branch, delete_branch,
|
||||
get_branches_to_display, rename_branch, BranchForDisplay,
|
||||
branch_compare_upstream, checkout_branch, create_branch,
|
||||
delete_branch, get_branches_to_display, rename_branch,
|
||||
BranchCompare, BranchForDisplay,
|
||||
};
|
||||
pub use commit::{amend, commit, tag};
|
||||
pub use commit_details::{
|
||||
|
|
|
|||
|
|
@ -12,13 +12,17 @@ use crate::{
|
|||
};
|
||||
use anyhow::Result;
|
||||
use asyncgit::{
|
||||
sync::BranchCompare,
|
||||
sync::{self, status::StatusType},
|
||||
AsyncDiff, AsyncNotification, AsyncStatus, DiffParams, DiffType,
|
||||
StatusParams, CWD,
|
||||
};
|
||||
use crossbeam_channel::Sender;
|
||||
use crossterm::event::Event;
|
||||
use tui::layout::{Constraint, Direction, Layout};
|
||||
use tui::{
|
||||
layout::{Alignment, Constraint, Direction, Layout},
|
||||
widgets::Paragraph,
|
||||
};
|
||||
|
||||
///
|
||||
#[derive(PartialEq)]
|
||||
|
|
@ -45,6 +49,7 @@ pub struct Status {
|
|||
git_diff: AsyncDiff,
|
||||
git_status_workdir: AsyncStatus,
|
||||
git_status_stage: AsyncStatus,
|
||||
git_branch_state: BranchCompare,
|
||||
queue: Queue,
|
||||
git_action_executed: bool,
|
||||
key_config: SharedKeyConfig,
|
||||
|
|
@ -95,6 +100,7 @@ impl DrawableComponent for Status {
|
|||
self.index_wd.draw(f, left_chunks[0])?;
|
||||
self.index.draw(f, left_chunks[1])?;
|
||||
self.diff.draw(f, chunks[1])?;
|
||||
self.draw_branch_state(f, &left_chunks);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -141,10 +147,38 @@ impl Status {
|
|||
git_status_workdir: AsyncStatus::new(sender.clone()),
|
||||
git_status_stage: AsyncStatus::new(sender.clone()),
|
||||
git_action_executed: false,
|
||||
git_branch_state: BranchCompare::default(),
|
||||
key_config,
|
||||
}
|
||||
}
|
||||
|
||||
fn draw_branch_state<B: tui::backend::Backend>(
|
||||
&self,
|
||||
f: &mut tui::Frame<B>,
|
||||
chunks: &[tui::layout::Rect],
|
||||
) {
|
||||
let w = Paragraph::new(format!(
|
||||
"\u{2191}{} \u{2193}{}",
|
||||
self.git_branch_state.ahead, self.git_branch_state.behind
|
||||
))
|
||||
.alignment(Alignment::Right);
|
||||
|
||||
let mut rect = if self.index_wd.focused() {
|
||||
let mut rect = chunks[0];
|
||||
rect.y += rect.height.saturating_sub(1);
|
||||
rect
|
||||
} else {
|
||||
chunks[1]
|
||||
};
|
||||
|
||||
rect.x += 1;
|
||||
rect.width = rect.width.saturating_sub(2);
|
||||
rect.height =
|
||||
rect.height.saturating_sub(rect.height.saturating_sub(1));
|
||||
|
||||
f.render_widget(w, rect);
|
||||
}
|
||||
|
||||
fn can_focus_diff(&self) -> bool {
|
||||
match self.focus {
|
||||
Focus::WorkDir => self.index_wd.is_file_seleted(),
|
||||
|
|
@ -216,6 +250,7 @@ impl Status {
|
|||
.fetch(StatusParams::new(StatusType::Stage, true))?;
|
||||
|
||||
self.index_wd.update()?;
|
||||
self.check_branch_state();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
@ -356,6 +391,20 @@ impl Status {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_branch_state(&mut self) {
|
||||
self.git_branch_state = self.index_wd.branch_name().map_or(
|
||||
BranchCompare::default(),
|
||||
|branch| {
|
||||
sync::branch_compare_upstream(CWD, branch.as_str())
|
||||
.unwrap_or_default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
const fn can_push(&self) -> bool {
|
||||
self.git_branch_state.ahead > 0
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for Status {
|
||||
|
|
@ -381,7 +430,7 @@ impl Component for Status {
|
|||
|
||||
out.push(CommandInfo::new(
|
||||
strings::commands::status_push(&self.key_config),
|
||||
self.index_wd.branch_name().is_some(),
|
||||
self.can_push(),
|
||||
true,
|
||||
));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue