Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default to tick-based updates #1657

Merged
merged 3 commits into from
Apr 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* commit hooks report "command not found" on Windows with wsl2 installed ([#1528](/~https://github.com/extrawurst/gitui/issues/1528))
* crashes on entering submodules ([#1510](/~https://github.com/extrawurst/gitui/issues/1510))
* fix race issue: revlog messages sometimes appear empty ([#1473](/~https://github.com/extrawurst/gitui/issues/1473))
* default to tick-based updates [[@cruessler](/~https://github.com/cruessler)] ([#1444](/~https://github.com/extrawurst/gitui/issues/1444))

### Changed
* minimum supported rust version bumped to 1.64 (thank you `clap`)
Expand Down
10 changes: 10 additions & 0 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::{
pub struct CliArgs {
pub theme: PathBuf,
pub repo_path: RepoPath,
pub notify_watcher: bool,
pub poll_watcher: bool,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

poll_watcher should be deprecated by this, right? because it is the default

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if we remove it? and people still call it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I followed your suggestion below and removed poll_watcher.

After the removal, clap prints an error when --poll is passed as an argument: error: unexpected argument '--poll' found.

}

Expand Down Expand Up @@ -54,11 +55,14 @@ pub fn process_cmdline() -> Result<CliArgs> {
get_app_config_path()?.join("theme.ron")
};

let notify_watcher: bool =
*arg_matches.get_one("watcher").unwrap_or(&false);
let arg_poll: bool =
*arg_matches.get_one("poll").unwrap_or(&false);

Ok(CliArgs {
theme,
notify_watcher,
poll_watcher: arg_poll,
repo_path,
})
Expand Down Expand Up @@ -95,6 +99,12 @@ fn app() -> ClapApp {
.long("logging")
.num_args(0),
)
.arg(
Arg::new("watcher")
.help("Use notify-based file system watcher instead of tick-based update. This is more performant, but can cause issues in larger repositories")
extrawurst marked this conversation as resolved.
Show resolved Hide resolved
.long("watcher")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("poll")
.help("Poll folder for changes instead of using file system events. This can be useful if you run into issues with maximum # of file descriptors")
Expand Down
53 changes: 42 additions & 11 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ use asyncgit::{
AsyncGitNotification,
};
use backtrace::Backtrace;
use crossbeam_channel::{tick, unbounded, Receiver, Select};
use crossbeam_channel::{never, tick, unbounded, Receiver, Select};
use crossterm::{
terminal::{
disable_raw_mode, enable_raw_mode, EnterAlternateScreen,
Expand All @@ -83,11 +83,13 @@ use tui::{
use ui::style::Theme;
use watcher::RepoWatcher;

static TICK_INTERVAL: Duration = Duration::from_secs(5);
extrawurst marked this conversation as resolved.
Show resolved Hide resolved
static SPINNER_INTERVAL: Duration = Duration::from_millis(80);

///
#[derive(Clone)]
pub enum QueueEvent {
Tick,
Notify,
SpinnerUpdate,
AsyncEvent(AsyncNotification),
Expand All @@ -114,6 +116,13 @@ pub enum AsyncNotification {
Git(AsyncGitNotification),
}

#[derive(Clone, Copy, PartialEq)]
enum Updater {
Ticker,
PollWatcher,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would sunset the notify based poll watcher entirely or do you see any point in keeping it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, if it’s causing issues that are not fixable or unlikely to be fixed, it makes more sense to completely remove it.

NotifyWatcher,
}

fn main() -> Result<()> {
let app_start = Instant::now();

Expand Down Expand Up @@ -145,14 +154,21 @@ fn main() -> Result<()> {
let mut repo_path = cliargs.repo_path;
let input = Input::new();

let updater = match (cliargs.notify_watcher, cliargs.poll_watcher)
{
(true, true) => Updater::PollWatcher,
(true, false) => Updater::NotifyWatcher,
_ => Updater::Ticker,
};

loop {
let quit_state = run_app(
app_start,
repo_path.clone(),
theme,
key_config.clone(),
&input,
cliargs.poll_watcher,
updater,
&mut terminal,
)?;

Expand All @@ -173,18 +189,27 @@ fn run_app(
theme: Theme,
key_config: KeyConfig,
input: &Input,
poll_watcher: bool,
updater: Updater,
terminal: &mut Terminal<CrosstermBackend<io::Stdout>>,
) -> Result<QuitState, anyhow::Error> {
let (tx_git, rx_git) = unbounded();
let (tx_app, rx_app) = unbounded();

let rx_input = input.receiver();
let watcher = RepoWatcher::new(
repo_work_dir(&repo)?.as_str(),
poll_watcher,
);
let rx_watcher = watcher.receiver();

let (rx_ticker, rx_watcher) = match updater {
Updater::NotifyWatcher | Updater::PollWatcher => {
let poll_watcher = updater == Updater::PollWatcher;
let repo_watcher = RepoWatcher::new(
repo_work_dir(&repo)?.as_str(),
poll_watcher,
);

(never(), repo_watcher.receiver())
}
Updater::Ticker => (tick(TICK_INTERVAL), never()),
};

let spinner_ticker = tick(SPINNER_INTERVAL);

let mut app = App::new(
Expand All @@ -210,6 +235,7 @@ fn run_app(
&rx_input,
&rx_git,
&rx_app,
&rx_ticker,
&rx_watcher,
&spinner_ticker,
)?
Expand All @@ -235,7 +261,9 @@ fn run_app(
}
app.event(ev)?;
}
QueueEvent::Notify => app.update()?,
QueueEvent::Tick | QueueEvent::Notify => {
app.update()?;
}
QueueEvent::AsyncEvent(ev) => {
if !matches!(
ev,
Expand Down Expand Up @@ -309,6 +337,7 @@ fn select_event(
rx_input: &Receiver<InputEvent>,
rx_git: &Receiver<AsyncGitNotification>,
rx_app: &Receiver<AsyncAppNotification>,
rx_ticker: &Receiver<Instant>,
rx_notify: &Receiver<()>,
rx_spinner: &Receiver<Instant>,
) -> Result<QueueEvent> {
Expand All @@ -317,6 +346,7 @@ fn select_event(
sel.recv(rx_input);
sel.recv(rx_git);
sel.recv(rx_app);
sel.recv(rx_ticker);
sel.recv(rx_notify);
sel.recv(rx_spinner);

Expand All @@ -331,8 +361,9 @@ fn select_event(
2 => oper.recv(rx_app).map(|e| {
QueueEvent::AsyncEvent(AsyncNotification::App(e))
}),
3 => oper.recv(rx_notify).map(|_| QueueEvent::Notify),
4 => oper.recv(rx_spinner).map(|_| QueueEvent::SpinnerUpdate),
3 => oper.recv(rx_ticker).map(|_| QueueEvent::Notify),
4 => oper.recv(rx_notify).map(|_| QueueEvent::Notify),
5 => oper.recv(rx_spinner).map(|_| QueueEvent::SpinnerUpdate),
_ => bail!("unknown select source"),
}?;

Expand Down