diff --git a/Makefile b/Makefile index 80ecc9b5c..f8f25d3ff 100644 --- a/Makefile +++ b/Makefile @@ -261,6 +261,7 @@ test-address-sanitizer: export TIG_ADDRESS_SANITIZER_ENABLED=yes TESTS = $(sort $(shell find test -type f -name '*-test')) TESTS_TODO = $(sort $(shell find test -type f -name '*-test' -exec grep -l '\(test_todo\|-todo=\)' {} \+)) +TESTS_TMP = $(patsubst test/%,test/tmp/%,$(TESTS)) clean-test: $(Q)$(RM) -r test/tmp @@ -268,6 +269,8 @@ clean-test: test: clean-test $(TESTS) $(QUIET_SUMMARY)test/tools/show-results.sh +fix-test: $(TESTS_TMP) + ifneq (,$(strip $(V:@=))) export MAKE_TEST_OPTS = no-indent else @@ -278,6 +281,29 @@ $(TESTS): PATH := $(CURDIR)/test/tools:$(CURDIR)/src:$(PATH) $(TESTS): $(EXE) test/tools/test-graph $(QUIET_TEST)$(TEST_SHELL) $@ +$(TESTS_TMP): + @ test -z "$$DEBUG" || set -x ; \ + if egrep -q '^ *\[FAIL\]+' $@/.test-result 2>/dev/null; then \ + name=$(patsubst test/tmp/%,test/%,$@); \ + ! test -f $$name.expected || name=$$name.expected; \ + if git diff --quiet $$name; then \ + perm=$$(stat -c %a $$name); \ + cat $@/.test-result | { \ + sed -r -e 's/\x1b\[.{0,5}m//g' \ + -e '/^ *\[(OK|FAIL)\]+ .*/d' \ + -e 's/^ $$/ /' \ + -e "s# a/expected/\S+# a/$$name#" \ + -e "s# b/\S+# b/$$name#" \ + -e "s#^(index .*? 100)...#\1$$perm#" | { \ + test -n "$$DEBUG" && cat || { \ + git apply --verbose --ignore-whitespace --unidiff-zero && \ + echo "Updated for $@!" || true; \ + }; \ + }; \ + }; \ + fi; \ + fi + test-todo: MAKE_TEST_OPTS += todo test-todo: $(TESTS_TODO) @@ -295,7 +321,7 @@ site: doc-man doc-html dist distclean install install-doc \ install-doc-man install-doc-html install-release-doc-html \ install-release-doc-man rpm spell-check strip test \ - test-coverage update-docs update-headers veryclean $(TESTS) + test-coverage update-docs update-headers veryclean $(TESTS) $(TESTS_TMP) ifdef NO_MKSTEMPS COMPAT_CPPFLAGS += -DNO_MKSTEMPS diff --git a/include/tig/line.h b/include/tig/line.h index c414637b9..0f8ed9e01 100644 --- a/include/tig/line.h +++ b/include/tig/line.h @@ -43,6 +43,11 @@ struct ref; _(PP_REFS, "Refs: "), \ _(PP_REFLOG, "Reflog: "), \ _(PP_REFLOGMSG, "Reflog message: "), \ + _(PP_AUTHOR, "Author: " ), \ + _(PP_DATE, "Date: "), \ + _(PP_AUTHORDATE, "AuthorDate: "), \ + _(PP_COMMITTER, "Commit: " ), \ + _(PP_COMMITDATE, "CommitDate: "), \ _(COMMIT, "commit "), \ _(PARENT, "parent "), \ _(TREE, "tree "), \ diff --git a/include/tig/main.h b/include/tig/main.h index 6c5cedb79..f9ea6fa6b 100644 --- a/include/tig/main.h +++ b/include/tig/main.h @@ -29,6 +29,7 @@ struct commit { struct main_state { struct graph *graph; struct commit current; + struct option_common optcom; char **reflog; size_t reflogs; int reflog_width; diff --git a/include/tig/options.h b/include/tig/options.h index 12f889162..048cd6d7a 100644 --- a/include/tig/options.h +++ b/include/tig/options.h @@ -90,6 +90,8 @@ typedef struct view_column *view_settings; _(vertical_split, enum vertical_split, VIEW_RESET_DISPLAY | VIEW_DIFF_LIKE) \ _(wrap_lines, bool, VIEW_DIFF_LIKE) \ _(wrap_search, bool, VIEW_NO_FLAGS) \ + _(date_use_author, bool, VIEW_LOG_LIKE) \ + _(author_as_committer, bool, VIEW_LOG_LIKE) \ #define DEFINE_OPTION_EXTERNS(name, type, flags) extern type opt_##name; OPTION_INFO(DEFINE_OPTION_EXTERNS) @@ -102,6 +104,7 @@ OPTION_INFO(DEFINE_OPTION_EXTERNS) _(display, enum author, VIEW_NO_FLAGS) \ _(width, int, VIEW_NO_FLAGS) \ _(maxwidth, int, VIEW_NO_FLAGS) \ + _(as_committer, bool, VIEW_BLAME_LIKE | VIEW_LOG_LIKE) \ #define COMMIT_TITLE_COLUMN_OPTIONS(_) \ _(display, bool, VIEW_NO_FLAGS) \ @@ -198,7 +201,7 @@ void update_options_from_argv(const char *argv[]); const char *ignore_space_arg(); const char *commit_order_arg(); const char *commit_order_arg_with_graph(enum graph_display graph_display); -const char *log_custom_pretty_arg(bool use_author_date); +const char *log_custom_pretty_arg(struct option_common *optcom); const char *use_mailmap_arg(); const char *diff_context_arg(); const char *diff_prefix_arg(); @@ -222,6 +225,7 @@ struct option_info *find_option_info(struct option_info *option, size_t options, enum status_code parse_option(struct option_info *option, const char *prefix, const char *arg); struct option_info *find_column_option_info(enum view_column_type type, union view_column_options *opts, const char *option, struct option_info *column_info, const char **column_name); +void read_option_common(void *view, struct option_common *optcom); enum status_code parse_int(int *opt, const char *arg, int min, int max); enum status_code parse_step(double *opt, const char *arg); enum status_code set_option(const char *opt, int argc, const char *argv[]); diff --git a/include/tig/parse.h b/include/tig/parse.h index e6e8888da..16c1e0c87 100644 --- a/include/tig/parse.h +++ b/include/tig/parse.h @@ -48,7 +48,7 @@ struct blame_header { }; bool parse_blame_header(struct blame_header *header, const char *text); -bool parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *line, bool use_author_date); +bool parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *line, struct option_common *optcom); /* Parse author lines where the name may be empty: * author 1138474660 +0100 diff --git a/include/tig/util.h b/include/tig/util.h index cdccf1233..c42087fdc 100644 --- a/include/tig/util.h +++ b/include/tig/util.h @@ -118,5 +118,14 @@ name(type **mem, size_t size, size_t increase) \ void sigsegv_handler(int sig); +/* + * Common structures + */ + +struct option_common { + bool author_as_committer; + bool use_author_date; +}; + #endif /* vim: set ts=8 sw=8 noexpandtab: */ diff --git a/src/blame.c b/src/blame.c index 762534903..be797fee2 100644 --- a/src/blame.c +++ b/src/blame.c @@ -43,6 +43,7 @@ struct blame { struct blame_state { struct blame_commit *commit; struct blame_header header; + struct option_common optcom; char author[SIZEOF_STR]; bool auto_filename_display; const char *filename; @@ -77,6 +78,8 @@ blame_open(struct view *view, enum open_flags flags) enum status_code code; size_t i; + read_option_common(view, &state->optcom); + if (is_initial_view(view)) { /* Finish validating and setting up blame options */ if (!opt_file_args || opt_file_args[1]) @@ -216,8 +219,6 @@ static bool blame_read(struct view *view, struct buffer *buf, bool force_stop) { struct blame_state *state = view->private; - struct view_column *column = get_view_column(view, VIEW_COLUMN_DATE); - bool use_author_date = column && column->opt.date.use_author; if (!buf) { if (failed_to_load_initial_view(view)) @@ -255,7 +256,7 @@ blame_read(struct view *view, struct buffer *buf, bool force_stop) state->commit = NULL; - } else if (parse_blame_info(state->commit, state->author, buf->data, use_author_date)) { + } else if (parse_blame_info(state->commit, state->author, buf->data, &state->optcom)) { if (!state->commit->filename) return false; diff --git a/src/diff.c b/src/diff.c index 2ce160773..53d795b3d 100644 --- a/src/diff.c +++ b/src/diff.c @@ -591,6 +591,10 @@ diff_blame_line(const char *ref, const char *file, unsigned long lineno, struct io io; bool ok = false; struct buffer buf; + struct option_common optcom = { + .author_as_committer = false, + .use_author_date = false, + }; if (!string_format(line_arg, "-L%lu,+1", lineno)) return false; @@ -604,7 +608,7 @@ diff_blame_line(const char *ref, const char *file, unsigned long lineno, break; header = NULL; - } else if (parse_blame_info(commit, author, buf.data, false)) { + } else if (parse_blame_info(commit, author, buf.data, &optcom)) { ok = commit->filename != NULL; break; } diff --git a/src/log.c b/src/log.c index 65375621b..529fdb2a7 100644 --- a/src/log.c +++ b/src/log.c @@ -24,10 +24,12 @@ struct log_state { * up/down in the log view. */ int last_lineno; size_t graph_indent; + struct option_common optcom; enum line_type last_type; bool commit_title_read; bool after_commit_header; bool reading_diff_stat; + bool external_format; }; static inline void @@ -63,16 +65,39 @@ log_select(struct view *view, struct line *line) state->last_type = line->type; } +static bool +log_check_external_formatter() +{ + /* check if any formatter arugments in "%(logargs)", "%(cmdlineargs)" */ + const char ** opt_list[] = { + opt_log_options, + opt_cmdline_args, + }; + for (int i=0; iprivate; + bool external_format = log_check_external_formatter(); const char *log_argv[] = { "git", "log", encoding_arg, commit_order_arg(), use_mailmap_arg(), "%(logargs)", "%(cmdlineargs)", - "%(revargs)", "--no-color", "--", "%(fileargs)", NULL + "%(revargs)", "--no-color", + external_format ? "" : "--pretty=fuller", + "--", "%(fileargs)", NULL }; enum status_code code; + read_option_common(view, &state->optcom); + state->external_format = external_format; code = begin_update(view, NULL, log_argv, flags | OPEN_WITH_STDERR); if (code != SUCCESS) return code; @@ -115,6 +140,7 @@ log_read(struct view *view, struct buffer *buf, bool force_stop) size_t len; char *commit; char *data; + bool swap_lines = false; if (!buf) return true; @@ -148,10 +174,71 @@ log_read(struct view *view, struct buffer *buf, bool force_stop) state->reading_diff_stat = false; } + if (!state->external_format) { + switch (type) + { + case LINE_PP_AUTHOR: + if (state->optcom.author_as_committer) + return true; + break; + case LINE_PP_COMMITTER: + if (!state->optcom.author_as_committer) + return true; + swap_lines = state->optcom.use_author_date; + break; + case LINE_PP_AUTHORDATE: + case LINE_PP_DATE: + if (!state->optcom.use_author_date) + return true; + break; + case LINE_PP_COMMITDATE: + if (state->optcom.use_author_date) + return true; + break; + default: + break; + } + /* remove 4 spaces after Commit:/Author:, or + * convert CommitDate:/AuthorDate: to Date: */ + switch (type) + { + case LINE_PP_AUTHOR: + case LINE_PP_COMMITTER: + { + char *p = strchr(data, ':'); + if (p && p[5]==' ') + memmove(p+1, p+5, strlen(p+5)+1); + break; + } + case LINE_PP_AUTHORDATE: + case LINE_PP_COMMITDATE: + { + char *p = strchr(data, ':'); + if (p && p[1]==' ' && (p - data) >= 10) { + memcpy(p - 10, "Date: ", STRING_SIZE("Date: ")); + memmove(p - 10 + STRING_SIZE("Date: "), p+2, strlen(p+2)+1); + } + break; + } + default: + break; + } + } + if (!pager_common_read(view, data, type, &line)) return false; if (line && state->graph_indent) line->graph_indent = 1; + if (swap_lines && view->lines >= 2) { + size_t last_idx = view->lines - 1; + struct line *line1 = &view->line[last_idx]; + struct line *line2 = &view->line[last_idx - 1]; + struct line buf = *line1; + *line1 = *line2; + *line2 = buf; + line1->lineno--; + line2->lineno++; + } return true; } diff --git a/src/main.c b/src/main.c index cfa900de4..e6568dd9c 100644 --- a/src/main.c +++ b/src/main.c @@ -274,21 +274,20 @@ main_with_graph(struct view *view, struct view_column *column, enum open_flags f static enum status_code main_open(struct view *view, enum open_flags flags) { + struct main_state *state = view->private; struct view_column *commit_title_column = get_view_column(view, VIEW_COLUMN_COMMIT_TITLE); enum graph_display graph_display = main_with_graph(view, commit_title_column, flags); - struct view_column *column = get_view_column(view, VIEW_COLUMN_DATE); - bool use_author_date = column && column->opt.date.use_author; + read_option_common(view, &state->optcom); const char *pretty_custom_argv[] = { GIT_MAIN_LOG(encoding_arg, commit_order_arg_with_graph(graph_display), "%(mainargs)", "%(cmdlineargs)", "%(revargs)", "%(fileargs)", - show_notes_arg(), log_custom_pretty_arg(use_author_date)) + show_notes_arg(), log_custom_pretty_arg(&state->optcom)) }; const char *pretty_raw_argv[] = { GIT_MAIN_LOG_RAW(encoding_arg, commit_order_arg_with_graph(graph_display), "%(mainargs)", "%(cmdlineargs)", "%(revargs)", "%(fileargs)", show_notes_arg()) }; - struct main_state *state = view->private; const char **main_argv = pretty_custom_argv; enum watch_trigger changes_triggers = WATCH_NONE; @@ -415,8 +414,6 @@ main_add_reflog(struct view *view, struct main_state *state, char *reflog) bool main_read(struct view *view, struct buffer *buf, bool force_stop) { - struct view_column *column = get_view_column(view, VIEW_COLUMN_DATE); - bool use_author_date = column && column->opt.date.use_author; struct main_state *state = view->private; struct graph *graph = state->graph; enum line_type type; @@ -510,16 +507,17 @@ main_read(struct view *view, struct buffer *buf, bool force_stop) break; case LINE_AUTHOR: - parse_author_line(line + STRING_SIZE("author "), - &commit->author, use_author_date ? &commit->time : NULL); - if (state->with_graph) - graph->render_parents(graph, &commit->graph); - break; - case LINE_COMMITTER: - parse_author_line(line + STRING_SIZE("committer "), - NULL, use_author_date ? NULL : &commit->time); + { + bool committer_line = (type == LINE_COMMITTER); + if ((state->optcom.author_as_committer ^ committer_line) == 0) + parse_author_line(line + + (committer_line ? STRING_SIZE("committer ") : STRING_SIZE("author ")), + &commit->author, &commit->time); + if (committer_line && state->with_graph) + graph->render_parents(graph, &commit->graph); break; + } default: /* Fill in the commit title if it has not already been set. */ diff --git a/src/options.c b/src/options.c index ecf9d068d..b22b25a79 100644 --- a/src/options.c +++ b/src/options.c @@ -115,6 +115,30 @@ find_column_option_info(enum view_column_type type, union view_column_options *o return NULL; } +void read_option_common(void *_view, struct option_common *opt) +{ + extern struct view log_view; + struct view *view = _view; + bool as_committer = false; + bool use_author_date = false; + + if (view == &log_view) { + as_committer = opt_author_as_committer; + use_author_date = opt_date_use_author; + } else { + struct view_column *column1 = get_view_column(view, VIEW_COLUMN_AUTHOR); + struct view_column *column2 = get_view_column(view, VIEW_COLUMN_DATE); + + if (column1) + as_committer = column1->opt.author.as_committer; + if (column2) + use_author_date = column2->opt.date.use_author; + } + + opt->author_as_committer = as_committer; + opt->use_author_date = use_author_date; +} + /* * State variables. */ @@ -159,15 +183,28 @@ use_mailmap_arg() } const char * -log_custom_pretty_arg(bool use_author_date) +log_custom_pretty_arg(struct option_common *optcom) { - return use_author_date - ? opt_mailmap - ? "--pretty=format:commit %m %H %P%x00%aN <%aE> %ad%x00%s%x00%N" - : "--pretty=format:commit %m %H %P%x00%an <%ae> %ad%x00%s%x00%N" - : opt_mailmap - ? "--pretty=format:commit %m %H %P%x00%aN <%aE> %cd%x00%s%x00%N" - : "--pretty=format:commit %m %H %P%x00%an <%ae> %cd%x00%s%x00%N"; + switch ((optcom->author_as_committer*2) + opt_mailmap) + { + case 0x3: + return optcom->use_author_date ? + "--pretty=format:commit %m %H %P%x00%cN <%cE> %ad%x00%s%x00%N" : + "--pretty=format:commit %m %H %P%x00%cN <%cE> %cd%x00%s%x00%N"; + case 0x2: + return optcom->use_author_date ? + "--pretty=format:commit %m %H %P%x00%cn <%ce> %ad%x00%s%x00%N" : + "--pretty=format:commit %m %H %P%x00%cn <%ce> %cd%x00%s%x00%N"; + case 0x1: + return optcom->use_author_date ? + "--pretty=format:commit %m %H %P%x00%aN <%aE> %ad%x00%s%x00%N" : + "--pretty=format:commit %m %H %P%x00%aN <%aE> %cd%x00%s%x00%N"; + case 0x0: + default: + return optcom->use_author_date ? + "--pretty=format:commit %m %H %P%x00%an <%ae> %ad%x00%s%x00%N" : + "--pretty=format:commit %m %H %P%x00%an <%ae> %cd%x00%s%x00%N"; + } } #define ENUM_ARG(enum_name, arg_string) ENUM_MAP_ENTRY(arg_string, enum_name) diff --git a/src/parse.c b/src/parse.c index d6131b1ad..c51a0f04c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -14,6 +14,7 @@ #include "tig/tig.h" #include "tig/parse.h" #include "tig/map.h" +#include "tig/options.h" size_t parse_size(const char *text) @@ -139,12 +140,12 @@ match_blame_header(const char *name, char **line) } bool -parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *line, bool use_author_date) +parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *line, struct option_common *optcom) { - if (match_blame_header("author ", &line)) { + if (match_blame_header(optcom->author_as_committer ? "committer " : "author ", &line)) { string_ncopy_do(author, SIZEOF_STR, line, strlen(line)); - } else if (match_blame_header("author-mail ", &line)) { + } else if (match_blame_header(optcom->author_as_committer ? "committer-mail " : "author-mail ", &line)) { char *end = strchr(line, '>'); if (end) @@ -154,10 +155,10 @@ parse_blame_info(struct blame_commit *commit, char author[SIZEOF_STR], char *lin commit->author = get_author(author, line); author[0] = 0; - } else if (match_blame_header(use_author_date ? "author-time " : "committer-time ", &line)) { + } else if (match_blame_header(optcom->use_author_date ? "author-time " : "committer-time ", &line)) { parse_timesec(&commit->time, line); - } else if (match_blame_header(use_author_date ? "author-tz " : "committer-tz ", &line)) { + } else if (match_blame_header(optcom->use_author_date ? "author-tz " : "committer-tz ", &line)) { parse_timezone(&commit->time, line); } else if (match_blame_header("summary ", &line)) { diff --git a/src/prompt.c b/src/prompt.c index 3f5cf706f..3225dfa52 100644 --- a/src/prompt.c +++ b/src/prompt.c @@ -872,6 +872,12 @@ prompt_toggle(struct view *view, const char *argv[], enum view_flag *flags) } } + for (column = view->columns; column; column = column->next) { + toggle = find_column_option_info(column->type, &column->opt, option, &template, &column_name); + if (toggle) + return prompt_toggle_option(view, argv, column_name, toggle, flags); + } + toggle = find_option_info(option_toggles, ARRAY_SIZE(option_toggles), "", option); if (toggle) { if ((view_has_flags(view, VIEW_FILE_FILTER) && @@ -882,12 +888,6 @@ prompt_toggle(struct view *view, const char *argv[], enum view_flag *flags) return prompt_toggle_option(view, argv, "", toggle, flags); } - for (column = view->columns; column; column = column->next) { - toggle = find_column_option_info(column->type, &column->opt, option, &template, &column_name); - if (toggle) - return prompt_toggle_option(view, argv, column_name, toggle, flags); - } - return error("`:toggle %s` not supported", option); } @@ -898,23 +898,19 @@ prompt_option_flags(struct view *view, const char *option) struct option_info *toggle; struct view_column *column; const char *column_name; - - toggle = find_option_info(option_toggles, ARRAY_SIZE(option_toggles), "", option); - - if (!toggle || !toggle->flags) { - const char *prefixed; - - if ((prefixed = strstr(option, "-view-"))) { - option = prefixed + STRING_SIZE("-view-"); - for (column = view->columns; column; column = column->next) { - toggle = find_column_option_info(column->type, &column->opt, - option, &template, &column_name); - if (toggle) - return toggle->flags; - } + const char *prefixed; + + if ((prefixed = strstr(option, "-view-"))) { + option = prefixed + STRING_SIZE("-view-"); + for (column = view->columns; column; column = column->next) { + toggle = find_column_option_info(column->type, &column->opt, + option, &template, &column_name); + if (toggle) + return toggle->flags; } } + toggle = find_option_info(option_toggles, ARRAY_SIZE(option_toggles), "", option); if (toggle) return toggle->flags; diff --git a/src/reflog.c b/src/reflog.c index 784cc94d3..076f548f2 100644 --- a/src/reflog.c +++ b/src/reflog.c @@ -41,10 +41,12 @@ reflog_request(struct view *view, enum request request, struct line *line) switch (request) { case REQ_ENTER: { - const char *main_argv[] = { + struct option_common optcom; + read_option_common(view, &optcom); + const char *main_argv[] = { GIT_MAIN_LOG(encoding_arg, commit_order_arg(), "%(mainargs)", "", commit->id, "", - show_notes_arg(), log_custom_pretty_arg(false)) + show_notes_arg(), log_custom_pretty_arg(&optcom)) }; enum open_flags flags = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT; diff --git a/src/refs.c b/src/refs.c index 90fcf4109..832f5ab7c 100644 --- a/src/refs.c +++ b/src/refs.c @@ -74,13 +74,13 @@ refs_request(struct view *view, enum request request, struct line *line) case REQ_ENTER: { const struct ref *ref = reference->ref; - struct view_column *column = get_view_column(view, VIEW_COLUMN_DATE); - bool use_author_date = column && column->opt.date.use_author; + struct option_common optcom; + read_option_common(view, &optcom); const char *all_references_argv[] = { GIT_MAIN_LOG(encoding_arg, commit_order_arg(), "%(mainargs)", "", refs_is_all(reference) ? "--all" : ref->id, "", - show_notes_arg(), log_custom_pretty_arg(use_author_date)) + show_notes_arg(), log_custom_pretty_arg(&optcom)) }; enum open_flags flags = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT; @@ -179,23 +179,42 @@ refs_open_visitor(void *data, const struct ref *ref) return true; } +static const char * +refs_custom_pretty_arg(struct option_common *optcom) +{ + switch ((optcom->author_as_committer*2) + opt_mailmap) + { + case 0x3: + return optcom->use_author_date ? + "--pretty=format:%H%x00%cN <%cE> %ad%x00%s" : + "--pretty=format:%H%x00%cN <%cE> %cd%x00%s"; + case 0x2: + return optcom->use_author_date ? + "--pretty=format:%H%x00%cn <%ce> %ad%x00%s" : + "--pretty=format:%H%x00%cn <%ce> %cd%x00%s"; + case 0x1: + return optcom->use_author_date ? + "--pretty=format:%H%x00%aN <%aE> %ad%x00%s" : + "--pretty=format:%H%x00%aN <%aE> %cd%x00%s"; + case 0x0: + default: + return optcom->use_author_date ? + "--pretty=format:%H%x00%an <%ae> %ad%x00%s" : + "--pretty=format:%H%x00%an <%ae> %cd%x00%s"; + } +} + static const char **refs_argv; static enum status_code refs_open(struct view *view, enum open_flags flags) { - struct view_column *column = get_view_column(view, VIEW_COLUMN_DATE); - bool use_author_date = column && column->opt.date.use_author; + struct option_common optcom; + read_option_common(view, &optcom); const char *refs_log[] = { - "git", "log", encoding_arg, "--no-color", "--date=raw", use_author_date - ? opt_mailmap - ? "--pretty=format:%H%x00%aN <%aE> %ad%x00%s" - : "--pretty=format:%H%x00%an <%ae> %ad%x00%s" - : opt_mailmap - ? "--pretty=format:%H%x00%aN <%aE> %cd%x00%s" - : "--pretty=format:%H%x00%an <%ae> %cd%x00%s", - "--all", "--decorate-refs=", "--simplify-by-decoration", - NULL + "git", "log", encoding_arg, "--no-color", "--date=raw", + refs_custom_pretty_arg(&optcom), "--all", "--simplify-by-decoration", + NULL }; enum status_code code; const char *name = REFS_ALL_NAME; diff --git a/src/tig.c b/src/tig.c index 5c28351a2..599e8001c 100644 --- a/src/tig.c +++ b/src/tig.c @@ -82,6 +82,10 @@ _('$', "commit title overflow display", "commit-title-overflow"), \ _('d', "untracked directory info", "status-show-untracked-dirs"), \ _('|', "view split", "vertical-split"), \ + _('E', "mail map", "mailmap"), \ + _('L', "local date", "date-local"), \ + _('M', "use author date", "date-use-author"), \ + _('m', "author as committer", "author-as-committer"), \ const struct menu_item toggle_menu_items[] = { diff --git a/src/tree.c b/src/tree.c index b0e6d9408..33b59d3ca 100644 --- a/src/tree.c +++ b/src/tree.c @@ -71,8 +71,9 @@ struct tree_entry { struct tree_state { char commit[SIZEOF_REV]; - const struct ident *author; - struct time author_time; + const struct ident *author; /* Author/Committer */ + struct time author_time; /* Author data/Commit date */ + struct option_common optcom; bool read_date; }; @@ -135,8 +136,6 @@ static bool tree_read_date(struct view *view, struct buffer *buf, struct tree_state *state) { char *text = buf ? buf->data : NULL; - struct view_column *column = get_view_column(view, VIEW_COLUMN_DATE); - bool use_author_date = column && column->opt.date.use_author; if (!text && state->read_date) { state->read_date = false; @@ -164,17 +163,19 @@ tree_read_date(struct view *view, struct buffer *buf, struct tree_state *state) state->read_date = true; return false; - } else if (*text == 'c' && get_line_type(text) == LINE_COMMIT) { - string_copy_rev_from_commit_line(state->commit, text); - + } else if (*text == 'c') { + enum line_type ltype = get_line_type(text); + if (ltype == LINE_COMMIT) { + string_copy_rev_from_commit_line(state->commit, text); + } else if (ltype == LINE_COMMITTER) { + parse_author_line(text + STRING_SIZE("committer "), + state->optcom.author_as_committer ? &state->author : NULL, + state->optcom.use_author_date ? NULL : &state->author_time); + } } else if (*text == 'a' && get_line_type(text) == LINE_AUTHOR) { parse_author_line(text + STRING_SIZE("author "), - &state->author, use_author_date ? &state->author_time : NULL); - - } else if (*text == 'c' && get_line_type(text) == LINE_COMMITTER) { - parse_author_line(text + STRING_SIZE("committer "), - NULL, use_author_date ? NULL : &state->author_time); - + state->optcom.author_as_committer ? NULL : &state->author, + state->optcom.use_author_date ? &state->author_time : NULL); } else if (*text == ':') { char *pos; size_t annotated = 1; @@ -455,10 +456,13 @@ tree_select(struct view *view, struct line *line) static enum status_code tree_open(struct view *view, enum open_flags flags) { + struct tree_state *state = view->private; static const char *tree_argv[] = { "git", "ls-tree", "-l", "%(commit)", "--", "%(directory)", NULL }; + read_option_common(view, &state->optcom); + if (string_rev_is_null(view->env->commit)) return error("No tree exists for this commit"); diff --git a/test/diff/diff-stat-test b/test/diff/diff-stat-test index e8e7808c8..e92b1fdb9 100755 --- a/test/diff/diff-stat-test +++ b/test/diff/diff-stat-test @@ -46,9 +46,9 @@ Dimensions: height=28 width=181 Position: offset=0 column=0 lineno=0 line[ 0] type=commit selected=1 line[ 0] cells=1 text=[commit 1b4c64b595aeb4de1d317d669faacd3c1d82f0b0] -line[ 1] type= selected=0 +line[ 1] type=pp-author selected=0 line[ 1] cells=1 text=[Author: A. U. Thor ] -line[ 2] type= selected=0 +line[ 2] type=pp-date selected=0 line[ 2] cells=1 text=[Date: Sun Jul 2 15:01:24 2017 +0200] line[ 3] type=default selected=0 line[ 3] cells=1 text=[] diff --git a/test/help/all-keybindings-test.expected b/test/help/all-keybindings-test.expected index f4eb13852..bca5de3fc 100755 --- a/test/help/all-keybindings-test.expected +++ b/test/help/all-keybindings-test.expected @@ -1,6 +1,6 @@ Quick reference for tig keybindings: [-] Collapse all sections - + [-] generic bindings View switching m view-main Show main view @@ -126,4 +126,4 @@ External commands: ! ?git stash drop %(stash) [-] pager bindings Internal commands: -[help] - line 2 of 148 86% +[help] - line 2 of 152 84% diff --git a/test/help/default-test b/test/help/default-test index d45dcc156..38221b3e5 100755 --- a/test/help/default-test +++ b/test/help/default-test @@ -30,30 +30,30 @@ Quick reference for tig keybindings: [-] generic bindings View switching - m view-main Show main view - d view-diff Show diff view - l view-log Show log view - L view-reflog Show reflog view - t view-tree Show tree view - f view-blob Show blob view - b view-blame Show blame view - r view-refs Show refs view - s, S view-status Show status view - c view-stage Show stage view - y view-stash Show stash view - g view-grep Show grep view - p view-pager Show pager view - h view-help Show help view + m view-main Show main view + d view-diff Show diff view + l view-log Show log view + L view-reflog Show reflog view + t view-tree Show tree view + f view-blob Show blob view + b view-blame Show blame view + r view-refs Show refs view + s, S view-status Show status view + c view-stage Show stage view + y view-stash Show stash view + g view-grep Show grep view + p view-pager Show pager view + h view-help Show help view View manipulation - enter Enter and open selected line - < back Go back to the previous view state - , , J next Move to next - , , K previous Move to previous - ',' parent Move to parent - view-next Move focus to the next view - R, refresh Reload and refresh view - O maximize Maximize the current view -[help] - line 1 of 107 26% + enter Enter and open selected line + < back Go back to the previous view state + , , J next Move to next + , , K previous Move to previous + ',' parent Move to parent + view-next Move focus to the next view + R, refresh Reload and refresh view + O maximize Maximize the current view +[help] - line 1 of 111 25% EOF assert_equals 'help-search.screen' < enter Enter and open selected line - < back Go back to the previous view state - , , J next Move to next - , , K previous Move to previous - ',' parent Move to parent - view-next Move focus to the next view - R, refresh Reload and refresh view - O maximize Maximize the current view -[help] - line 20 of 107 26% + enter Enter and open selected line + < back Go back to the previous view state + , , J next Move to next + , , K previous Move to previous + ',' parent Move to parent + view-next Move focus to the next view + R, refresh Reload and refresh view + O maximize Maximize the current view +[help] - line 20 of 111 25% EOF assert_equals 'help-collapsed.screen' <): - . line-number Toggle line numbers - D date Toggle dates - A author Toggle author - ~ line-graphics Toggle graphics - g commit-title-graph Toggle revision graph - # file-name Toggle file names - * file-size Toggle file sizes - W ignore-space Toggle space changes - l commit-order Toggle commit order - F commit-title-refs Toggle reference display - C show-changes Toggle local change display -[help] - line 5 of 34 82% + . line-number Toggle line numbers + D date Toggle dates + A author Toggle author + ~ line-graphics Toggle graphics + g commit-title-graph Toggle revision graph + # file-name Toggle file names + * file-size Toggle file sizes + W ignore-space Toggle space changes + l commit-order Toggle commit order + F commit-title-refs Toggle reference display + C show-changes Toggle local change display +[help] - line 5 of 38 73% EOF diff --git a/test/help/user-command-test b/test/help/user-command-test index 23ebaebff..454d5a5b8 100755 --- a/test/help/user-command-test +++ b/test/help/user-command-test @@ -55,5 +55,5 @@ Searching [+] main bindings [+] diff bindings [+] reflog bindings -[help] - line 82 of 132 82% +[help] - line 82 of 136 80% EOF diff --git a/test/log/log-graph-test b/test/log/log-graph-test index c7c7c1df2..d84e963bb 100755 --- a/test/log/log-graph-test +++ b/test/log/log-graph-test @@ -35,7 +35,7 @@ assert_equals 'log-graph.screen' < -| Date: Tue Dec 17 00:02:15 2013 +0100 +| Date: Tue Dec 17 00:10:36 2013 +0100 | | Update links to reflect project name change | diff --git a/test/tigrc/env-vars-test b/test/tigrc/env-vars-test index cd3736a3f..6f4a30579 100755 --- a/test/tigrc/env-vars-test +++ b/test/tigrc/env-vars-test @@ -36,5 +36,5 @@ Quick reference for tig keybindings: [-] generic bindings Misc : prompt Open the prompt -[help] - line 1 of 25 24% +[help] - line 1 of 29 20% EOF diff --git a/test/tigrc/parse-test b/test/tigrc/parse-test index 94bac5ead..2601340f2 100755 --- a/test/tigrc/parse-test +++ b/test/tigrc/parse-test @@ -128,5 +128,5 @@ External commands: 4 ): -[help] - line 1 of 25 32% +[help] - line 1 of 29 27% EOF test_case source-nonexistent-file-quietly \ @@ -94,7 +94,7 @@ Misc : prompt Open the prompt [-] toggle bindings Toggle keys (enter: o ): -[help] - line 1 of 25 32% +[help] - line 1 of 29 27% EOF test_case source-tilde-path \ @@ -115,7 +115,7 @@ View manipulation q quit Close all views and quit Misc : prompt Open the prompt -[help] - line 1 of 27 29% +[help] - line 1 of 31 25% EOF run_test_cases diff --git a/tigrc b/tigrc index 738f4fbad..2e54c1d44 100644 --- a/tigrc +++ b/tigrc @@ -16,6 +16,7 @@ # : Show author information? # - width (int) : Fixed width when nonzero # - maxwidth (int) : Autosize limit +# - as_committer (bool) : Show committer instead of author? # # commit-title # - display (bool) : Show the commit title? @@ -129,6 +130,8 @@ set diff-indicator = yes # Show diff +/- signs? set log-options = --cc --stat # User-defined options for `tig log` (git-log) #set main-options = -n 1000 # User-defined options for `tig` (git-log) set mailmap = yes # Use .mailmap to show canonical name and email address? +set author-as-committer = no # Show committer instead of author? +set date-use-author = no # Show author date instead of committer date? # Misc set start-on-head = no # Start with cursor on HEAD commit?