X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=tig.c;h=222b3698de6bcc60395ab74519b4c9048e2e5ed6;hb=29b1fccb6aaa8140fc2fdf82d750891444379ce1;hp=e52185e4be36b0f15174ff2faad7e2c50196c933;hpb=ac66fdb0a7d9af37eeecc59c0fd284f6b065d7fe;p=tig.git diff --git a/tig.c b/tig.c index e52185e..222b369 100644 --- a/tig.c +++ b/tig.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -103,6 +104,7 @@ static size_t utf8_length(const char **string, size_t col, int *width, size_t ma /* The format and size of the date column in the main view. */ #define DATE_FORMAT "%Y-%m-%d %H:%M" #define DATE_COLS STRING_SIZE("2006-04-29 14:21 ") +#define DATE_SHORT_COLS STRING_SIZE("2006-04-29 ") #define ID_COLS 8 @@ -112,10 +114,6 @@ static size_t utf8_length(const char **string, size_t col, int *width, size_t ma #define S_ISGITLINK(mode) (((mode) & S_IFMT) == 0160000) -#ifndef GIT_CONFIG -#define GIT_CONFIG "config" -#endif - /* Some ASCII-shorthands fitted into the ncurses namespace. */ #define KEY_TAB '\t' #define KEY_RETURN '\r' @@ -339,12 +337,75 @@ suffixcmp(const char *str, int slen, const char *suffix) } -static const char * -mkdate(const time_t *time) +/* + * What value of "tz" was in effect back then at "time" in the + * local timezone? + */ +static int local_tzoffset(time_t time) +{ + time_t t, t_local; + struct tm tm; + int offset, eastwest; + + t = time; + localtime_r(&t, &tm); + t_local = mktime(&tm); + + if (t_local < t) { + eastwest = -1; + offset = t - t_local; + } else { + eastwest = 1; + offset = t_local - t; + } + offset /= 60; /* in minutes */ + offset = (offset % 60) + ((offset / 60) * 100); + return offset * eastwest; +} + +enum date { + DATE_NONE = 0, + DATE_DEFAULT, + DATE_RELATIVE, + DATE_SHORT +}; + +static char * +string_date(const time_t *time, enum date date) { static char buf[DATE_COLS + 1]; + static const struct enum_map reldate[] = { + { "second", 1, 60 * 2 }, + { "minute", 60, 60 * 60 * 2 }, + { "hour", 60 * 60, 60 * 60 * 24 * 2 }, + { "day", 60 * 60 * 24, 60 * 60 * 24 * 7 * 2 }, + { "week", 60 * 60 * 24 * 7, 60 * 60 * 24 * 7 * 5 }, + { "month", 60 * 60 * 24 * 30, 60 * 60 * 24 * 30 * 12 }, + }; struct tm tm; + if (date == DATE_RELATIVE) { + struct timeval now; + time_t date = *time + local_tzoffset(*time); + time_t seconds; + int i; + + gettimeofday(&now, NULL); + seconds = now.tv_sec < date ? date - now.tv_sec : now.tv_sec - date; + for (i = 0; i < ARRAY_SIZE(reldate); i++) { + if (seconds >= reldate[i].value) + continue; + + seconds /= reldate[i].namelen; + if (!string_format(buf, "%ld %s%s %s", + seconds, reldate[i].name, + seconds > 1 ? "s" : "", + now.tv_sec >= date ? "ago" : "ahead")) + break; + return buf; + } + } + gmtime_r(time, &tm); return strftime(buf, sizeof(buf), DATE_FORMAT, &tm) ? buf : NULL; } @@ -436,9 +497,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; @@ -584,9 +658,9 @@ run_io_append(const char **argv, enum format_flags flags, int fd) } static bool -run_io_rd(struct io *io, const char **argv, enum format_flags flags) +run_io_rd(struct io *io, const char **argv, const char *dir, enum format_flags flags) { - return init_io_rd(io, argv, NULL, flags) && start_io(io); + return init_io_rd(io, argv, dir, flags) && start_io(io); } static bool @@ -723,7 +797,8 @@ run_io_buf(const char **argv, char buf[], size_t bufsize) { struct io io = {}; - return run_io_rd(&io, argv, FORMAT_NONE) && io_read_buf(&io, buf, bufsize); + return run_io_rd(&io, argv, NULL, FORMAT_NONE) + && io_read_buf(&io, buf, bufsize); } static int @@ -837,6 +912,7 @@ run_io_load(const char **argv, const char *separators, REQ_(OPTIONS, "Open option menu"), \ REQ_(TOGGLE_LINENO, "Toggle line numbers"), \ REQ_(TOGGLE_DATE, "Toggle date display"), \ + REQ_(TOGGLE_DATE_SHORT, "Toggle short (date-only) dates"), \ REQ_(TOGGLE_AUTHOR, "Toggle author display"), \ REQ_(TOGGLE_REV_GRAPH, "Toggle revision graph visualization"), \ REQ_(TOGGLE_REFS, "Toggle reference display (tags/branches)"), \ @@ -900,7 +976,7 @@ get_request(const char *name) */ /* Option and state variables. */ -static bool opt_date = TRUE; +static enum date opt_date = DATE_DEFAULT; static bool opt_author = TRUE; static bool opt_line_number = FALSE; static bool opt_line_graphics = TRUE; @@ -931,6 +1007,7 @@ static FILE *opt_tty = NULL; #define is_initial_commit() (!*opt_head_rev) #define is_head_commit(rev) (!strcmp((rev), "HEAD") || !strcmp(opt_head_rev, (rev))) +#define mkdate(time) string_date(time, opt_date) /* @@ -992,6 +1069,8 @@ LINE(STAT_NONE, "", COLOR_DEFAULT, COLOR_DEFAULT, 0), \ LINE(STAT_STAGED, "", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ LINE(STAT_UNSTAGED,"", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ LINE(STAT_UNTRACKED,"", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ +LINE(HELP_KEYMAP, "", COLOR_CYAN, COLOR_DEFAULT, 0), \ +LINE(HELP_GROUP, "", COLOR_BLUE, COLOR_DEFAULT, 0), \ LINE(BLAME_ID, "", COLOR_MAGENTA, COLOR_DEFAULT, 0) enum line_type { @@ -1083,6 +1162,7 @@ struct line { unsigned int selected:1; unsigned int dirty:1; unsigned int cleareol:1; + unsigned int other:16; void *data; /* User data */ }; @@ -1310,26 +1390,68 @@ get_key_name(int key_value) return seq ? seq : "(no key)"; } +static bool +append_key(char *buf, size_t *pos, const struct keybinding *keybinding) +{ + const char *sep = *pos > 0 ? ", " : ""; + const char *keyname = get_key_name(keybinding->alias); + + return string_nformat(buf, BUFSIZ, pos, "%s%s", sep, keyname); +} + +static bool +append_keymap_request_keys(char *buf, size_t *pos, enum request request, + enum keymap keymap, bool all) +{ + int i; + + for (i = 0; i < keybindings[keymap].size; i++) { + if (keybindings[keymap].data[i].request == request) { + if (!append_key(buf, pos, &keybindings[keymap].data[i])) + return FALSE; + if (!all) + break; + } + } + + return TRUE; +} + +#define get_key(keymap, request) get_keys(keymap, request, FALSE) + static const char * -get_key(enum request request) +get_keys(enum keymap keymap, enum request request, bool all) { static char buf[BUFSIZ]; size_t pos = 0; - char *sep = ""; int i; buf[pos] = 0; - for (i = 0; i < ARRAY_SIZE(default_keybindings); i++) { - const struct keybinding *keybinding = &default_keybindings[i]; + if (!append_keymap_request_keys(buf, &pos, request, keymap, all)) + return "Too many keybindings!"; + if (pos > 0 && !all) + return buf; - if (keybinding->request != request) - continue; + if (keymap != KEYMAP_GENERIC) { + /* Only the generic keymap includes the default keybindings when + * listing all keys. */ + if (all) + return buf; - if (!string_format_from(buf, &pos, "%s%s", sep, - get_key_name(keybinding->alias))) + if (!append_keymap_request_keys(buf, &pos, request, KEYMAP_GENERIC, all)) return "Too many keybindings!"; - sep = ", "; + if (pos) + return buf; + } + + for (i = 0; i < ARRAY_SIZE(default_keybindings); i++) { + if (default_keybindings[i].request == request) { + if (!append_key(buf, &pos, &default_keybindings[i])) + return "Too many keybindings!"; + if (!all) + return buf; + } } return buf; @@ -1572,8 +1694,20 @@ option_set_command(int argc, const char *argv[]) if (!strcmp(argv[0], "show-author")) return parse_bool(&opt_author, argv[2]); - if (!strcmp(argv[0], "show-date")) - return parse_bool(&opt_date, argv[2]); + if (!strcmp(argv[0], "show-date")) { + bool show_date; + + if (!strcmp(argv[2], "relative")) { + opt_date = DATE_RELATIVE; + return OK; + } else if (!strcmp(argv[2], "short")) { + opt_date = DATE_SHORT; + return OK; + } else if (parse_bool(&show_date, argv[2])) { + opt_date = show_date ? DATE_DEFAULT : DATE_NONE; + } + return ERR; + } if (!strcmp(argv[0], "show-rev-graph")) return parse_bool(&opt_rev_graph, argv[2]); @@ -1731,7 +1865,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; @@ -1857,6 +1991,8 @@ struct view_ops { bool (*grep)(struct view *view, struct line *line); /* Select line */ void (*select)(struct view *view, struct line *line); + /* Prepare view for loading */ + bool (*prepare)(struct view *view); }; static struct view_ops blame_ops; @@ -2025,9 +2161,10 @@ draw_field(struct view *view, enum line_type type, const char *text, int len, bo static bool draw_date(struct view *view, time_t *time) { - const char *date = mkdate(time); + const char *date = time ? mkdate(time) : ""; + int cols = opt_date == DATE_SHORT ? DATE_SHORT_COLS : DATE_COLS; - return draw_field(view, LINE_DATE, date, DATE_COLS, FALSE); + return draw_field(view, LINE_DATE, date, cols, FALSE); } static bool @@ -2304,6 +2441,21 @@ redraw_display(bool clear) } } +static void +toggle_date_option(enum date *date) +{ + static const char *help[] = { + "no", + "default", + "relative", + "short" + }; + + opt_date = (opt_date + 1) % ARRAY_SIZE(help); + redraw_display(FALSE); + report("Displaying %s dates", help[opt_date]); +} + static void toggle_view_option(bool *option, const char *help) { @@ -2325,8 +2477,12 @@ open_option_menu(void) }; int selected = 0; - if (prompt_menu("Toggle option", menu, &selected)) - toggle_view_option(menu[selected].data, menu[selected].text); + if (prompt_menu("Toggle option", menu, &selected)) { + if (menu[selected].data == &opt_date) + toggle_date_option(menu[selected].data); + else + toggle_view_option(menu[selected].data, menu[selected].text); + } } static void @@ -2840,7 +2996,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 @@ -2849,16 +3005,13 @@ begin_update(struct view *view, bool refresh) if (view->pipe) end_update(view, TRUE); - if (refresh) { - if (!start_io(&view->io)) - return FALSE; - - } else { - if (view == VIEW(REQ_VIEW_TREE) && strcmp(view->vid, view->id)) - opt_path[0] = 0; - - if (!run_io_rd(&view->io, view->ops->argv, FORMAT_ALL)) + if (!refresh) { + if (view->ops->prepare) { + if (!view->ops->prepare(view)) + return FALSE; + } else if (!init_io_rd(&view->io, view->ops->argv, NULL, FORMAT_ALL)) { return FALSE; + } /* Put the current ref_* value to the view title ref * member. This is needed by the blob view. Most other @@ -2867,6 +3020,9 @@ begin_update(struct view *view, bool refresh) string_copy_rev(view->ref, view->id); } + if (!start_io(&view->io)) + return FALSE; + setup_update(view, view->id); return TRUE; @@ -3045,6 +3201,11 @@ open_view(struct view *prev, enum request request, enum open_flags flags) display[current_view] = view; } + /* No parent signals that this is the first loaded view. */ + if (prev && view != prev) { + view->parent = prev; + } + /* Resize the view when switching between split- and full-screen, * or when switching between two different full-screen views. */ if (nviews != displayed_views() || @@ -3080,8 +3241,6 @@ open_view(struct view *prev, enum request request, enum open_flags flags) /* "Blur" the previous view. */ update_view_title(prev); } - - view->parent = prev; } if (view->pipe && view->lines == 0) { @@ -3205,7 +3364,7 @@ view_driver(struct view *view, enum request request) case REQ_VIEW_BLAME: if (!opt_file[0]) { report("No file chosen, press %s to open tree view", - get_key(REQ_VIEW_TREE)); + get_key(view->keymap, REQ_VIEW_TREE)); break; } open_view(view, request, OPEN_DEFAULT); @@ -3214,7 +3373,7 @@ view_driver(struct view *view, enum request request) case REQ_VIEW_BLOB: if (!ref_blob[0]) { report("No file chosen, press %s to open tree view", - get_key(REQ_VIEW_TREE)); + get_key(view->keymap, REQ_VIEW_TREE)); break; } open_view(view, request, OPEN_DEFAULT); @@ -3223,7 +3382,7 @@ view_driver(struct view *view, enum request request) case REQ_VIEW_PAGER: if (!VIEW(REQ_VIEW_PAGER)->pipe && !VIEW(REQ_VIEW_PAGER)->lines) { report("No pager content, press %s to run command from prompt", - get_key(REQ_PROMPT)); + get_key(view->keymap, REQ_PROMPT)); break; } open_view(view, request, OPEN_DEFAULT); @@ -3232,7 +3391,7 @@ view_driver(struct view *view, enum request request) case REQ_VIEW_STAGE: if (!VIEW(REQ_VIEW_STAGE)->lines) { report("No stage content, press %s to open the status view and choose file", - get_key(REQ_VIEW_STATUS)); + get_key(view->keymap, REQ_VIEW_STATUS)); break; } open_view(view, request, OPEN_DEFAULT); @@ -3319,7 +3478,7 @@ view_driver(struct view *view, enum request request) break; case REQ_TOGGLE_DATE: - toggle_view_option(&opt_date, "date display"); + toggle_date_option(&opt_date); break; case REQ_TOGGLE_AUTHOR: @@ -3389,7 +3548,8 @@ view_driver(struct view *view, enum request request) return FALSE; default: - report("Unknown key, press 'h' for help"); + report("Unknown key, press %s for help", + get_key(view->keymap, REQ_VIEW_HELP)); return TRUE; } @@ -3794,80 +3954,149 @@ static struct view_ops diff_ops = { * Help backend */ +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(struct view *view) +help_open_keymap_title(struct view *view, enum keymap keymap) { char buf[SIZEOF_STR]; - size_t bufpos; - int i; + struct line *line; - if (view->lines > 0) - return TRUE; + line = add_line_format(view, LINE_HELP_KEYMAP, "[%c] %s bindings", + help_keymap_hidden[keymap] ? '+' : '-', + help_keymap_name(buf, keymap)); + if (line) + line->other = keymap; - add_line_text(view, "Quick reference for tig keybindings:", LINE_DEFAULT); + return help_keymap_hidden[keymap]; +} + +static void +help_open_keymap(struct view *view, enum keymap keymap) +{ + const char *group = NULL; + char buf[SIZEOF_STR]; + size_t bufpos; + bool add_title = TRUE; + int i; for (i = 0; i < ARRAY_SIZE(req_info); i++) { - const char *key; + const char *key = NULL; if (req_info[i].request == REQ_NONE) continue; if (!req_info[i].request) { - add_line_text(view, "", LINE_DEFAULT); - add_line_text(view, req_info[i].help, LINE_DEFAULT); + group = req_info[i].help; continue; } - key = get_key(req_info[i].request); - if (!*key) - key = "(no key defined)"; + key = get_keys(keymap, req_info[i].request, TRUE); + if (!key || !*key) + continue; - for (bufpos = 0; bufpos <= req_info[i].namelen; bufpos++) { - buf[bufpos] = tolower(req_info[i].name[bufpos]); - if (buf[bufpos] == '_') - buf[bufpos] = '-'; + if (add_title && help_open_keymap_title(view, keymap)) + return; + add_title = false; + + if (group) { + add_line_text(view, group, LINE_HELP_GROUP); + group = NULL; } - add_line_format(view, LINE_DEFAULT, " %-25s %-20s %s", - key, buf, req_info[i].help); + 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); } - if (run_requests) { - add_line_text(view, "", LINE_DEFAULT); - add_line_text(view, "External commands:", LINE_DEFAULT); - } + group = "External commands:"; for (i = 0; i < run_requests; i++) { struct run_request *req = get_run_request(REQ_NONE + i + 1); const char *key; int argc; - if (!req) + if (!req || req->keymap != keymap) continue; key = get_key_name(req->key); if (!*key) key = "(no key defined)"; + if (add_title && help_open_keymap_title(view, keymap)) + return; + if (group) { + add_line_text(view, group, LINE_HELP_GROUP); + group = NULL; + } + for (bufpos = 0, argc = 0; req->argv[argc]; argc++) if (!string_format_from(buf, &bufpos, "%s%s", argc ? " " : "", req->argv[argc])) - return REQ_NONE; + return; - add_line_format(view, LINE_DEFAULT, " %-10s %-14s `%s`", - keymap_table[req->keymap].name, key, buf); + add_line_format(view, LINE_DEFAULT, " %-25s `%s`", key, buf); } +} + +static bool +help_open(struct view *view) +{ + enum keymap keymap; + + reset_view(view); + add_line_text(view, "Quick reference for tig keybindings:", LINE_DEFAULT); + add_line_text(view, "", LINE_DEFAULT); + + for (keymap = 0; keymap < ARRAY_SIZE(keymap_table); keymap++) + help_open_keymap(view, keymap); return TRUE; } +static enum request +help_request(struct view *view, enum request request, struct line *line) +{ + switch (request) { + case REQ_ENTER: + if (line->type == LINE_HELP_KEYMAP) { + help_keymap_hidden[line->other] = + !help_keymap_hidden[line->other]; + view->p_restore = TRUE; + open_view(view, REQ_VIEW_HELP, OPEN_REFRESH); + } + + return REQ_NONE; + default: + return pager_request(view, request, line); + } +} + static struct view_ops help_ops = { "line", NULL, help_open, NULL, pager_draw, - pager_request, + help_request, pager_grep, pager_select, }; @@ -4035,7 +4264,7 @@ tree_read_date(struct view *view, char *text, bool *read_date) return TRUE; } - if (!run_io_rd(&io, log_file, FORMAT_NONE)) { + if (!run_io_rd(&io, log_file, opt_cdup, FORMAT_NONE)) { report("Failed to load tree data"); return TRUE; } @@ -4058,8 +4287,6 @@ tree_read_date(struct view *view, char *text, bool *read_date) if (!pos) return TRUE; text = pos + 1; - if (*opt_prefix && !strncmp(text, opt_prefix, strlen(opt_prefix))) - text += strlen(opt_prefix); if (*opt_path && !strncmp(text, opt_path, strlen(opt_path))) text += strlen(opt_path); pos = strchr(text, '/'); @@ -4302,6 +4529,32 @@ tree_select(struct view *view, struct line *line) string_copy_rev(view->ref, entry->id); } +static bool +tree_prepare(struct view *view) +{ + if (view->lines == 0 && opt_prefix[0]) { + char *pos = opt_prefix; + + while (pos && *pos) { + char *end = strchr(pos, '/'); + + if (end) + *end = 0; + push_tree_stack_entry(pos, 0); + pos = end; + if (end) { + *end = '/'; + pos++; + } + } + + } else if (strcmp(view->vid, view->id)) { + opt_path[0] = 0; + } + + return init_io_rd(&view->io, view->ops->argv, opt_cdup, FORMAT_ALL); +} + static const char *tree_argv[SIZEOF_ARG] = { "git", "ls-tree", "%(commit)", "%(directory)", NULL }; @@ -4315,6 +4568,7 @@ static struct view_ops tree_ops = { tree_request, tree_grep, tree_select, + tree_prepare, }; static bool @@ -4393,8 +4647,16 @@ struct blame { static bool blame_open(struct view *view) { - if (*opt_ref || !io_open(&view->io, opt_file)) { - if (!run_io_rd(&view->io, blame_cat_file_argv, FORMAT_ALL)) + char path[SIZEOF_STR]; + + if (!view->parent && *opt_prefix) { + string_copy(path, opt_file); + if (!string_format(opt_file, "%s%s", opt_prefix, path)) + return FALSE; + } + + 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; } @@ -4490,7 +4752,7 @@ blame_read_file(struct view *view, const char *line, bool *read_file) if (view->lines == 0 && !view->parent) die("No blame exist for %s", view->vid); - if (view->lines == 0 || !run_io_rd(&io, argv, FORMAT_ALL)) { + if (view->lines == 0 || !run_io_rd(&io, argv, opt_cdup, FORMAT_ALL)) { report("Failed to load blame data"); return TRUE; } @@ -4906,7 +5168,7 @@ branch_open(struct view *view) "--simplify-by-decoration", "--all", NULL }; - if (!run_io_rd(&view->io, branch_log, FORMAT_NONE)) { + if (!run_io_rd(&view->io, branch_log, NULL, FORMAT_NONE)) { report("Failed to load branch data"); return TRUE; } @@ -5175,8 +5437,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/")) @@ -5553,9 +5814,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, @@ -5565,12 +5825,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 @@ -5672,10 +5945,10 @@ status_select(struct view *view, struct line *line) if (status && status->status == 'U') { text = "Press %s to resolve conflict in %s"; - key = get_key(REQ_STATUS_MERGE); + key = get_key(KEYMAP_STATUS, REQ_STATUS_MERGE); } else { - key = get_key(REQ_STATUS_UPDATE); + key = get_key(KEYMAP_STATUS, REQ_STATUS_UPDATE); } string_format(view->ref, text, key, file); @@ -5873,7 +6146,7 @@ stage_request(struct view *view, enum request request, struct line *line) case REQ_STAGE_NEXT: if (stage_line_type == LINE_STAT_UNTRACKED) { report("File is untracked; press %s to add", - get_key(REQ_STATUS_UPDATE)); + get_key(KEYMAP_STAGE, REQ_STATUS_UPDATE)); return REQ_NONE; } stage_next(view, line); @@ -7205,7 +7478,7 @@ read_repo_config_option(char *name, size_t namelen, char *value, size_t valuelen static int load_git_config(void) { - const char *config_list_argv[] = { "git", GIT_CONFIG, "--list", NULL }; + const char *config_list_argv[] = { "git", "config", "--list", NULL }; return run_io_load(config_list_argv, "=", read_repo_config_option); } @@ -7373,8 +7646,8 @@ parse_options(int argc, const char *argv[]) die("command too long"); } - if (!prepare_update(VIEW(request), custom_argv, NULL, FORMAT_NONE)) - die("Failed to format arguments"); + if (!prepare_update(VIEW(request), custom_argv, NULL, FORMAT_NONE)) + die("Failed to format arguments"); return request; }