From e56765a6b3e810ede826b5076deb32945070e262 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Mon, 30 Jun 2014 23:48:51 -0400 Subject: [PATCH] Partly restore old refresh behavior This ensures that the current view is refreshed after returning from an external command when `refresh-mode` is set to `after-command`. That was what Tig used to do before the option was introduced. It special cases the 'after-command' event to force a refresh in the current view. The fix is tested to work in both the main and status view. Fixes #289 --- NEWS.adoc | 2 + include/tig/watch.h | 2 +- src/display.c | 8 +- src/watch.c | 31 ++++++-- test/main/refresh-test | 104 +++++++++++++++++++++++++ test/status/refresh-test | 194 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 330 insertions(+), 11 deletions(-) create mode 100755 test/main/refresh-test create mode 100755 test/status/refresh-test diff --git a/NEWS.adoc b/NEWS.adoc index aa933db..d9c26fb 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -14,6 +14,8 @@ Improvement: Bug fixes: + - Refresh the current view when returning from an external command and + `refresh-mode=after-command`. (GH #289) - Fix readline completion. - Fix '/' to `find-next` when readline support is enabled. (GH #302) - Fix readline prompt to correctly handle UTF-8 characters. diff --git a/include/tig/watch.h b/include/tig/watch.h index 602f48f..9ca52c9 100644 --- a/include/tig/watch.h +++ b/include/tig/watch.h @@ -19,7 +19,7 @@ enum watch_event { WATCH_EVENT_SWITCH_VIEW, - WATCH_EVENT_AFTER_EXTERNAL, + WATCH_EVENT_AFTER_COMMAND, WATCH_EVENT_LOAD, WATCH_EVENT_PERIODIC, }; diff --git a/src/display.c b/src/display.c index 89c1657..347af8a 100644 --- a/src/display.c +++ b/src/display.c @@ -41,11 +41,13 @@ open_external_viewer(const char *argv[], const char *dir, bool confirm, bool ref if (confirm || !ok) { if (!ok && *notice) fprintf(stderr, "%s", notice); - fprintf(stderr, "Press Enter to continue"); - getc(opt_tty); + if (!is_script_executing()) { + fprintf(stderr, "Press Enter to continue"); + getc(opt_tty); + } } reset_prog_mode(); - if (watch_update(WATCH_EVENT_AFTER_EXTERNAL) && refresh) { + if (watch_update(WATCH_EVENT_AFTER_COMMAND) && refresh) { struct view *view; int i; diff --git a/src/watch.c b/src/watch.c index 751ee14..d0d4ad5 100644 --- a/src/watch.c +++ b/src/watch.c @@ -106,7 +106,7 @@ watch_index_handler(struct watch_handler *handler, enum watch_event event, enum enum watch_trigger changed = WATCH_NONE; struct index_diff diff; - if (event == WATCH_EVENT_AFTER_EXTERNAL) + if (event == WATCH_EVENT_AFTER_COMMAND) return check_file_mtime(&handler->last_modified, "%s/index", repo.git_dir) ? check : WATCH_NONE; @@ -139,7 +139,7 @@ static enum watch_trigger watch_refs_handler(struct watch_handler *handler, enum watch_event event, enum watch_trigger check) { - if (event == WATCH_EVENT_AFTER_EXTERNAL) + if (event == WATCH_EVENT_AFTER_COMMAND) load_refs(TRUE); return WATCH_NONE; @@ -157,7 +157,7 @@ watch_no_refresh(enum watch_event event) { return opt_refresh_mode == REFRESH_MODE_MANUAL || (opt_refresh_mode == REFRESH_MODE_AFTER_COMMAND && - event != WATCH_EVENT_AFTER_EXTERNAL); + event != WATCH_EVENT_AFTER_COMMAND); } static void @@ -172,10 +172,17 @@ watch_apply_changes(struct watch *source, enum watch_event event, for (watch = watches; watch; watch = watch->next) { enum watch_trigger triggers = changed & watch->triggers; - if (source == watch) + if (source == watch) { source->state |= triggers; - else if (triggers) - watch->changed |= triggers; + continue; + } + + if (event == WATCH_EVENT_AFTER_COMMAND) { + watch->state = WATCH_NONE; + triggers = watch->triggers; + } + + watch->changed |= triggers; } } @@ -189,14 +196,24 @@ static enum watch_trigger watch_update_event(enum watch_event event, enum watch_trigger trigger, enum watch_trigger changed) { + time_t timestamp = 0; int i; if (watch_no_refresh(event)) return WATCH_NONE; - for (i = 0; trigger && i < ARRAY_SIZE(watch_handlers); i++) { + if (event == WATCH_EVENT_AFTER_COMMAND) + timestamp = time(NULL); + + for (i = 0; i < ARRAY_SIZE(watch_handlers); i++) { struct watch_handler *handler = &watch_handlers[i]; + if (event == WATCH_EVENT_AFTER_COMMAND) { + changed = handler->triggers; + handler->last_modified = timestamp; + continue; + } + if (*repo.git_dir && (trigger & handler->triggers) && (changed | handler->triggers) != changed) diff --git a/test/main/refresh-test b/test/main/refresh-test new file mode 100755 index 0000000..c77c281 --- /dev/null +++ b/test/main/refresh-test @@ -0,0 +1,104 @@ +#!/bin/sh + +. libtest.sh +. libgit.sh + +export LINES=5 + +steps ' + :view-main + :wait + :save-display main-with-unstaged.screen + + + :wait + :save-display main-after-add-a.screen + + + :wait + :save-display main-after-add-all.screen + + + :wait + :save-display main-after-commit.screen + + + :wait + :save-display main-after-reset-soft.screen + + + :wait + :save-display main-after-reset-a-and-bc.screen + + + :wait + :save-display main-after-reset-hard.screen +' + +tigrc < !sh -c 'git add a' +bind generic !sh -c 'git add -u' +bind generic !sh -c 'git commit -m "Commit changes"' +bind generic !sh -c 'git reset --soft HEAD^' +bind generic !sh -c 'git reset a b.c' +bind generic !sh -c 'git reset --hard' +EOF + +in_work_dir create_dirty_workdir + +export GIT_AUTHOR_DATE="$(expr $author_date + $author_date_delta)" +export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" + +test_tig + +YYY_MM_DD_HH_MM="$(date +"%Y-%m-%d %H:%M")" + +assert_equals 'main-with-unstaged.screen' < + :wait + :save-display status-after-add-a.screen + + + :wait + :save-display status-after-add-all.screen + + + :wait + :save-display status-after-commit.screen + + + :wait + :save-display status-after-reset-soft.screen + + + :wait + :save-display status-after-reset-a-and-bc.screen + + + :wait + :save-display status-after-reset-hard.screen + + + :wait + :save-display status-after-touch-new-file.screen +' + +tigrc < !sh -c 'git add a' +bind generic !sh -c 'git add -u' +bind generic !sh -c 'git commit -m "Commit changes"' +bind generic !sh -c 'git reset --soft HEAD^' +bind generic !sh -c 'git reset a b.c' +bind generic !sh -c 'git reset --hard' +bind generic !sh -c 'touch new-file' +EOF + +in_work_dir create_dirty_workdir + +export GIT_AUTHOR_DATE="$(expr $author_date + $author_date_delta)" +export GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" + +test_tig + +assert_equals 'status-with-unstaged.screen' <