X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=tig.c;h=77e1d8183372669bc1fed7fda0cbb97ada649417;hb=bb46d935db3f3548bbe2d411f58588943058148c;hp=7cdd3eaa3371202ed2016eec4cb2e9ec03545295;hpb=af1bb582742ee329013278c8e05f6753ef43e49f;p=tig.git diff --git a/tig.c b/tig.c index 7cdd3ea..77e1d81 100644 --- a/tig.c +++ b/tig.c @@ -140,13 +140,6 @@ static struct ref_list *get_ref_list(const char *id); static void foreach_ref(bool (*visitor)(void *data, const struct ref *ref), void *data); static int load_refs(void); -enum format_flags { - FORMAT_ALL, /* Perform replacement in all arguments. */ - FORMAT_NONE /* No replacement should be performed. */ -}; - -static bool format_argv(const char *dst[], const char *src[], enum format_flags flags); - enum input_status { INPUT_OK, INPUT_SKIP, @@ -678,6 +671,27 @@ argv_from_env(const char **argv, const char *name) return !env || argv_from_string(argv, &argc, env); } +static void +argv_free(const char *argv[]) +{ + int argc; + + for (argc = 0; argv[argc]; argc++) + free((void *) argv[argc]); + argv[0] = NULL; +} + +static bool +argv_copy(const char *dst[], const char *src[]) +{ + int argc; + + for (argc = 0; src[argc]; argc++) + if (!(dst[argc] = strdup(src[argc]))) + return FALSE; + return TRUE; +} + /* * Executing external commands. @@ -693,12 +707,9 @@ enum io_type { }; struct io { - enum io_type type; /* The requested type of pipe. */ - const char *dir; /* Directory from which to execute. */ - pid_t pid; /* PID of spawned process. */ int pipe; /* Pipe end for reading or writing. */ + pid_t pid; /* PID of spawned process. */ int error; /* Error status. */ - const char *argv[SIZEOF_ARG]; /* Shell command arguments. */ char *buf; /* Read buffer. */ size_t bufalloc; /* Allocated buffer size. */ size_t bufsize; /* Buffer content size. */ @@ -707,30 +718,10 @@ struct io { }; static void -io_reset(struct io *io) +io_init(struct io *io) { + memset(io, 0, sizeof(*io)); io->pipe = -1; - io->pid = 0; - io->buf = io->bufpos = NULL; - io->bufalloc = io->bufsize = 0; - io->error = 0; - io->eof = 0; -} - -static void -io_init(struct io *io, const char *dir, enum io_type type) -{ - io_reset(io); - io->type = type; - io->dir = dir; -} - -static bool -io_format(struct io *io, const char *dir, enum io_type type, - const char *argv[], enum format_flags flags) -{ - io_init(io, dir, type); - return format_argv(io->argv, argv, flags); } static bool @@ -740,7 +731,7 @@ io_open(struct io *io, const char *fmt, ...) bool fits; va_list args; - io_init(io, NULL, IO_FD); + io_init(io); va_start(args, fmt); fits = vsnprintf(name, sizeof(name), fmt, args) < sizeof(name); @@ -770,7 +761,7 @@ io_done(struct io *io) if (io->pipe != -1) close(io->pipe); free(io->buf); - io_reset(io); + io_init(io); while (pid > 0) { int status; @@ -793,35 +784,37 @@ io_done(struct io *io) } static bool -io_start(struct io *io) +io_run(struct io *io, enum io_type type, const char *dir, const char *argv[], ...) { int pipefds[2] = { -1, -1 }; + va_list args; - if (io->type == IO_FD) - return TRUE; + io_init(io); - if ((io->type == IO_RD || io->type == IO_WR) && pipe(pipefds) < 0) { + if ((type == IO_RD || type == IO_WR) && pipe(pipefds) < 0) { io->error = errno; return FALSE; - } else if (io->type == IO_AP) { - pipefds[1] = io->pipe; + } else if (type == IO_AP) { + va_start(args, argv); + pipefds[1] = va_arg(args, int); + va_end(args); } if ((io->pid = fork())) { if (io->pid == -1) io->error = errno; - if (pipefds[!(io->type == IO_WR)] != -1) - close(pipefds[!(io->type == IO_WR)]); + if (pipefds[!(type == IO_WR)] != -1) + close(pipefds[!(type == IO_WR)]); if (io->pid != -1) { - io->pipe = pipefds[!!(io->type == IO_WR)]; + io->pipe = pipefds[!!(type == IO_WR)]; return TRUE; } } else { - if (io->type != IO_FG) { + if (type != IO_FG) { int devnull = open("/dev/null", O_RDWR); - int readfd = io->type == IO_WR ? pipefds[0] : devnull; - int writefd = (io->type == IO_RD || io->type == IO_AP) + int readfd = type == IO_WR ? pipefds[0] : devnull; + int writefd = (type == IO_RD || type == IO_AP) ? pipefds[1] : devnull; dup2(readfd, STDIN_FILENO); @@ -835,71 +828,42 @@ io_start(struct io *io) close(pipefds[1]); } - if (io->dir && *io->dir && chdir(io->dir) == -1) + if (dir && *dir && chdir(dir) == -1) exit(errno); - execvp(io->argv[0], (char *const*) io->argv); + execvp(argv[0], (char *const*) argv); exit(errno); } - if (pipefds[!!(io->type == IO_WR)] != -1) - close(pipefds[!!(io->type == IO_WR)]); + if (pipefds[!!(type == IO_WR)] != -1) + close(pipefds[!!(type == IO_WR)]); return FALSE; } static bool -io_run(struct io *io, const char **argv, const char *dir, enum io_type type) +io_complete(enum io_type type, const char **argv, const char *dir, int fd) { - io_init(io, dir, type); - if (!format_argv(io->argv, argv, FORMAT_NONE)) - return FALSE; - return io_start(io); -} + struct io io; -static int -io_complete(struct io *io) -{ - return io_start(io) && io_done(io); + return io_run(&io, type, dir, argv, fd) && io_done(&io); } -static int +static bool io_run_bg(const char **argv) { - struct io io = {}; - - if (!io_format(&io, NULL, IO_BG, argv, FORMAT_NONE)) - return FALSE; - return io_complete(&io); + return io_complete(IO_BG, argv, NULL, -1); } static bool io_run_fg(const char **argv, const char *dir) { - struct io io = {}; - - if (!io_format(&io, dir, IO_FG, argv, FORMAT_NONE)) - return FALSE; - return io_complete(&io); -} - -static bool -io_run_append(const char **argv, enum format_flags flags, int fd) -{ - struct io io = {}; - - if (!io_format(&io, NULL, IO_AP, argv, flags)) { - close(fd); - return FALSE; - } - - io.pipe = fd; - return io_complete(&io); + return io_complete(IO_FG, argv, dir, -1); } static bool -io_run_rd(struct io *io, const char **argv, const char *dir, enum format_flags flags) +io_run_append(const char **argv, int fd) { - return io_format(io, dir, IO_RD, argv, flags) && io_start(io); + return io_complete(IO_AP, argv, NULL, fd); } static bool @@ -1034,10 +998,9 @@ io_read_buf(struct io *io, char buf[], size_t bufsize) static bool io_run_buf(const char **argv, char buf[], size_t bufsize) { - struct io io = {}; + struct io io; - return io_run_rd(&io, argv, NULL, FORMAT_NONE) - && io_read_buf(&io, buf, bufsize); + return io_run(&io, IO_RD, NULL, argv) && io_read_buf(&io, buf, bufsize); } static int @@ -1047,9 +1010,6 @@ io_load(struct io *io, const char *separators, char *name; int state = OK; - if (!io_start(io)) - return ERR; - while (state == OK && (name = io_get(io, '\n', TRUE))) { char *value; size_t namelen; @@ -1082,10 +1042,11 @@ static int io_run_load(const char **argv, const char *separators, int (*read_property)(char *, size_t, char *, size_t)) { - struct io io = {}; + struct io io; - return io_format(&io, NULL, IO_RD, argv, FORMAT_NONE) - ? io_load(&io, separators, read_property) : ERR; + if (!io_run(&io, IO_RD, NULL, argv)) + return ERR; + return io_load(&io, separators, read_property); } @@ -1279,6 +1240,8 @@ LINE(AUTHOR, "author ", COLOR_GREEN, COLOR_DEFAULT, 0), \ LINE(COMMITTER, "committer ", COLOR_MAGENTA, COLOR_DEFAULT, 0), \ LINE(SIGNOFF, " Signed-off-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \ LINE(ACKED, " Acked-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \ +LINE(TESTED, " Tested-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \ +LINE(REVIEWED, " Reviewed-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \ LINE(DEFAULT, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \ LINE(CURSOR, "", COLOR_WHITE, COLOR_GREEN, A_BOLD), \ LINE(STATUS, "", COLOR_GREEN, COLOR_DEFAULT, 0), \ @@ -1522,6 +1485,14 @@ static void add_keybinding(enum keymap keymap, enum request request, int key) { struct keybinding_table *table = &keybindings[keymap]; + size_t i; + + for (i = 0; i < keybindings[keymap].size; i++) { + if (keybindings[keymap].data[i].alias == key) { + keybindings[keymap].data[i].request = request; + return; + } + } table->data = realloc(table->data, (table->size + 1) * sizeof(*table->data)); if (!table->data) @@ -1727,7 +1698,7 @@ add_run_request(enum keymap keymap, int key, int argc, const char **argv) req->key = key; req->argv[0] = NULL; - if (!format_argv(req->argv, argv, FORMAT_NONE)) + if (!argv_copy(req->argv, argv)) return REQ_NONE; return REQ_NONE + ++run_requests; @@ -1762,8 +1733,10 @@ add_builtin_run_requests(void) int i; for (i = 0; i < ARRAY_SIZE(reqs); i++) { - enum request req; + enum request req = get_keybinding(reqs[i].keymap, reqs[i].key); + if (req != reqs[i].key) + continue; req = add_run_request(reqs[i].keymap, reqs[i].key, reqs[i].argc, reqs[i].argv); if (req != REQ_NONE) add_keybinding(reqs[i].keymap, req, reqs[i].key); @@ -2009,7 +1982,7 @@ option_bind_command(int argc, const char *argv[]) return ERR; } - if (set_keymap(&keymap, argv[0]) == ERR) { + if (!set_keymap(&keymap, argv[0])) { config_msg = "Unknown key map"; return ERR; } @@ -2115,7 +2088,7 @@ read_option(char *opt, size_t optlen, char *value, size_t valuelen) static void load_option_file(const char *path) { - struct io io = {}; + struct io io; /* It's OK that the file doesn't exist. */ if (!io_open(&io, "%s", path)) @@ -2137,8 +2110,6 @@ load_options(void) const char *tigrc_system = getenv("TIGRC_SYSTEM"); char buf[SIZEOF_STR]; - add_builtin_run_requests(); - if (!tigrc_system) tigrc_system = SYSCONFDIR "/tigrc"; load_option_file(tigrc_system); @@ -2150,6 +2121,10 @@ load_options(void) } load_option_file(tigrc_user); + /* Add _after_ loading config files to avoid adding run requests + * that conflict with keybindings. */ + add_builtin_run_requests(); + return OK; } @@ -2200,7 +2175,6 @@ struct view { enum keymap keymap; /* What keymap does this view have */ bool git_dir; /* Whether the view requires a git directory. */ - bool refresh; /* Whether the view supports refreshing. */ char ref[SIZEOF_REF]; /* Hovered commit reference */ char vid[SIZEOF_REF]; /* View ID. Set to id member when updating. */ @@ -2225,6 +2199,7 @@ struct view { /* If non-NULL, points to the view that opened this view. If this view * is closed tig will switch back to the parent view. */ struct view *parent; + struct view *prev; /* Buffering */ size_t lines; /* Total number of lines */ @@ -2238,6 +2213,8 @@ struct view { bool has_scrolled; /* View was scrolled. */ /* Loading */ + const char *argv[SIZEOF_ARG]; /* Shell command arguments. */ + const char *dir; /* Directory from which to execute. */ struct io io; struct io *pipe; time_t start_time; @@ -2277,24 +2254,24 @@ static struct view_ops status_ops; static struct view_ops tree_ops; static struct view_ops branch_ops; -#define VIEW_STR(type, name, env, ref, ops, map, git, refresh) \ - { type, name, #env, ref, ops, map, git, refresh } +#define VIEW_STR(type, name, env, ref, ops, map, git) \ + { type, name, #env, ref, ops, map, git } -#define VIEW_(id, name, ops, git, refresh, ref) \ - VIEW_STR(VIEW_##id, name, TIG_##id##_CMD, ref, ops, KEYMAP_##id, git, refresh) +#define VIEW_(id, name, ops, git, ref) \ + VIEW_STR(VIEW_##id, name, TIG_##id##_CMD, ref, ops, KEYMAP_##id, git) static struct view views[] = { - VIEW_(MAIN, "main", &main_ops, TRUE, TRUE, ref_head), - VIEW_(DIFF, "diff", &diff_ops, TRUE, FALSE, ref_commit), - VIEW_(LOG, "log", &log_ops, TRUE, TRUE, ref_head), - VIEW_(TREE, "tree", &tree_ops, TRUE, FALSE, ref_commit), - VIEW_(BLOB, "blob", &blob_ops, TRUE, FALSE, ref_blob), - VIEW_(BLAME, "blame", &blame_ops, TRUE, FALSE, ref_commit), - VIEW_(BRANCH, "branch", &branch_ops, TRUE, TRUE, ref_head), - VIEW_(HELP, "help", &help_ops, FALSE, FALSE, ""), - VIEW_(PAGER, "pager", &pager_ops, FALSE, FALSE, "stdin"), - VIEW_(STATUS, "status", &status_ops, TRUE, TRUE, ""), - VIEW_(STAGE, "stage", &stage_ops, TRUE, TRUE, ""), + VIEW_(MAIN, "main", &main_ops, TRUE, ref_head), + VIEW_(DIFF, "diff", &diff_ops, TRUE, ref_commit), + VIEW_(LOG, "log", &log_ops, TRUE, ref_head), + VIEW_(TREE, "tree", &tree_ops, TRUE, ref_commit), + VIEW_(BLOB, "blob", &blob_ops, TRUE, ref_blob), + VIEW_(BLAME, "blame", &blame_ops, TRUE, ref_commit), + VIEW_(BRANCH, "branch", &branch_ops, TRUE, ref_head), + VIEW_(HELP, "help", &help_ops, FALSE, ""), + VIEW_(PAGER, "pager", &pager_ops, FALSE, "stdin"), + VIEW_(STATUS, "status", &status_ops, TRUE, ""), + VIEW_(STAGE, "stage", &stage_ops, TRUE, ""), }; #define VIEW(req) (&views[(req) - REQ_OFFSET - 1]) @@ -2305,8 +2282,18 @@ static struct view views[] = { #define view_is_displayed(view) \ (view == display[0] || view == display[1]) -#define view_has_parent(view, child_type, parent_type) \ - (view->type == child_type && view->parent && view->parent->type == parent_type) +static enum request +view_request(struct view *view, enum request request) +{ + if (!view || !view->lines) + return request; + return view->ops->request(view, request, &view->line[view->lineno]); +} + + +/* + * View drawing. + */ static inline void set_view_attr(struct view *view, enum line_type type) @@ -2697,6 +2684,11 @@ redraw_display(bool clear) } } + +/* + * Option management + */ + static void toggle_enum_option_do(unsigned int *opt, const char *help, const struct enum_map *map, size_t size) @@ -3120,15 +3112,6 @@ reset_view(struct view *view) view->update_secs = 0; } -static void -free_argv(const char *argv[]) -{ - int argc; - - for (argc = 0; argv[argc]; argc++) - free((void *) argv[argc]); -} - static const char * format_arg(const char *name) { @@ -3159,13 +3142,12 @@ format_arg(const char *name) } static bool -format_argv(const char *dst_argv[], const char *src_argv[], enum format_flags flags) +format_argv(const char *dst_argv[], const char *src_argv[], bool replace) { char buf[SIZEOF_STR]; int argc; - bool noreplace = flags == FORMAT_NONE; - free_argv(dst_argv); + argv_free(dst_argv); for (argc = 0; src_argv[argc]; argc++) { const char *arg = src_argv[argc]; @@ -3176,7 +3158,7 @@ format_argv(const char *dst_argv[], const char *src_argv[], enum format_flags fl int len = next - arg; const char *value; - if (!next || noreplace) { + if (!next || !replace) { len = strlen(arg); value = ""; @@ -3191,7 +3173,7 @@ format_argv(const char *dst_argv[], const char *src_argv[], enum format_flags fl if (!string_format_from(buf, &bufpos, "%.*s%s", len, arg, value)) return FALSE; - arg = next && !noreplace ? strchr(next, ')') + 1 : NULL; + arg = next && replace ? strchr(next, ')') + 1 : NULL; } dst_argv[argc] = strdup(buf); @@ -3250,12 +3232,28 @@ setup_update(struct view *view, const char *vid) view->start_time = time(NULL); } +static bool +prepare_io(struct view *view, const char *dir, const char *argv[], bool replace) +{ + view->dir = dir; + return format_argv(view->argv, argv, replace); +} + static bool prepare_update(struct view *view, const char *argv[], const char *dir) { if (view->pipe) end_update(view, TRUE); - return io_format(&view->io, dir, IO_RD, argv, FORMAT_NONE); + return prepare_io(view, dir, argv, FALSE); +} + +static bool +start_update(struct view *view, const char **argv, const char *dir) +{ + if (view->pipe) + io_done(view->pipe); + return prepare_io(view, dir, argv, FALSE) && + io_run(&view->io, IO_RD, dir, view->argv); } static bool @@ -3263,6 +3261,7 @@ prepare_update_file(struct view *view, const char *name) { if (view->pipe) end_update(view, TRUE); + argv_free(view->argv); return io_open(&view->io, "%s/%s", opt_cdup[0] ? opt_cdup : ".", name); } @@ -3276,7 +3275,7 @@ begin_update(struct view *view, bool refresh) if (view->ops->prepare) { if (!view->ops->prepare(view)) return FALSE; - } else if (!io_format(&view->io, NULL, IO_RD, view->ops->argv, FORMAT_ALL)) { + } else if (!prepare_io(view, NULL, view->ops->argv, TRUE)) { return FALSE; } @@ -3287,7 +3286,7 @@ begin_update(struct view *view, bool refresh) string_copy_rev(view->ref, view->id); } - if (!io_start(&view->io)) + if (view->argv[0] && !io_run(&view->io, IO_RD, view->dir, view->argv)) return FALSE; setup_update(view, view->id); @@ -3364,7 +3363,8 @@ update_view(struct view *view) end_update(view, TRUE); } else if (io_eof(view->pipe)) { - report(""); + if (view_is_displayed(view)) + report(""); end_update(view, FALSE); } @@ -3461,6 +3461,7 @@ open_view(struct view *prev, enum request request, enum open_flags flags) if (split) { display[1] = view; current_view = 1; + view->parent = prev; } else if (!nomaximize) { /* Maximize the current view. */ memset(display, 0, sizeof(display)); @@ -3468,9 +3469,9 @@ 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. */ + /* No prev signals that this is the first loaded view. */ if (prev && view != prev) { - view->parent = prev; + view->prev = prev; } /* Resize the view when switching between split- and full-screen, @@ -3571,9 +3572,9 @@ open_run_request(enum request request) return; } - if (format_argv(argv, req->argv, FORMAT_ALL)) + if (format_argv(argv, req->argv, TRUE)) open_external_viewer(argv, NULL); - free_argv(argv); + argv_free(argv); } /* @@ -3590,18 +3591,13 @@ view_driver(struct view *view, enum request request) if (request > REQ_NONE) { open_run_request(request); - /* FIXME: When all views can refresh always do this. */ - if (view->refresh) - request = REQ_REFRESH; - else - return TRUE; + view_request(view, REQ_REFRESH); + return TRUE; } - if (view && view->lines) { - request = view->ops->request(view, request, &view->line[view->lineno]); - if (request == REQ_NONE) - return TRUE; - } + request = view_request(view, request); + if (request == REQ_NONE) + return TRUE; switch (request) { case REQ_MOVE_UP: @@ -3679,11 +3675,7 @@ view_driver(struct view *view, enum request request) case REQ_PREVIOUS: request = request == REQ_NEXT ? REQ_MOVE_DOWN : REQ_MOVE_UP; - if (view_has_parent(view, VIEW_DIFF, VIEW_MAIN) || - view_has_parent(view, VIEW_DIFF, VIEW_BLAME) || - view_has_parent(view, VIEW_STAGE, VIEW_STATUS) || - view_has_parent(view, VIEW_BLOB, VIEW_TREE) || - view_has_parent(view, VIEW_MAIN, VIEW_BRANCH)) { + if (view->parent) { int line; view = view->parent; @@ -3692,9 +3684,7 @@ view_driver(struct view *view, enum request request) if (view_is_displayed(view)) update_view_title(view); if (line != view->lineno) - view->ops->request(view, REQ_ENTER, - &view->line[view->lineno]); - + view_request(view, REQ_ENTER); } else { move_view(view, request); } @@ -3789,13 +3779,12 @@ view_driver(struct view *view, enum request request) break; case REQ_VIEW_CLOSE: - /* XXX: Mark closed views by letting view->parent point to the + /* XXX: Mark closed views by letting view->prev point to the * view itself. Parents to closed view should never be * followed. */ - if (view->parent && - view->parent->parent != view->parent) { - maximize_view(view->parent); - view->parent = view; + if (view->prev && view->prev != view) { + maximize_view(view->prev); + view->prev = view; break; } /* Fall-through */ @@ -4004,7 +3993,9 @@ select_commit_parent(const char *id, char rev[SIZEOF_REV], const char *path) return FALSE; } - if (parents > 1 && !open_commit_parent_menu(buf, &parents)) + if (parents == 1) + parents = 0; + else if (!open_commit_parent_menu(buf, &parents)) return FALSE; string_copy_rev(rev, &buf[41 * parents]); @@ -4498,7 +4489,6 @@ tree_read_date(struct view *view, char *text, bool *read_date) "git", "log", "--no-color", "--pretty=raw", "--cc", "--raw", view->id, "--", path, NULL }; - struct io io = {}; if (!view->lines) { tree_entry(view, LINE_TREE_HEAD, opt_path, NULL, NULL); @@ -4506,13 +4496,11 @@ tree_read_date(struct view *view, char *text, bool *read_date) return TRUE; } - if (!io_run_rd(&io, log_file, opt_cdup, FORMAT_NONE)) { + if (!start_update(view, log_file, opt_cdup)) { report("Failed to load tree data"); return TRUE; } - io_done(view->pipe); - view->io = io; *read_date = TRUE; return FALSE; @@ -4641,14 +4629,15 @@ tree_draw(struct view *view, struct line *line, unsigned int lineno) } static void -open_blob_editor() +open_blob_editor(const char *id) { + const char *blob_argv[] = { "git", "cat-file", "blob", id, NULL }; char file[SIZEOF_STR] = "/tmp/tigblob.XXXXXX"; int fd = mkstemp(file); if (fd == -1) report("Failed to create temporary file"); - else if (!io_run_append(blob_ops.argv, FORMAT_ALL, fd)) + else if (!io_run_append(blob_argv, fd)) report("Failed to save blob data to file"); else open_editor(file); @@ -4660,6 +4649,7 @@ static enum request tree_request(struct view *view, enum request request, struct line *line) { enum open_flags flags; + struct tree_entry *entry = line->data; switch (request) { case REQ_VIEW_BLAME: @@ -4675,7 +4665,7 @@ tree_request(struct view *view, enum request request, struct line *line) if (line->type != LINE_TREE_FILE) { report("Edit only supported for files"); } else if (!is_head_commit(view->vid)) { - open_blob_editor(); + open_blob_editor(entry->id); } else { open_editor(opt_file); } @@ -4726,7 +4716,7 @@ tree_request(struct view *view, enum request request, struct line *line) break; case LINE_TREE_FILE: - flags = display[0] == view ? OPEN_SPLIT : OPEN_DEFAULT; + flags = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT; request = REQ_VIEW_BLOB; break; @@ -4794,7 +4784,7 @@ tree_prepare(struct view *view) opt_path[0] = 0; } - return io_format(&view->io, opt_cdup, IO_RD, view->ops->argv, FORMAT_ALL); + return prepare_io(view, opt_cdup, view->ops->argv, TRUE); } static const char *tree_argv[SIZEOF_ARG] = { @@ -4826,7 +4816,7 @@ blob_request(struct view *view, enum request request, struct line *line) { switch (request) { case REQ_EDIT: - open_blob_editor(); + open_blob_editor(view->vid); return REQ_NONE; default: return pager_request(view, request, line); @@ -4859,18 +4849,6 @@ static struct view_ops blob_ops = { * reading output from git-blame. */ -static const char *blame_head_argv[] = { - "git", "blame", "--incremental", "--", "%(file)", NULL -}; - -static const char *blame_ref_argv[] = { - "git", "blame", "--incremental", "%(ref)", "--", "%(file)", NULL -}; - -static const char *blame_cat_file_argv[] = { - "git", "cat-file", "blob", "%(ref):%(file)", NULL -}; - struct blame_commit { char id[SIZEOF_REV]; /* SHA1 ID. */ char title[128]; /* First line of the commit message. */ @@ -4891,14 +4869,19 @@ blame_open(struct view *view) { char path[SIZEOF_STR]; - if (!view->parent && *opt_prefix) { + if (!view->prev && *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 (!io_run_rd(&view->io, blame_cat_file_argv, opt_cdup, FORMAT_ALL)) + const char *blame_cat_file_argv[] = { + "git", "cat-file", "blob", path, NULL + }; + + if (!string_format(path, "%s:%s", opt_ref, opt_file) || + !start_update(view, blame_cat_file_argv, opt_cdup)) return FALSE; } @@ -4988,19 +4971,19 @@ static bool blame_read_file(struct view *view, const char *line, bool *read_file) { if (!line) { - const char **argv = *opt_ref ? blame_ref_argv : blame_head_argv; - struct io io = {}; + const char *blame_argv[] = { + "git", "blame", "--incremental", + *opt_ref ? opt_ref : "--incremental", "--", opt_file, NULL + }; - if (view->lines == 0 && !view->parent) + if (view->lines == 0 && !view->prev) die("No blame exist for %s", view->vid); - if (view->lines == 0 || !io_run_rd(&io, argv, opt_cdup, FORMAT_ALL)) { + if (view->lines == 0 || !start_update(view, blame_argv, opt_cdup)) { report("Failed to load blame data"); return TRUE; } - io_done(view->pipe); - view->io = io; *read_file = FALSE; return FALSE; @@ -5131,12 +5114,12 @@ setup_blame_parent_line(struct view *view, struct blame *blame) "git", "diff-tree", "-U0", blame->commit->id, "--", blame->commit->filename, NULL }; - struct io io = {}; + struct io io; int parent_lineno = -1; int blamed_lineno = -1; char *line; - if (!io_run(&io, diff_tree_argv, NULL, IO_RD)) + if (!io_run(&io, IO_RD, NULL, diff_tree_argv)) return; while ((line = io_get(&io, '\n', TRUE))) { @@ -5163,7 +5146,7 @@ setup_blame_parent_line(struct view *view, struct blame *blame) static enum request blame_request(struct view *view, enum request request, struct line *line) { - enum open_flags flags = display[0] == view ? OPEN_SPLIT : OPEN_DEFAULT; + enum open_flags flags = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT; struct blame *blame = line->data; switch (request) { @@ -5428,7 +5411,7 @@ branch_open(struct view *view) "--simplify-by-decoration", "--all", NULL }; - if (!io_run_rd(&view->io, branch_log, NULL, FORMAT_NONE)) { + if (!start_update(view, branch_log, NULL)) { report("Failed to load branch data"); return TRUE; } @@ -5547,9 +5530,9 @@ status_run(struct view *view, const char *argv[], char status, enum line_type ty { struct status *unmerged = NULL; char *buf; - struct io io = {}; + struct io io; - if (!io_run(&io, argv, opt_cdup, IO_RD)) + if (!io_run(&io, IO_RD, opt_cdup, argv)) return FALSE; add_line_data(view, NULL, type); @@ -5697,7 +5680,7 @@ status_update_onbranch(void) continue; if (!*opt_head) { - struct io io = {}; + struct io io; if (io_open(&io, "%s/rebase-merge/head-name", opt_git_dir) && io_read_buf(&io, buf, sizeof(buf))) { @@ -5889,7 +5872,7 @@ status_enter(struct view *view, struct line *line) die("line type %d not handled in switch", line->type); } - split = view_is_displayed(view) ? OPEN_SPLIT : 0; + split = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT; open_view(view, REQ_VIEW_STAGE, OPEN_PREPARED | split); if (view_is_displayed(VIEW(REQ_VIEW_STAGE))) { if (status) { @@ -5944,11 +5927,11 @@ status_update_prepare(struct io *io, enum line_type type) switch (type) { case LINE_STAT_STAGED: - return io_run(io, staged_argv, opt_cdup, IO_WR); + return io_run(io, IO_WR, opt_cdup, staged_argv); case LINE_STAT_UNSTAGED: case LINE_STAT_UNTRACKED: - return io_run(io, others_argv, opt_cdup, IO_WR); + return io_run(io, IO_WR, opt_cdup, others_argv); default: die("line type %d not handled in switch", type); @@ -5987,7 +5970,7 @@ status_update_write(struct io *io, struct status *status, enum line_type type) static bool status_update_file(struct status *status, enum line_type type) { - struct io io = {}; + struct io io; bool result; if (!status_update_prepare(&io, type)) @@ -6001,7 +5984,7 @@ static bool status_update_files(struct view *view, struct line *line) { char buf[sizeof(view->ref)]; - struct io io = {}; + struct io io; bool result = TRUE; struct line *pos = view->line + view->lines; int files = 0; @@ -6274,7 +6257,7 @@ stage_apply_chunk(struct view *view, struct line *chunk, bool revert) "git", "apply", "--whitespace=nowarn", NULL }; struct line *diff_hdr; - struct io io = {}; + struct io io; int argc = 3; diff_hdr = stage_diff_find(view, chunk, LINE_DIFF_HEADER); @@ -6287,7 +6270,7 @@ stage_apply_chunk(struct view *view, struct line *chunk, bool revert) apply_argv[argc++] = "-R"; apply_argv[argc++] = "-"; apply_argv[argc++] = NULL; - if (!io_run(&io, apply_argv, opt_cdup, IO_WR)) + if (!io_run(&io, IO_WR, opt_cdup, apply_argv)) return FALSE; if (!stage_diff_write(&io, diff_hdr, chunk) || @@ -6769,7 +6752,7 @@ main_read(struct view *view, char *line) if (!line) { int i; - if (!view->lines && !view->parent) + if (!view->lines && !view->prev) die("No revisions match the given arguments."); if (view->lines > 0) { commit = view->line[view->lines - 1].data; @@ -6859,7 +6842,7 @@ main_read(struct view *view, char *line) static enum request main_request(struct view *view, enum request request, struct line *line) { - enum open_flags flags = display[0] == view ? OPEN_SPLIT : OPEN_DEFAULT; + enum open_flags flags = view_is_displayed(view) ? OPEN_SPLIT : OPEN_DEFAULT; switch (request) { case REQ_ENTER: