diff options
Diffstat (limited to 'add-patch.c')
-rw-r--r-- | add-patch.c | 141 |
1 files changed, 83 insertions, 58 deletions
diff --git a/add-patch.c b/add-patch.c index e6fa107..cd5cfc9 100644 --- a/add-patch.c +++ b/add-patch.c @@ -2,7 +2,7 @@ #include "add-interactive.h" #include "strbuf.h" #include "run-command.h" -#include "argv-array.h" +#include "strvec.h" #include "pathspec.h" #include "color.h" #include "diff.h" @@ -266,6 +266,20 @@ struct add_p_state { const char *revision; }; +static void add_p_state_clear(struct add_p_state *s) +{ + size_t i; + + strbuf_release(&s->answer); + strbuf_release(&s->buf); + strbuf_release(&s->plain); + strbuf_release(&s->colored); + for (i = 0; i < s->file_diff_nr; i++) + free(s->file_diff[i].hunk); + free(s->file_diff); + clear_add_i_state(&s->s); +} + static void err(struct add_p_state *s, const char *fmt, ...) { va_list args; @@ -286,12 +300,12 @@ static void setup_child_process(struct add_p_state *s, va_start(ap, cp); while ((arg = va_arg(ap, const char *))) - argv_array_push(&cp->args, arg); + strvec_push(&cp->args, arg); va_end(ap); cp->git_cmd = 1; - argv_array_pushf(&cp->env_array, - INDEX_ENVIRONMENT "=%s", s->s.r->index_file); + strvec_pushf(&cp->env_array, + INDEX_ENVIRONMENT "=%s", s->s.r->index_file); } static int parse_range(const char **p, @@ -370,7 +384,7 @@ static int is_octal(const char *p, size_t len) static int parse_diff(struct add_p_state *s, const struct pathspec *ps) { - struct argv_array args = ARGV_ARRAY_INIT; + struct strvec args = STRVEC_INIT; const char *diff_algorithm = s->s.interactive_diff_algorithm; struct strbuf *plain = &s->plain, *colored = NULL; struct child_process cp = CHILD_PROCESS_INIT; @@ -380,32 +394,32 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) struct hunk *hunk = NULL; int res; - argv_array_pushv(&args, s->mode->diff_cmd); + strvec_pushv(&args, s->mode->diff_cmd); if (diff_algorithm) - argv_array_pushf(&args, "--diff-algorithm=%s", diff_algorithm); + strvec_pushf(&args, "--diff-algorithm=%s", diff_algorithm); if (s->revision) { struct object_id oid; - argv_array_push(&args, - /* could be on an unborn branch */ - !strcmp("HEAD", s->revision) && - get_oid("HEAD", &oid) ? - empty_tree_oid_hex() : s->revision); + strvec_push(&args, + /* could be on an unborn branch */ + !strcmp("HEAD", s->revision) && + get_oid("HEAD", &oid) ? + empty_tree_oid_hex() : s->revision); } - color_arg_index = args.argc; + color_arg_index = args.nr; /* Use `--no-color` explicitly, just in case `diff.color = always`. */ - argv_array_pushl(&args, "--no-color", "-p", "--", NULL); + strvec_pushl(&args, "--no-color", "-p", "--", NULL); for (i = 0; i < ps->nr; i++) - argv_array_push(&args, ps->items[i].original); + strvec_push(&args, ps->items[i].original); setup_child_process(s, &cp, NULL); - cp.argv = args.argv; + cp.argv = args.v; res = capture_command(&cp, plain, 0); if (res) { - argv_array_clear(&args); + strvec_clear(&args); return error(_("could not parse diff")); } if (!plain->len) { - argv_array_clear(&args); + strvec_clear(&args); return 0; } strbuf_complete_line(plain); @@ -415,11 +429,11 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) const char *diff_filter = s->s.interactive_diff_filter; setup_child_process(s, &colored_cp, NULL); - xsnprintf((char *)args.argv[color_arg_index], 8, "--color"); - colored_cp.argv = args.argv; + xsnprintf((char *)args.v[color_arg_index], 8, "--color"); + colored_cp.argv = args.v; colored = &s->colored; res = capture_command(&colored_cp, colored, 0); - argv_array_clear(&args); + strvec_clear(&args); if (res) return error(_("could not parse colored diff")); @@ -444,7 +458,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) colored_p = colored->buf; colored_pend = colored_p + colored->len; } - argv_array_clear(&args); + strvec_clear(&args); /* parse files and hunks */ p = plain->buf; @@ -457,11 +471,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) eol = pend; if (starts_with(p, "diff ")) { - s->file_diff_nr++; - ALLOC_GROW(s->file_diff, s->file_diff_nr, + ALLOC_GROW_BY(s->file_diff, s->file_diff_nr, 1, file_diff_alloc); file_diff = s->file_diff + s->file_diff_nr - 1; - memset(file_diff, 0, sizeof(*file_diff)); hunk = &file_diff->head; hunk->start = p - plain->buf; if (colored_p) @@ -483,11 +495,9 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) */ hunk->splittable_into++; - file_diff->hunk_nr++; - ALLOC_GROW(file_diff->hunk, file_diff->hunk_nr, + ALLOC_GROW_BY(file_diff->hunk, file_diff->hunk_nr, 1, file_diff->hunk_alloc); hunk = file_diff->hunk + file_diff->hunk_nr - 1; - memset(hunk, 0, sizeof(*hunk)); hunk->start = p - plain->buf; if (colored) @@ -511,7 +521,7 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) if (file_diff->mode_change) BUG("double mode change?\n\n%.*s", (int)(eol - plain->buf), plain->buf); - if (file_diff->hunk_nr++) + if (file_diff->hunk_nr) BUG("mode change in the middle?\n\n%.*s", (int)(eol - plain->buf), plain->buf); @@ -520,9 +530,8 @@ static int parse_diff(struct add_p_state *s, const struct pathspec *ps) * is _part of_ the header "hunk". */ file_diff->mode_change = 1; - ALLOC_GROW(file_diff->hunk, file_diff->hunk_nr, + ALLOC_GROW_BY(file_diff->hunk, file_diff->hunk_nr, 1, file_diff->hunk_alloc); - memset(file_diff->hunk, 0, sizeof(struct hunk)); file_diff->hunk->start = p - plain->buf; if (colored_p) file_diff->hunk->colored_start = @@ -1158,7 +1167,7 @@ static int run_apply_check(struct add_p_state *s, setup_child_process(s, &cp, "apply", "--check", NULL); - argv_array_pushv(&cp.args, s->mode->apply_check_args); + strvec_pushv(&cp.args, s->mode->apply_check_args); if (pipe_command(&cp, s->buf.buf, s->buf.len, NULL, 0, NULL, 0)) return error(_("'git apply --cached' failed")); @@ -1203,7 +1212,7 @@ static int edit_hunk_loop(struct add_p_state *s, for (;;) { int res = edit_hunk_manually(s, hunk); if (res == 0) { - /* abandonded */ + /* abandoned */ *hunk = backup; return -1; } @@ -1357,6 +1366,15 @@ static int patch_update_file(struct add_p_state *s, struct child_process cp = CHILD_PROCESS_INIT; int colored = !!s->colored.len, quit = 0; enum prompt_mode_type prompt_mode_type; + enum { + ALLOW_GOTO_PREVIOUS_HUNK = 1 << 0, + ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK = 1 << 1, + ALLOW_GOTO_NEXT_HUNK = 1 << 2, + ALLOW_GOTO_NEXT_UNDECIDED_HUNK = 1 << 3, + ALLOW_SEARCH_AND_GOTO = 1 << 4, + ALLOW_SPLIT = 1 << 5, + ALLOW_EDIT = 1 << 6 + } permitted = 0; if (!file_diff->hunk_nr) return 0; @@ -1393,22 +1411,35 @@ static int patch_update_file(struct add_p_state *s, fputs(s->buf.buf, stdout); strbuf_reset(&s->buf); - if (undecided_previous >= 0) + if (undecided_previous >= 0) { + permitted |= ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK; strbuf_addstr(&s->buf, ",k"); - if (hunk_index) + } + if (hunk_index) { + permitted |= ALLOW_GOTO_PREVIOUS_HUNK; strbuf_addstr(&s->buf, ",K"); - if (undecided_next >= 0) + } + if (undecided_next >= 0) { + permitted |= ALLOW_GOTO_NEXT_UNDECIDED_HUNK; strbuf_addstr(&s->buf, ",j"); - if (hunk_index + 1 < file_diff->hunk_nr) + } + if (hunk_index + 1 < file_diff->hunk_nr) { + permitted |= ALLOW_GOTO_NEXT_HUNK; strbuf_addstr(&s->buf, ",J"); - if (file_diff->hunk_nr > 1) + } + if (file_diff->hunk_nr > 1) { + permitted |= ALLOW_SEARCH_AND_GOTO; strbuf_addstr(&s->buf, ",g,/"); - if (hunk->splittable_into > 1) + } + if (hunk->splittable_into > 1) { + permitted |= ALLOW_SPLIT; strbuf_addstr(&s->buf, ",s"); + } if (hunk_index + 1 > file_diff->mode_change && - !file_diff->deleted) + !file_diff->deleted) { + permitted |= ALLOW_EDIT; strbuf_addstr(&s->buf, ",e"); - + } if (file_diff->deleted) prompt_mode_type = PROMPT_DELETION; else if (file_diff->added) @@ -1457,22 +1488,22 @@ soft_increment: break; } } else if (s->answer.buf[0] == 'K') { - if (hunk_index) + if (permitted & ALLOW_GOTO_PREVIOUS_HUNK) hunk_index--; else err(s, _("No previous hunk")); } else if (s->answer.buf[0] == 'J') { - if (hunk_index + 1 < file_diff->hunk_nr) + if (permitted & ALLOW_GOTO_NEXT_HUNK) hunk_index++; else err(s, _("No next hunk")); } else if (s->answer.buf[0] == 'k') { - if (undecided_previous >= 0) + if (permitted & ALLOW_GOTO_PREVIOUS_UNDECIDED_HUNK) hunk_index = undecided_previous; else err(s, _("No previous hunk")); } else if (s->answer.buf[0] == 'j') { - if (undecided_next >= 0) + if (permitted & ALLOW_GOTO_NEXT_UNDECIDED_HUNK) hunk_index = undecided_next; else err(s, _("No next hunk")); @@ -1480,7 +1511,7 @@ soft_increment: char *pend; unsigned long response; - if (file_diff->hunk_nr < 2) { + if (!(permitted & ALLOW_SEARCH_AND_GOTO)) { err(s, _("No other hunks to goto")); continue; } @@ -1517,7 +1548,7 @@ soft_increment: regex_t regex; int ret; - if (file_diff->hunk_nr < 2) { + if (!(permitted & ALLOW_SEARCH_AND_GOTO)) { err(s, _("No other hunks to search")); continue; } @@ -1562,7 +1593,7 @@ soft_increment: hunk_index = i; } else if (s->answer.buf[0] == 's') { size_t splittable_into = hunk->splittable_into; - if (splittable_into < 2) + if (!(permitted & ALLOW_SPLIT)) err(s, _("Sorry, cannot split this hunk")); else if (!split_hunk(s, file_diff, hunk - file_diff->hunk)) @@ -1570,7 +1601,7 @@ soft_increment: _("Split into %d hunks."), (int)splittable_into); } else if (s->answer.buf[0] == 'e') { - if (hunk_index + 1 == file_diff->mode_change) + if (!(permitted & ALLOW_EDIT)) err(s, _("Sorry, cannot edit this hunk")); else if (edit_hunk_loop(s, file_diff, hunk) >= 0) { hunk->use = USE_HUNK; @@ -1619,7 +1650,7 @@ soft_increment: s->mode->is_reverse); else { setup_child_process(s, &cp, "apply", NULL); - argv_array_pushv(&cp.args, s->mode->apply_args); + strvec_pushv(&cp.args, s->mode->apply_args); if (pipe_command(&cp, s->buf.buf, s->buf.len, NULL, 0, NULL, 0)) error(_("'git apply' failed")); @@ -1673,9 +1704,7 @@ int run_add_p(struct repository *r, enum add_p_mode mode, repo_refresh_and_write_index(r, REFRESH_QUIET, 0, 1, NULL, NULL, NULL) < 0) || parse_diff(&s, ps) < 0) { - strbuf_release(&s.plain); - strbuf_release(&s.colored); - clear_add_i_state(&s.s); + add_p_state_clear(&s); return -1; } @@ -1690,10 +1719,6 @@ int run_add_p(struct repository *r, enum add_p_mode mode, else if (binary_count == s.file_diff_nr) fprintf(stderr, _("Only binary files changed.\n")); - strbuf_release(&s.answer); - strbuf_release(&s.buf); - strbuf_release(&s.plain); - strbuf_release(&s.colored); - clear_add_i_state(&s.s); + add_p_state_clear(&s); return 0; } |