X-Git-Url: https://git.distorted.org.uk/~mdw/tig/blobdiff_plain/c38c64bb6e5e9c1f173e24c964b06497e24108d9..17a27c168dc82bf424bd94bbaba44c65fe57b280:/tig.c diff --git a/tig.c b/tig.c index cc7f6b8..ce21fba 100644 --- a/tig.c +++ b/tig.c @@ -352,6 +352,7 @@ sq_quote(char buf[SIZEOF_STR], size_t bufsize, const char *src) REQ_(TOGGLE_LINENO, "Toggle line numbers"), \ REQ_(TOGGLE_REV_GRAPH, "Toggle revision graph visualization"), \ REQ_(STATUS_UPDATE, "Update file status"), \ + REQ_(STATUS_MERGE, "Merge file using external tool"), \ REQ_(EDIT, "Open in editor"), \ REQ_(CHERRY_PICK, "Cherry-pick commit to current branch") @@ -787,6 +788,7 @@ static struct keybinding default_keybindings[] = { { 'g', REQ_TOGGLE_REV_GRAPH }, { ':', REQ_PROMPT }, { 'u', REQ_STATUS_UPDATE }, + { 'M', REQ_STATUS_MERGE }, { 'e', REQ_EDIT }, { 'C', REQ_CHERRY_PICK }, @@ -2146,7 +2148,31 @@ open_view(struct view *prev, enum request request, enum open_flags flags) } static void -open_editor(bool from_root, char *file) +open_external_viewer(const char *cmd) +{ + def_prog_mode(); /* save current tty modes */ + endwin(); /* restore original tty modes */ + system(cmd); + fprintf(stderr, "Press Enter to continue"); + getc(stdin); + reset_prog_mode(); + redraw_display(); +} + +static void +open_mergetool(const char *file) +{ + char cmd[SIZEOF_STR]; + char file_sq[SIZEOF_STR]; + + if (sq_quote(file_sq, 0, file) < sizeof(file_sq) && + string_format(cmd, "git mergetool %s", file_sq)) { + open_external_viewer(cmd); + } +} + +static void +open_editor(bool from_root, const char *file) { char cmd[SIZEOF_STR]; char file_sq[SIZEOF_STR]; @@ -2165,11 +2191,7 @@ open_editor(bool from_root, char *file) if (sq_quote(file_sq, 0, file) < sizeof(file_sq) && string_format(cmd, "%s %s%s", editor, prefix, file_sq)) { - def_prog_mode(); /* save current tty modes */ - endwin(); /* restore original tty modes */ - system(cmd); - reset_prog_mode(); - redraw_display(); + open_external_viewer(cmd); } } @@ -2981,6 +3003,7 @@ static bool status_run(struct view *view, const char cmd[], bool diff, enum line_type type) { struct status *file = NULL; + struct status *unmerged = NULL; char buf[SIZEOF_STR * 4]; size_t bufsize = 0; FILE *pipe; @@ -3030,6 +3053,23 @@ status_run(struct view *view, const char cmd[], bool diff, enum line_type type) if (!sep) break; sepsize = sep - buf + 1; + + /* Collapse all 'M'odified entries that + * follow a associated 'U'nmerged entry. + */ + if (file->status == 'U') { + unmerged = file; + + } else if (unmerged) { + int collapse = !strcmp(buf, unmerged->name); + + unmerged = NULL; + if (collapse) { + free(file); + view->lines--; + continue; + } + } } /* git-ls-files just delivers a NUL separated @@ -3055,7 +3095,8 @@ error_out: return TRUE; } -#define STATUS_DIFF_INDEX_CMD "git diff-index -z --cached HEAD" +/* Don't show unmerged entries in the staged section. */ +#define STATUS_DIFF_INDEX_CMD "git diff-index -z --diff-filter=ACDMRTXB --cached HEAD" #define STATUS_DIFF_FILES_CMD "git diff-files -z" #define STATUS_LIST_OTHER_CMD \ "git ls-files -z --others --exclude-per-directory=.gitignore" @@ -3320,8 +3361,6 @@ status_update(struct view *view) } else if (!status_update_file(view, line->data, line->type)) { report("Failed to update file status"); } - - open_view(view, REQ_VIEW_STATUS, OPEN_RELOAD); } static enum request @@ -3334,26 +3373,34 @@ status_request(struct view *view, enum request request, struct line *line) status_update(view); break; + case REQ_STATUS_MERGE: + open_mergetool(status->name); + break; + case REQ_EDIT: if (!status) return request; open_editor(status->status != '?', status->name); - open_view(view, REQ_VIEW_STATUS, OPEN_RELOAD); break; case REQ_ENTER: + /* After returning the status view has been split to + * show the stage view. No further reloading is + * necessary. */ status_enter(view, line); - break; + return REQ_NONE; case REQ_REFRESH: - open_view(view, REQ_VIEW_STATUS, OPEN_RELOAD); + /* Simply reload the view. */ break; default: return request; } + open_view(view, REQ_VIEW_STATUS, OPEN_RELOAD); + return REQ_NONE; } @@ -3363,6 +3410,7 @@ status_select(struct view *view, struct line *line) struct status *status = line->data; char file[SIZEOF_STR] = "all files"; char *text; + char *key; if (status && !string_format(file, "'%s'", status->name)) return; @@ -3391,7 +3439,15 @@ status_select(struct view *view, struct line *line) die("w00t"); } - string_format(view->ref, text, get_key(REQ_STATUS_UPDATE), file); + if (status && status->status == 'U') { + text = "Press %s to resolve conflict in %s"; + key = get_key(REQ_STATUS_MERGE); + + } else { + key = get_key(REQ_STATUS_UPDATE); + } + + string_format(view->ref, text, key, file); } static bool @@ -4038,13 +4094,7 @@ cherry_pick_commit(struct commit *commit) cherry_pick = "git cherry-pick"; if (string_format(cmd, "%s %s", cherry_pick, commit->id)) { - def_prog_mode(); /* save current tty modes */ - endwin(); /* restore original tty modes */ - system(cmd); - fprintf(stderr, "Press Enter to continue"); - getc(stdin); - reset_prog_mode(); - redraw_display(); + open_external_viewer(cmd); } }