mirror of
https://github.com/gitui-org/gitui
synced 2026-05-23 00:48:35 +00:00
less libgit calls and added optional timing logging for benchmarking
This commit is contained in:
parent
55e9fe643b
commit
cb247b9e7f
11 changed files with 137 additions and 24 deletions
8
Cargo.lock
generated
8
Cargo.lock
generated
|
|
@ -234,6 +234,7 @@ dependencies = [
|
|||
"git2",
|
||||
"itertools 0.9.0",
|
||||
"log",
|
||||
"scopetime",
|
||||
"simplelog",
|
||||
"tui",
|
||||
]
|
||||
|
|
@ -522,6 +523,13 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scopetime"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.1.13"
|
||||
|
|
|
|||
|
|
@ -14,4 +14,9 @@ itertools = "0.9"
|
|||
log = "0.4"
|
||||
simplelog = "0.7"
|
||||
dirs = "2.0"
|
||||
tui = { version = "0.8", default-features = false, features = ['crossterm'] }
|
||||
scopetime = { path = "./scopetime" }
|
||||
tui = { version = "0.8", default-features=false, features = ['crossterm'] }
|
||||
|
||||
[features]
|
||||
default=[]
|
||||
timing=["scopetime/enabled"]
|
||||
|
|
|
|||
|
|
@ -37,12 +37,9 @@ gitui
|
|||
* [x] inspect diffs
|
||||
* [x] commit
|
||||
* [x] [input polling in thread](assets/perf_compare.jpg)
|
||||
* [x] only ask git when necessary. maybe in a worker thread?
|
||||
* [ ] show content of new files
|
||||
* [ ] put libgit calls in threadpool
|
||||
* [ ] show content of new unstaged files
|
||||
* [ ] discard untracked files (remove)
|
||||
* [ ] use [notify](https://crates.io/crates/notify) to watch git
|
||||
* [ ] log view
|
||||
* [ ] stashing support
|
||||
* [ ] (un)staging selected hunks
|
||||
|
||||
# resources (quick links)
|
||||
|
|
|
|||
12
scopetime/Cargo.toml
Normal file
12
scopetime/Cargo.toml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "scopetime"
|
||||
version = "0.1.0"
|
||||
authors = ["Stephan Dilly <dilly.stephan@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
|
||||
[features]
|
||||
default=[]
|
||||
enabled=[]
|
||||
64
scopetime/src/lib.rs
Normal file
64
scopetime/src/lib.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
use log::trace;
|
||||
use std::time::Instant;
|
||||
|
||||
///
|
||||
pub struct ScopeTimeLog<'a> {
|
||||
title: &'a str,
|
||||
mod_path: &'a str,
|
||||
file: &'a str,
|
||||
line: u32,
|
||||
time: Instant,
|
||||
}
|
||||
|
||||
///
|
||||
impl<'a> ScopeTimeLog<'a> {
|
||||
///
|
||||
pub fn new(
|
||||
mod_path: &'a str,
|
||||
title: &'a str,
|
||||
file: &'a str,
|
||||
line: u32,
|
||||
) -> Self {
|
||||
Self {
|
||||
title,
|
||||
mod_path,
|
||||
file,
|
||||
line,
|
||||
time: Instant::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for ScopeTimeLog<'a> {
|
||||
fn drop(&mut self) {
|
||||
trace!(
|
||||
"scopetime: {:?} ms [{}::{}] @{}:{}",
|
||||
self.time.elapsed().as_millis(),
|
||||
self.mod_path,
|
||||
self.title,
|
||||
self.file,
|
||||
self.line,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "enabled")]
|
||||
#[macro_export]
|
||||
macro_rules! scope_time {
|
||||
($target:literal) => {
|
||||
//TODO: add module_path!() aswell?
|
||||
#[allow(unused_variables)]
|
||||
let time = $crate::ScopeTimeLog::new(
|
||||
module_path!(),
|
||||
$target,
|
||||
file!(),
|
||||
line!(),
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enabled"))]
|
||||
#[macro_export]
|
||||
macro_rules! scope_time {
|
||||
($target:literal) => {};
|
||||
}
|
||||
|
|
@ -191,7 +191,8 @@ impl App {
|
|||
|
||||
///
|
||||
pub fn update(&mut self) {
|
||||
trace!("update");
|
||||
trace!("app::update");
|
||||
|
||||
self.index.update();
|
||||
self.index_wd.update();
|
||||
self.update_diff();
|
||||
|
|
@ -230,6 +231,11 @@ impl App {
|
|||
fn commands(&self) -> Vec<CommandInfo> {
|
||||
let mut res = Vec::new();
|
||||
if !self.commit.is_visible() {
|
||||
res.push(CommandInfo {
|
||||
name: strings::COMMIT_CMD_OPEN.to_string(),
|
||||
enabled: !self.index.is_empty(),
|
||||
});
|
||||
|
||||
if self.index_wd.focused() {
|
||||
let some_selection =
|
||||
self.index_wd.selection().is_some();
|
||||
|
|
|
|||
|
|
@ -44,10 +44,7 @@ impl Component for CommitComponent {
|
|||
|
||||
fn commands(&self) -> Vec<CommandInfo> {
|
||||
if !self.visible {
|
||||
vec![CommandInfo {
|
||||
name: strings::COMMIT_CMD_OPEN.to_string(),
|
||||
enabled: !git_utils::index_empty(),
|
||||
}]
|
||||
vec![]
|
||||
} else {
|
||||
vec![
|
||||
CommandInfo {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
use crate::components::CommandInfo;
|
||||
use crate::components::Component;
|
||||
use crate::components::{CommandInfo, Component};
|
||||
use crate::{
|
||||
git_status::{self, StatusItem},
|
||||
git_status::{self, StatusItem, StatusItemType},
|
||||
tui_utils,
|
||||
};
|
||||
use crossterm::event::{Event, KeyCode};
|
||||
use git2::StatusShow;
|
||||
use git_status::StatusItemType;
|
||||
use std::{borrow::Cow, cmp};
|
||||
use tui::{
|
||||
backend::Backend,
|
||||
|
|
@ -68,6 +66,11 @@ impl IndexComponent {
|
|||
self.show_selection = focus;
|
||||
}
|
||||
|
||||
///
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.items.is_empty()
|
||||
}
|
||||
|
||||
fn move_selection(&mut self, delta: i32) {
|
||||
let items_len = self.items.len();
|
||||
if items_len > 0 {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use crate::git_utils;
|
||||
use git2::{Status, StatusOptions, StatusShow};
|
||||
use scopetime::scope_time;
|
||||
|
||||
#[derive(PartialEq, Copy, Clone)]
|
||||
pub enum StatusItemType {
|
||||
|
|
@ -33,6 +34,8 @@ pub struct StatusItem {
|
|||
}
|
||||
|
||||
pub fn get_index(show: StatusShow) -> Vec<StatusItem> {
|
||||
scope_time!("get_index");
|
||||
|
||||
let repo = git_utils::repo();
|
||||
|
||||
let mut res = Vec::new();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use git2::{
|
|||
ObjectType, Repository, RepositoryOpenFlags, StatusOptions,
|
||||
StatusShow,
|
||||
};
|
||||
use scopetime::scope_time;
|
||||
use std::path::Path;
|
||||
|
||||
///
|
||||
|
|
@ -33,6 +34,8 @@ pub struct Diff(pub Vec<DiffLine>);
|
|||
|
||||
///
|
||||
pub fn get_diff(p: &Path, stage: bool) -> Diff {
|
||||
scope_time!("get_diff");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let mut opt = DiffOptions::new();
|
||||
|
|
@ -108,6 +111,8 @@ pub fn repo() -> Repository {
|
|||
|
||||
///
|
||||
pub fn commit(msg: &String) {
|
||||
scope_time!("commit");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let signature = repo.signature().unwrap();
|
||||
|
|
@ -131,6 +136,8 @@ pub fn commit(msg: &String) {
|
|||
|
||||
///
|
||||
pub fn index_empty() -> bool {
|
||||
scope_time!("index_empty");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let statuses = repo
|
||||
|
|
@ -143,6 +150,8 @@ pub fn index_empty() -> bool {
|
|||
}
|
||||
|
||||
pub fn stage_add(path: &Path) -> bool {
|
||||
scope_time!("stage_add");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let mut index = repo.index().unwrap();
|
||||
|
|
@ -168,6 +177,8 @@ pub fn stage_add(path: &Path) -> bool {
|
|||
}
|
||||
|
||||
pub fn stage_reset(path: &Path) -> bool {
|
||||
scope_time!("stage_reset");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let reference = repo.head().unwrap();
|
||||
|
|
@ -186,6 +197,8 @@ pub fn stage_reset(path: &Path) -> bool {
|
|||
}
|
||||
|
||||
pub fn index_reset(path: &Path) -> bool {
|
||||
scope_time!("index_reset");
|
||||
|
||||
let repo = repo();
|
||||
|
||||
let mut checkout_opts = CheckoutBuilder::new();
|
||||
|
|
|
|||
23
src/main.rs
23
src/main.rs
|
|
@ -18,6 +18,7 @@ use crossterm::{
|
|||
},
|
||||
ExecutableCommand, Result,
|
||||
};
|
||||
use scopetime::scope_time;
|
||||
use simplelog::*;
|
||||
use std::{env, fs, fs::File, io};
|
||||
use tui::{backend::CrosstermBackend, Terminal};
|
||||
|
|
@ -41,18 +42,22 @@ fn main() -> Result<()> {
|
|||
|
||||
loop {
|
||||
let events = receiver.recv().unwrap();
|
||||
for e in events {
|
||||
if let QueueEvent::InputEvent(ev) = e {
|
||||
app.event(ev);
|
||||
} else {
|
||||
app.update();
|
||||
{
|
||||
scope_time!("loop");
|
||||
|
||||
for e in events {
|
||||
if let QueueEvent::InputEvent(ev) = e {
|
||||
app.event(ev);
|
||||
} else {
|
||||
app.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
terminal.draw(|mut f| app.draw(&mut f))?;
|
||||
terminal.draw(|mut f| app.draw(&mut f))?;
|
||||
|
||||
if app.is_quit() {
|
||||
break;
|
||||
if app.is_quit() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue