X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=tig.c;h=41d8123379eec382c30f9e7d9e9bb9c1f09892d2;hb=0cc55146effae5fa6095a142248cc45e5b24d05a;hp=f98fb24a4a076a5f317e38ff1b6ed539347dfaed;hpb=6859ce581a2d983ac77f7e7cdd4318244cd11f2e;p=tig.git diff --git a/tig.c b/tig.c index f98fb24..41d8123 100644 --- a/tig.c +++ b/tig.c @@ -137,7 +137,7 @@ struct ref_list { }; static struct ref_list *get_ref_list(const char *id); -static void foreach_ref(bool (*visitor)(void *data, struct ref *ref), void *data); +static void foreach_ref(bool (*visitor)(void *data, const struct ref *ref), void *data); static int load_refs(void); enum format_flags { @@ -305,6 +305,24 @@ struct enum_map { #define ENUM_MAP(name, value) { name, STRING_SIZE(name), value } +static char * +enum_map_name(const char *name, size_t namelen) +{ + static char buf[SIZEOF_STR]; + int bufpos; + + for (bufpos = 0; bufpos <= namelen; bufpos++) { + buf[bufpos] = tolower(name[bufpos]); + if (buf[bufpos] == '_') + buf[bufpos] = '-'; + } + + buf[bufpos] = 0; + return buf; +} + +#define enum_name(entry) enum_map_name((entry).name, (entry).namelen) + static bool map_enum_do(const struct enum_map *map, size_t map_size, int *value, const char *name) { @@ -497,9 +515,22 @@ init_io_rd(struct io *io, const char *argv[], const char *dir, } static bool -io_open(struct io *io, const char *name) +io_open(struct io *io, const char *fmt, ...) { + char name[SIZEOF_STR] = ""; + bool fits; + va_list args; + init_io(io, NULL, IO_FD); + + va_start(args, fmt); + fits = vsnprintf(name, sizeof(name), fmt, args) < sizeof(name); + va_end(args); + + if (!fits) { + io->error = ENAMETOOLONG; + return FALSE; + } io->pipe = *name ? open(name, O_RDONLY) : STDIN_FILENO; if (io->pipe == -1) io->error = errno; @@ -981,9 +1012,9 @@ static char opt_head[SIZEOF_REF] = ""; static char opt_head_rev[SIZEOF_REV] = ""; static char opt_remote[SIZEOF_REF] = ""; static char opt_encoding[20] = "UTF-8"; -static bool opt_utf8 = TRUE; static char opt_codeset[20] = "UTF-8"; -static iconv_t opt_iconv = ICONV_NONE; +static iconv_t opt_iconv_in = ICONV_NONE; +static iconv_t opt_iconv_out = ICONV_NONE; static char opt_search[SIZEOF_STR] = ""; static char opt_cdup[SIZEOF_STR] = ""; static char opt_prefix[SIZEOF_STR] = ""; @@ -1690,8 +1721,9 @@ option_set_command(int argc, const char *argv[]) } else if (!strcmp(argv[2], "short")) { opt_date = DATE_SHORT; return OK; - } else if (parse_bool(&show_date, argv[2])) { + } else if (parse_bool(&show_date, argv[2]) == OK) { opt_date = show_date ? DATE_DEFAULT : DATE_NONE; + return OK; } return ERR; } @@ -1852,7 +1884,7 @@ load_option_file(const char *path) struct io io = {}; /* It's OK that the file doesn't exist. */ - if (!io_open(&io, path)) + if (!io_open(&io, "%s", path)) return; config_lineno = 0; @@ -2047,6 +2079,7 @@ static int draw_chars(struct view *view, enum line_type type, const char *string, int max_len, bool use_tilde) { + static char out_buffer[BUFSIZ * 2]; int len = 0; int col = 0; int trimmed = FALSE; @@ -2055,22 +2088,28 @@ draw_chars(struct view *view, enum line_type type, const char *string, if (max_len <= 0) return 0; - if (opt_utf8) { - len = utf8_length(&string, skip, &col, max_len, &trimmed, use_tilde); - } else { - col = len = strlen(string); - if (len > max_len) { - if (use_tilde) { - max_len -= 1; + len = utf8_length(&string, skip, &col, max_len, &trimmed, use_tilde); + + set_view_attr(view, type); + if (len > 0) { + if (opt_iconv_out != ICONV_NONE) { + ICONV_CONST char *inbuf = (ICONV_CONST char *) string; + size_t inlen = len + 1; + + char *outbuf = out_buffer; + size_t outlen = sizeof(out_buffer); + + size_t ret; + + ret = iconv(opt_iconv_out, &inbuf, &inlen, &outbuf, &outlen); + if (ret != (size_t) -1) { + string = out_buffer; + len = sizeof(out_buffer) - outlen; } - col = len = max_len; - trimmed = TRUE; } - } - set_view_attr(view, type); - if (len > 0) waddnstr(view->win, string, len); + } if (trimmed && use_tilde) { set_view_attr(view, LINE_DELIMITER); waddch(view->win, '~'); @@ -2438,9 +2477,9 @@ toggle_date_option(enum date *date) "short" }; - opt_date = (opt_date + 1) % ARRAY_SIZE(help); + *date = (*date + 1) % ARRAY_SIZE(help); redraw_display(FALSE); - report("Displaying %s dates", help[opt_date]); + report("Displaying %s dates", help[*date]); } static void @@ -2983,7 +3022,7 @@ prepare_update_file(struct view *view, const char *name) { if (view->pipe) end_update(view, TRUE); - return io_open(&view->io, name); + return io_open(&view->io, "%s", name); } static bool @@ -3043,7 +3082,7 @@ update_view(struct view *view) } for (; (line = io_get(view->pipe, '\n', can_read)); can_read = FALSE) { - if (opt_iconv != ICONV_NONE) { + if (opt_iconv_in != ICONV_NONE) { ICONV_CONST char *inbuf = line; size_t inlen = strlen(line) + 1; @@ -3052,7 +3091,7 @@ update_view(struct view *view) size_t ret; - ret = iconv(opt_iconv, &inbuf, &inlen, &outbuf, &outlen); + ret = iconv(opt_iconv_in, &inbuf, &inlen, &outbuf, &outlen); if (ret != (size_t) -1) line = out_buffer; } @@ -3223,11 +3262,9 @@ open_view(struct view *prev, enum request request, enum open_flags flags) do_scroll_view(prev, lines); } - if (prev && view != prev) { - if (split) { - /* "Blur" the previous view. */ - update_view_title(prev); - } + if (prev && view != prev && split && view_is_displayed(prev)) { + /* "Blur" the previous view. */ + update_view_title(prev); } if (view->pipe && view->lines == 0) { @@ -3943,33 +3980,14 @@ static struct view_ops diff_ops = { static bool help_keymap_hidden[ARRAY_SIZE(keymap_table)]; -static char * -help_name(char buf[SIZEOF_STR], const char *name, size_t namelen) -{ - int bufpos; - - for (bufpos = 0; bufpos <= namelen; bufpos++) { - buf[bufpos] = tolower(name[bufpos]); - if (buf[bufpos] == '_') - buf[bufpos] = '-'; - } - - buf[bufpos] = 0; - return buf; -} - -#define help_keymap_name(buf, keymap) \ - help_name(buf, keymap_table[keymap].name, keymap_table[keymap].namelen) - static bool help_open_keymap_title(struct view *view, enum keymap keymap) { - char buf[SIZEOF_STR]; struct line *line; line = add_line_format(view, LINE_HELP_KEYMAP, "[%c] %s bindings", help_keymap_hidden[keymap] ? '+' : '-', - help_keymap_name(buf, keymap)); + enum_name(keymap_table[keymap])); if (line) line->other = keymap; @@ -4010,8 +4028,7 @@ help_open_keymap(struct view *view, enum keymap keymap) } add_line_format(view, LINE_DEFAULT, " %-25s %-20s %s", key, - help_name(buf, req_info[i].name, req_info[i].namelen), - req_info[i].help); + enum_name(req_info[i]), req_info[i].help); } group = "External commands:"; @@ -4642,10 +4659,7 @@ blame_open(struct view *view) return FALSE; } - if (!string_format(path, "%s%s", opt_cdup, opt_file)) - return FALSE; - - if (*opt_ref || !io_open(&view->io, path)) { + if (*opt_ref || !io_open(&view->io, "%s%s", opt_cdup, opt_file)) { if (!run_io_rd(&view->io, blame_cat_file_argv, opt_cdup, FORMAT_ALL)) return FALSE; } @@ -5026,9 +5040,11 @@ static struct view_ops blame_ops = { struct branch { const char *author; /* Author of the last commit. */ time_t time; /* Date of the last activity. */ - struct ref *ref; /* Name and commit ID information. */ + const struct ref *ref; /* Name and commit ID information. */ }; +static const struct ref branch_all; + static const enum sort_field branch_sort_fields[] = { ORDERBY_NAME, ORDERBY_DATE, ORDERBY_AUTHOR }; @@ -5065,13 +5081,15 @@ branch_draw(struct view *view, struct line *line, unsigned int lineno) if (opt_author && draw_author(view, branch->author)) return TRUE; - draw_text(view, type, branch->ref->name, TRUE); + draw_text(view, type, branch->ref == &branch_all ? "All branches" : branch->ref->name, TRUE); return TRUE; } static enum request branch_request(struct view *view, enum request request, struct line *line) { + struct branch *branch = line->data; + switch (request) { case REQ_REFRESH: load_refs(); @@ -5084,7 +5102,21 @@ branch_request(struct view *view, enum request request, struct line *line) return REQ_NONE; case REQ_ENTER: - open_view(view, REQ_VIEW_MAIN, OPEN_SPLIT); + if (branch->ref == &branch_all) { + const char *all_branches_argv[] = { + "git", "log", "--no-color", "--pretty=raw", "--parents", + "--topo-order", "--all", NULL + }; + struct view *main_view = VIEW(REQ_VIEW_MAIN); + + if (!prepare_update(main_view, all_branches_argv, NULL, FORMAT_NONE)) { + report("Failed to load view of all branches"); + return REQ_NONE; + } + open_view(view, REQ_VIEW_MAIN, OPEN_PREPARED | OPEN_SPLIT); + } else { + open_view(view, REQ_VIEW_MAIN, OPEN_SPLIT); + } return REQ_NONE; default: @@ -5134,7 +5166,7 @@ branch_read(struct view *view, char *line) } static bool -branch_open_visitor(void *data, struct ref *ref) +branch_open_visitor(void *data, const struct ref *ref) { struct view *view = data; struct branch *branch; @@ -5164,6 +5196,7 @@ branch_open(struct view *view) } setup_update(view, view->id); + branch_open_visitor(view, &branch_all); foreach_ref(branch_open_visitor, view); view->p_restore = TRUE; @@ -5277,7 +5310,7 @@ status_run(struct view *view, const char *argv[], char status, enum line_type ty char *buf; struct io io = {}; - if (!run_io(&io, argv, NULL, IO_RD)) + if (!run_io(&io, argv, opt_cdup, IO_RD)) return FALSE; add_line_data(view, NULL, type); @@ -5427,8 +5460,7 @@ status_update_onbranch(void) if (!*opt_head) { struct io io = {}; - if (string_format(buf, "%s/rebase-merge/head-name", opt_git_dir) && - io_open(&io, buf) && + if (io_open(&io, "%s/rebase-merge/head-name", opt_git_dir) && io_read_buf(&io, buf, sizeof(buf))) { head = buf; if (!prefixcmp(head, "refs/heads/")) @@ -5676,10 +5708,8 @@ status_update_prepare(struct io *io, enum line_type type) return run_io(io, staged_argv, opt_cdup, IO_WR); case LINE_STAT_UNSTAGED: - return run_io(io, others_argv, opt_cdup, IO_WR); - case LINE_STAT_UNTRACKED: - return run_io(io, others_argv, NULL, IO_WR); + return run_io(io, others_argv, opt_cdup, IO_WR); default: die("line type %d not handled in switch", type); @@ -5805,9 +5835,8 @@ status_revert(struct status *status, enum line_type type, bool has_none) } else { report("Cannot revert changes to multiple files"); } - return FALSE; - } else { + } else if (prompt_yesno("Are you sure you want to revert changes?")) { char mode[10] = "100644"; const char *reset_argv[] = { "git", "update-index", "--cacheinfo", mode, @@ -5817,12 +5846,25 @@ status_revert(struct status *status, enum line_type type, bool has_none) "git", "checkout", "--", status->old.name, NULL }; - if (!prompt_yesno("Are you sure you want to overwrite any changes?")) - return FALSE; - string_format(mode, "%o", status->old.mode); - return (status->status != 'U' || run_io_fg(reset_argv, opt_cdup)) && - run_io_fg(checkout_argv, opt_cdup); + if (status->status == 'U') { + string_format(mode, "%5o", status->old.mode); + + if (status->old.mode == 0 && status->new.mode == 0) { + reset_argv[2] = "--force-remove"; + reset_argv[3] = status->old.name; + reset_argv[4] = NULL; + } + + if (!run_io_fg(reset_argv, opt_cdup)) + return FALSE; + if (status->old.mode == 0 && status->new.mode == 0) + return TRUE; + } + + return run_io_fg(checkout_argv, opt_cdup); } + + return FALSE; } static enum request @@ -5861,10 +5903,8 @@ status_request(struct view *view, enum request request, struct line *line) break; case REQ_VIEW_BLAME: - if (status) { - string_copy(opt_file, status->new.name); + if (status) opt_ref[0] = 0; - } return request; case REQ_ENTER: @@ -5931,6 +5971,8 @@ status_select(struct view *view, struct line *line) } string_format(view->ref, text, key, file); + if (status) + string_copy(opt_file, status->new.name); } static bool @@ -7186,7 +7228,7 @@ compare_refs(const void *ref1_, const void *ref2_) } static void -foreach_ref(bool (*visitor)(void *data, struct ref *ref), void *data) +foreach_ref(bool (*visitor)(void *data, const struct ref *ref), void *data) { size_t i; @@ -7660,12 +7702,15 @@ main(int argc, const char *argv[]) if (!opt_git_dir[0] && request != REQ_VIEW_PAGER) die("Not a git repository"); - if (*opt_encoding && strcasecmp(opt_encoding, "UTF-8")) - opt_utf8 = FALSE; + if (*opt_encoding && strcmp(opt_codeset, "UTF-8")) { + opt_iconv_in = iconv_open("UTF-8", opt_encoding); + if (opt_iconv_in == ICONV_NONE) + die("Failed to initialize character set conversion"); + } - if (*opt_codeset && strcmp(opt_codeset, opt_encoding)) { - opt_iconv = iconv_open(opt_codeset, opt_encoding); - if (opt_iconv == ICONV_NONE) + if (*opt_codeset && strcmp(opt_codeset, "UTF-8")) { + opt_iconv_out = iconv_open(opt_codeset, "UTF-8"); + if (opt_iconv_out == ICONV_NONE) die("Failed to initialize character set conversion"); }