From 12913a78cedc491f89a34ab0b545831d6006fc98 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:12 +0200 Subject: [PATCH 01/50] builtin/apply: make gitdiff_verify_name() return void As the value returned by gitdiff_verify_name() is put into the same variable that is passed as a parameter to this function, it is simpler to pass the address of the variable and have gitdiff_verify_name() change the variable itself. This also makes it possible to later have this function return -1 instead of die()ing in case of error. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 8e4da2e1bd..fe5aebdb0f 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -925,43 +925,43 @@ static int gitdiff_hdrend(const char *line, struct patch *patch) #define DIFF_OLD_NAME 0 #define DIFF_NEW_NAME 1 -static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, int side) +static void gitdiff_verify_name(const char *line, int isnull, char **name, int side) { - if (!orig_name && !isnull) - return find_name(line, NULL, p_value, TERM_TAB); + if (!*name && !isnull) { + *name = find_name(line, NULL, p_value, TERM_TAB); + return; + } - if (orig_name) { - int len = strlen(orig_name); + if (*name) { + int len = strlen(*name); char *another; if (isnull) die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), - orig_name, linenr); + *name, linenr); another = find_name(line, NULL, p_value, TERM_TAB); - if (!another || memcmp(another, orig_name, len + 1)) + if (!another || memcmp(another, *name, len + 1)) die((side == DIFF_NEW_NAME) ? _("git apply: bad git-diff - inconsistent new filename on line %d") : _("git apply: bad git-diff - inconsistent old filename on line %d"), linenr); free(another); - return orig_name; } else { /* expect "/dev/null" */ if (memcmp("/dev/null", line, 9) || line[9] != '\n') die(_("git apply: bad git-diff - expected /dev/null on line %d"), linenr); - return NULL; } } static int gitdiff_oldname(const char *line, struct patch *patch) { - patch->old_name = gitdiff_verify_name(line, patch->is_new, patch->old_name, - DIFF_OLD_NAME); + gitdiff_verify_name(line, patch->is_new, &patch->old_name, + DIFF_OLD_NAME); return 0; } static int gitdiff_newname(const char *line, struct patch *patch) { - patch->new_name = gitdiff_verify_name(line, patch->is_delete, patch->new_name, - DIFF_NEW_NAME); + gitdiff_verify_name(line, patch->is_delete, &patch->new_name, + DIFF_NEW_NAME); return 0; } From 560e35468feea3b471418dfe48d753f433141e10 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:13 +0200 Subject: [PATCH 02/50] builtin/apply: avoid parameter shadowing 'p_value' global MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's just rename the global 'state_p_value' as it will become 'state->p_value' in a following patch. This also avoid errors when compiling with -Wshadow and makes it safer to later move global variables into a "state" struct. Helped-by: Nguyễn Thái Ngọc Duy Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index fe5aebdb0f..e133b381d3 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -35,7 +35,7 @@ static int prefix_length = -1; static int newfd = -1; static int unidiff_zero; -static int p_value = 1; +static int state_p_value = 1; static int p_value_known; static int check_index; static int update_index; @@ -872,24 +872,24 @@ static void parse_traditional_patch(const char *first, const char *second, struc q = guess_p_value(second); if (p < 0) p = q; if (0 <= p && p == q) { - p_value = p; + state_p_value = p; p_value_known = 1; } } if (is_dev_null(first)) { patch->is_new = 1; patch->is_delete = 0; - name = find_name_traditional(second, NULL, p_value); + name = find_name_traditional(second, NULL, state_p_value); patch->new_name = name; } else if (is_dev_null(second)) { patch->is_new = 0; patch->is_delete = 1; - name = find_name_traditional(first, NULL, p_value); + name = find_name_traditional(first, NULL, state_p_value); patch->old_name = name; } else { char *first_name; - first_name = find_name_traditional(first, NULL, p_value); - name = find_name_traditional(second, first_name, p_value); + first_name = find_name_traditional(first, NULL, state_p_value); + name = find_name_traditional(second, first_name, state_p_value); free(first_name); if (has_epoch_timestamp(first)) { patch->is_new = 1; @@ -928,7 +928,7 @@ static int gitdiff_hdrend(const char *line, struct patch *patch) static void gitdiff_verify_name(const char *line, int isnull, char **name, int side) { if (!*name && !isnull) { - *name = find_name(line, NULL, p_value, TERM_TAB); + *name = find_name(line, NULL, state_p_value, TERM_TAB); return; } @@ -938,7 +938,7 @@ static void gitdiff_verify_name(const char *line, int isnull, char **name, int s if (isnull) die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), *name, linenr); - another = find_name(line, NULL, p_value, TERM_TAB); + another = find_name(line, NULL, state_p_value, TERM_TAB); if (!another || memcmp(another, *name, len + 1)) die((side == DIFF_NEW_NAME) ? _("git apply: bad git-diff - inconsistent new filename on line %d") : @@ -997,7 +997,7 @@ static int gitdiff_copysrc(const char *line, struct patch *patch) { patch->is_copy = 1; free(patch->old_name); - patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->old_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); return 0; } @@ -1005,7 +1005,7 @@ static int gitdiff_copydst(const char *line, struct patch *patch) { patch->is_copy = 1; free(patch->new_name); - patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->new_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); return 0; } @@ -1013,7 +1013,7 @@ static int gitdiff_renamesrc(const char *line, struct patch *patch) { patch->is_rename = 1; free(patch->old_name); - patch->old_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->old_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); return 0; } @@ -1021,7 +1021,7 @@ static int gitdiff_renamedst(const char *line, struct patch *patch) { patch->is_rename = 1; free(patch->new_name); - patch->new_name = find_name(line, NULL, p_value ? p_value - 1 : 0, 0); + patch->new_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); return 0; } @@ -1092,10 +1092,10 @@ static const char *skip_tree_prefix(const char *line, int llen) int nslash; int i; - if (!p_value) + if (!state_p_value) return (llen && line[0] == '/') ? NULL : line; - nslash = p_value; + nslash = state_p_value; for (i = 0; i < llen; i++) { int ch = line[i]; if (ch == '/' && --nslash <= 0) @@ -1481,8 +1481,8 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc "%d leading pathname component (line %d)", "git diff header lacks filename information when removing " "%d leading pathname components (line %d)", - p_value), - p_value, linenr); + state_p_value), + state_p_value, linenr); patch->old_name = xstrdup(patch->def_name); patch->new_name = xstrdup(patch->def_name); } @@ -4461,7 +4461,7 @@ static int option_parse_include(const struct option *opt, static int option_parse_p(const struct option *opt, const char *arg, int unset) { - p_value = atoi(arg); + state_p_value = atoi(arg); p_value_known = 1; return 0; } From eb8fdbff3c26639912e73a01cfa2a86ce787d4b2 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:14 +0200 Subject: [PATCH 03/50] builtin/apply: avoid parameter shadowing 'linenr' global Let's just rename the global 'state_linenr' as it will become 'state->linenr' in a following patch. This also avoid errors when compiling with -Wshadow and makes it safer to later move global variables into a "state" struct. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index e133b381d3..705a9c8bd1 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -144,7 +144,7 @@ static int max_change, max_len; * file (and how) we're patching right now.. The "is_xxxx" * things are flags, where -1 means "don't know yet". */ -static int linenr = 1; +static int state_linenr = 1; /* * This represents one "hunk" from a patch, starting with @@ -905,7 +905,7 @@ static void parse_traditional_patch(const char *first, const char *second, struc } } if (!name) - die(_("unable to find filename in patch at line %d"), linenr); + die(_("unable to find filename in patch at line %d"), state_linenr); } static int gitdiff_hdrend(const char *line, struct patch *patch) @@ -937,17 +937,17 @@ static void gitdiff_verify_name(const char *line, int isnull, char **name, int s char *another; if (isnull) die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), - *name, linenr); + *name, state_linenr); another = find_name(line, NULL, state_p_value, TERM_TAB); if (!another || memcmp(another, *name, len + 1)) die((side == DIFF_NEW_NAME) ? _("git apply: bad git-diff - inconsistent new filename on line %d") : - _("git apply: bad git-diff - inconsistent old filename on line %d"), linenr); + _("git apply: bad git-diff - inconsistent old filename on line %d"), state_linenr); free(another); } else { /* expect "/dev/null" */ if (memcmp("/dev/null", line, 9) || line[9] != '\n') - die(_("git apply: bad git-diff - expected /dev/null on line %d"), linenr); + die(_("git apply: bad git-diff - expected /dev/null on line %d"), state_linenr); } } @@ -1272,8 +1272,8 @@ static int parse_git_header(const char *line, int len, unsigned int size, struct line += len; size -= len; - linenr++; - for (offset = len ; size > 0 ; offset += len, size -= len, line += len, linenr++) { + state_linenr++; + for (offset = len ; size > 0 ; offset += len, size -= len, line += len, state_linenr++) { static const struct opentry { const char *str; int (*fn)(const char *, struct patch *); @@ -1440,7 +1440,7 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc patch->is_new = patch->is_delete = -1; patch->old_mode = patch->new_mode = 0; patch->old_name = patch->new_name = NULL; - for (offset = 0; size > 0; offset += len, size -= len, line += len, linenr++) { + for (offset = 0; size > 0; offset += len, size -= len, line += len, state_linenr++) { unsigned long nextlen; len = linelen(line, size); @@ -1461,7 +1461,7 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc if (parse_fragment_header(line, len, &dummy) < 0) continue; die(_("patch fragment without header at line %d: %.*s"), - linenr, (int)len-1, line); + state_linenr, (int)len-1, line); } if (size < len + 6) @@ -1482,13 +1482,13 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc "git diff header lacks filename information when removing " "%d leading pathname components (line %d)", state_p_value), - state_p_value, linenr); + state_p_value, state_linenr); patch->old_name = xstrdup(patch->def_name); patch->new_name = xstrdup(patch->def_name); } if (!patch->is_delete && !patch->new_name) die("git diff header lacks filename information " - "(line %d)", linenr); + "(line %d)", state_linenr); patch->is_toplevel_relative = 1; *hdrsize = git_hdr_len; return offset; @@ -1510,7 +1510,7 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc /* Ok, we'll consider it a patch */ parse_traditional_patch(line, line+len, patch); *hdrsize = len + nextlen; - linenr += 2; + state_linenr += 2; return offset; } return -1; @@ -1538,7 +1538,7 @@ static void check_whitespace(const char *line, int len, unsigned ws_rule) { unsigned result = ws_check(line + 1, len - 1, ws_rule); - record_ws_error(result, line + 1, len - 2, linenr); + record_ws_error(result, line + 1, len - 2, state_linenr); } /* @@ -1568,11 +1568,11 @@ static int parse_fragment(const char *line, unsigned long size, /* Parse the thing.. */ line += len; size -= len; - linenr++; + state_linenr++; added = deleted = 0; for (offset = len; 0 < size; - offset += len, size -= len, line += len, linenr++) { + offset += len, size -= len, line += len, state_linenr++) { if (!oldlines && !newlines) break; len = linelen(line, size); @@ -1668,10 +1668,10 @@ static int parse_single_patch(const char *line, unsigned long size, struct patch int len; fragment = xcalloc(1, sizeof(*fragment)); - fragment->linenr = linenr; + fragment->linenr = state_linenr; len = parse_fragment(line, size, patch, fragment); if (len <= 0) - die(_("corrupt patch at line %d"), linenr); + die(_("corrupt patch at line %d"), state_linenr); fragment->patch = line; fragment->size = len; oldlines += fragment->oldlines; @@ -1799,13 +1799,13 @@ static struct fragment *parse_binary_hunk(char **buf_p, else return NULL; - linenr++; + state_linenr++; buffer += llen; while (1) { int byte_length, max_byte_length, newsize; llen = linelen(buffer, size); used += llen; - linenr++; + state_linenr++; if (llen == 1) { /* consume the blank line */ buffer++; @@ -1859,7 +1859,7 @@ static struct fragment *parse_binary_hunk(char **buf_p, free(data); *status_p = -1; error(_("corrupt binary patch at line %d: %.*s"), - linenr-1, llen-1, buffer); + state_linenr-1, llen-1, buffer); return NULL; } @@ -1892,7 +1892,7 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch) forward = parse_binary_hunk(&buffer, &size, &status, &used); if (!forward && !status) /* there has to be one hunk (forward hunk) */ - return error(_("unrecognized binary patch at line %d"), linenr-1); + return error(_("unrecognized binary patch at line %d"), state_linenr-1); if (status) /* otherwise we already gave an error message */ return status; @@ -2010,7 +2010,7 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) if (llen == sizeof(git_binary) - 1 && !memcmp(git_binary, buffer + hd, llen)) { int used; - linenr++; + state_linenr++; used = parse_binary(buffer + hd + llen, size - hd - llen, patch); if (used < 0) @@ -2031,7 +2031,7 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) int len = strlen(binhdr[i]); if (len < size - hd && !memcmp(binhdr[i], buffer + hd, len)) { - linenr++; + state_linenr++; patch->is_binary = 1; patchsize = llen; break; @@ -2045,7 +2045,7 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) */ if ((apply || check) && (!patch->is_binary && !metadata_changes(patch))) - die(_("patch with only garbage at line %d"), linenr); + die(_("patch with only garbage at line %d"), state_linenr); } return offset + hdrsize + patchsize; From bb0ba9974314da72bba9a6200fa3bd61c4d9eab4 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:15 +0200 Subject: [PATCH 04/50] builtin/apply: avoid local variable shadowing 'len' parameter This is just a cleanup to avoid errors when compiling with -Wshadow and to make it safer to later move global variables into a "state" struct. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 705a9c8bd1..bb8bf7f0e3 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2194,17 +2194,17 @@ static void update_pre_post_images(struct image *preimage, fixed = preimage->buf; for (i = reduced = ctx = 0; i < postimage->nr; i++) { - size_t len = postimage->line[i].len; + size_t l_len = postimage->line[i].len; if (!(postimage->line[i].flag & LINE_COMMON)) { /* an added line -- no counterparts in preimage */ - memmove(new, old, len); - old += len; - new += len; + memmove(new, old, l_len); + old += l_len; + new += l_len; continue; } /* a common context -- skip it in the original postimage */ - old += len; + old += l_len; /* and find the corresponding one in the fixed preimage */ while (ctx < preimage->nr && @@ -2223,11 +2223,11 @@ static void update_pre_post_images(struct image *preimage, } /* and copy it in, while fixing the line length */ - len = preimage->line[ctx].len; - memcpy(new, fixed, len); - new += len; - fixed += len; - postimage->line[i].len = len; + l_len = preimage->line[ctx].len; + memcpy(new, fixed, l_len); + new += l_len; + fixed += l_len; + postimage->line[i].len = l_len; ctx++; } From 7a3eb9e2224d883df229fe4adce51e762165573a Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:16 +0200 Subject: [PATCH 05/50] builtin/apply: extract line_by_line_fuzzy_match() from match_fragment() The match_fragment() function is very big and contains a big special case algorithm that does line by line fuzzy matching. So let's extract this algorithm in a separate line_by_line_fuzzy_match() function. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 126 +++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 55 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index bb8bf7f0e3..7bab466fe2 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -2242,6 +2242,74 @@ static void update_pre_post_images(struct image *preimage, postimage->nr -= reduced; } +static int line_by_line_fuzzy_match(struct image *img, + struct image *preimage, + struct image *postimage, + unsigned long try, + int try_lno, + int preimage_limit) +{ + int i; + size_t imgoff = 0; + size_t preoff = 0; + size_t postlen = postimage->len; + size_t extra_chars; + char *buf; + char *preimage_eof; + char *preimage_end; + struct strbuf fixed; + char *fixed_buf; + size_t fixed_len; + + for (i = 0; i < preimage_limit; i++) { + size_t prelen = preimage->line[i].len; + size_t imglen = img->line[try_lno+i].len; + + if (!fuzzy_matchlines(img->buf + try + imgoff, imglen, + preimage->buf + preoff, prelen)) + return 0; + if (preimage->line[i].flag & LINE_COMMON) + postlen += imglen - prelen; + imgoff += imglen; + preoff += prelen; + } + + /* + * Ok, the preimage matches with whitespace fuzz. + * + * imgoff now holds the true length of the target that + * matches the preimage before the end of the file. + * + * Count the number of characters in the preimage that fall + * beyond the end of the file and make sure that all of them + * are whitespace characters. (This can only happen if + * we are removing blank lines at the end of the file.) + */ + buf = preimage_eof = preimage->buf + preoff; + for ( ; i < preimage->nr; i++) + preoff += preimage->line[i].len; + preimage_end = preimage->buf + preoff; + for ( ; buf < preimage_end; buf++) + if (!isspace(*buf)) + return 0; + + /* + * Update the preimage and the common postimage context + * lines to use the same whitespace as the target. + * If whitespace is missing in the target (i.e. + * if the preimage extends beyond the end of the file), + * use the whitespace from the preimage. + */ + extra_chars = preimage_end - preimage_eof; + strbuf_init(&fixed, imgoff + extra_chars); + strbuf_add(&fixed, img->buf + try, imgoff); + strbuf_add(&fixed, preimage_eof, extra_chars); + fixed_buf = strbuf_detach(&fixed, &fixed_len); + update_pre_post_images(preimage, postimage, + fixed_buf, fixed_len, postlen); + return 1; +} + static int match_fragment(struct image *img, struct image *preimage, struct image *postimage, @@ -2331,61 +2399,9 @@ static int match_fragment(struct image *img, * fuzzy matching. We collect all the line length information because * we need it to adjust whitespace if we match. */ - if (ws_ignore_action == ignore_ws_change) { - size_t imgoff = 0; - size_t preoff = 0; - size_t postlen = postimage->len; - size_t extra_chars; - char *preimage_eof; - char *preimage_end; - for (i = 0; i < preimage_limit; i++) { - size_t prelen = preimage->line[i].len; - size_t imglen = img->line[try_lno+i].len; - - if (!fuzzy_matchlines(img->buf + try + imgoff, imglen, - preimage->buf + preoff, prelen)) - return 0; - if (preimage->line[i].flag & LINE_COMMON) - postlen += imglen - prelen; - imgoff += imglen; - preoff += prelen; - } - - /* - * Ok, the preimage matches with whitespace fuzz. - * - * imgoff now holds the true length of the target that - * matches the preimage before the end of the file. - * - * Count the number of characters in the preimage that fall - * beyond the end of the file and make sure that all of them - * are whitespace characters. (This can only happen if - * we are removing blank lines at the end of the file.) - */ - buf = preimage_eof = preimage->buf + preoff; - for ( ; i < preimage->nr; i++) - preoff += preimage->line[i].len; - preimage_end = preimage->buf + preoff; - for ( ; buf < preimage_end; buf++) - if (!isspace(*buf)) - return 0; - - /* - * Update the preimage and the common postimage context - * lines to use the same whitespace as the target. - * If whitespace is missing in the target (i.e. - * if the preimage extends beyond the end of the file), - * use the whitespace from the preimage. - */ - extra_chars = preimage_end - preimage_eof; - strbuf_init(&fixed, imgoff + extra_chars); - strbuf_add(&fixed, img->buf + try, imgoff); - strbuf_add(&fixed, preimage_eof, extra_chars); - fixed_buf = strbuf_detach(&fixed, &fixed_len); - update_pre_post_images(preimage, postimage, - fixed_buf, fixed_len, postlen); - return 1; - } + if (ws_ignore_action == ignore_ws_change) + return line_by_line_fuzzy_match(img, preimage, postimage, + try, try_lno, preimage_limit); if (ws_error_action != correct_ws_error) return 0; From d1b27ced9a38ed03e99422b6cb24ff95c7437663 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:17 +0200 Subject: [PATCH 06/50] builtin/apply: move 'options' variable into cmd_apply() The 'options' variable doesn't need to be static and global to the file. It can be local to cmd_apply(), so let's move it there. This will make it easier to libify the apply functionality. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/apply.c b/builtin/apply.c index 7bab466fe2..5a1d65a695 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -79,7 +79,6 @@ static enum ws_ignore { static const char *patch_input_file; static struct strbuf root = STRBUF_INIT; static int read_stdin = 1; -static int options; static void parse_whitespace_option(const char *option) { @@ -4517,6 +4516,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) int errs = 0; int is_not_gitdir = !startup_info->have_repository; int force_apply = 0; + int options = 0; const char *whitespace_option = NULL; From dcde8b3dcd8d4411a2311fa0a93ca4ca3b26d61f Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:18 +0200 Subject: [PATCH 07/50] builtin/apply: move 'read_stdin' global into cmd_apply() The 'read_stdin' variable doesn't need to be static and global to the file. It can be local to cmd_apply(), so let's move it there. This will make it easier to libify the apply functionality. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/apply.c b/builtin/apply.c index 5a1d65a695..c911e4ec82 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -78,7 +78,6 @@ static enum ws_ignore { static const char *patch_input_file; static struct strbuf root = STRBUF_INIT; -static int read_stdin = 1; static void parse_whitespace_option(const char *option) { @@ -4517,6 +4516,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) int is_not_gitdir = !startup_info->have_repository; int force_apply = 0; int options = 0; + int read_stdin = 1; const char *whitespace_option = NULL; From 2fc0f1849bd0d6100719bb53f89f15fbd734157a Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 11 May 2016 15:16:19 +0200 Subject: [PATCH 08/50] builtin/apply: introduce 'struct apply_state' to start libifying Currently commands that want to use the apply functionality have to launch a "git apply" process which can be bad for performance. Let's start libifying the apply functionality and to do that we first need to get rid of the global variables in "builtin/apply.c". This patch introduces "struct apply_state" into which all the previously global variables will be moved. A new parameter called "state" that is a pointer to the "apply_state" structure will come at the beginning of the helper functions that need it and will be passed around the call chain. To start let's move the "prefix" and "prefix_length" global variables into "struct apply_state". Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 94 +++++++++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 38 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index c911e4ec82..ae068e7392 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -21,6 +21,11 @@ #include "ll-merge.h" #include "rerere.h" +struct apply_state { + const char *prefix; + int prefix_length; +}; + /* * --check turns on checking that the working tree matches the * files that are being modified, but doesn't apply the patch @@ -30,8 +35,6 @@ * --index updates the cache as well. * --cached updates only the cache without ever touching the working tree. */ -static const char *prefix; -static int prefix_length = -1; static int newfd = -1; static int unidiff_zero; @@ -748,7 +751,7 @@ static int count_slashes(const char *cp) * Given the string after "--- " or "+++ ", guess the appropriate * p_value for the given patch. */ -static int guess_p_value(const char *nameline) +static int guess_p_value(struct apply_state *state, const char *nameline) { char *name, *cp; int val = -1; @@ -761,17 +764,17 @@ static int guess_p_value(const char *nameline) cp = strchr(name, '/'); if (!cp) val = 0; - else if (prefix) { + else if (state->prefix) { /* * Does it begin with "a/$our-prefix" and such? Then this is * very likely to apply to our directory. */ - if (!strncmp(name, prefix, prefix_length)) - val = count_slashes(prefix); + if (!strncmp(name, state->prefix, state->prefix_length)) + val = count_slashes(state->prefix); else { cp++; - if (!strncmp(cp, prefix, prefix_length)) - val = count_slashes(prefix) + 1; + if (!strncmp(cp, state->prefix, state->prefix_length)) + val = count_slashes(state->prefix) + 1; } } free(name); @@ -858,7 +861,10 @@ static int has_epoch_timestamp(const char *nameline) * files, we can happily check the index for a match, but for creating a * new file we should try to match whatever "patch" does. I have no idea. */ -static void parse_traditional_patch(const char *first, const char *second, struct patch *patch) +static void parse_traditional_patch(struct apply_state *state, + const char *first, + const char *second, + struct patch *patch) { char *name; @@ -866,8 +872,8 @@ static void parse_traditional_patch(const char *first, const char *second, struc second += 4; /* skip "+++ " */ if (!p_value_known) { int p, q; - p = guess_p_value(first); - q = guess_p_value(second); + p = guess_p_value(state, first); + q = guess_p_value(state, second); if (p < 0) p = q; if (0 <= p && p == q) { state_p_value = p; @@ -1429,7 +1435,11 @@ static int parse_fragment_header(const char *line, int len, struct fragment *fra return offset; } -static int find_header(const char *line, unsigned long size, int *hdrsize, struct patch *patch) +static int find_header(struct apply_state *state, + const char *line, + unsigned long size, + int *hdrsize, + struct patch *patch) { unsigned long offset, len; @@ -1506,7 +1516,7 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc continue; /* Ok, we'll consider it a patch */ - parse_traditional_patch(line, line+len, patch); + parse_traditional_patch(state, line, line+len, patch); *hdrsize = len + nextlen; state_linenr += 2; return offset; @@ -1913,21 +1923,21 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch) return used; } -static void prefix_one(char **name) +static void prefix_one(struct apply_state *state, char **name) { char *old_name = *name; if (!old_name) return; - *name = xstrdup(prefix_filename(prefix, prefix_length, *name)); + *name = xstrdup(prefix_filename(state->prefix, state->prefix_length, *name)); free(old_name); } -static void prefix_patch(struct patch *p) +static void prefix_patch(struct apply_state *state, struct patch *p) { - if (!prefix || p->is_toplevel_relative) + if (!state->prefix || p->is_toplevel_relative) return; - prefix_one(&p->new_name); - prefix_one(&p->old_name); + prefix_one(state, &p->new_name); + prefix_one(state, &p->old_name); } /* @@ -1944,16 +1954,16 @@ static void add_name_limit(const char *name, int exclude) it->util = exclude ? NULL : (void *) 1; } -static int use_patch(struct patch *p) +static int use_patch(struct apply_state *state, struct patch *p) { const char *pathname = p->new_name ? p->new_name : p->old_name; int i; /* Paths outside are not touched regardless of "--include" */ - if (0 < prefix_length) { + if (0 < state->prefix_length) { int pathlen = strlen(pathname); - if (pathlen <= prefix_length || - memcmp(prefix, pathname, prefix_length)) + if (pathlen <= state->prefix_length || + memcmp(state->prefix, pathname, state->prefix_length)) return 0; } @@ -1980,17 +1990,17 @@ static int use_patch(struct patch *p) * Return the number of bytes consumed, so that the caller can call us * again for the next patch. */ -static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) +static int parse_chunk(struct apply_state *state, char *buffer, unsigned long size, struct patch *patch) { int hdrsize, patchsize; - int offset = find_header(buffer, size, &hdrsize, patch); + int offset = find_header(state, buffer, size, &hdrsize, patch); if (offset < 0) return offset; - prefix_patch(patch); + prefix_patch(state, patch); - if (!use_patch(patch)) + if (!use_patch(state, patch)) patch->ws_rule = 0; else patch->ws_rule = whitespace_rule(patch->new_name @@ -4367,7 +4377,10 @@ static struct lock_file lock_file; #define INACCURATE_EOF (1<<0) #define RECOUNT (1<<1) -static int apply_patch(int fd, const char *filename, int options) +static int apply_patch(struct apply_state *state, + int fd, + const char *filename, + int options) { size_t offset; struct strbuf buf = STRBUF_INIT; /* owns the patch text */ @@ -4384,14 +4397,14 @@ static int apply_patch(int fd, const char *filename, int options) patch = xcalloc(1, sizeof(*patch)); patch->inaccurate_eof = !!(options & INACCURATE_EOF); patch->recount = !!(options & RECOUNT); - nr = parse_chunk(buf.buf + offset, buf.len - offset, patch); + nr = parse_chunk(state, buf.buf + offset, buf.len - offset, patch); if (nr < 0) { free_patch(patch); break; } if (apply_in_reverse) reverse_patches(patch); - if (use_patch(patch)) { + if (use_patch(state, patch)) { patch_stats(patch); *listp = patch; listp = &patch->next; @@ -4517,6 +4530,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) int force_apply = 0; int options = 0; int read_stdin = 1; + struct apply_state state; const char *whitespace_option = NULL; @@ -4589,15 +4603,17 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) OPT_END() }; - prefix = prefix_; - prefix_length = prefix ? strlen(prefix) : 0; + memset(&state, 0, sizeof(state)); + state.prefix = prefix_; + state.prefix_length = state.prefix ? strlen(state.prefix) : 0; + git_apply_config(); if (apply_default_whitespace) parse_whitespace_option(apply_default_whitespace); if (apply_default_ignorewhitespace) parse_ignorewhitespace_option(apply_default_ignorewhitespace); - argc = parse_options(argc, argv, prefix, builtin_apply_options, + argc = parse_options(argc, argv, state.prefix, builtin_apply_options, apply_usage, 0); if (apply_with_reject && threeway) @@ -4628,23 +4644,25 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) int fd; if (!strcmp(arg, "-")) { - errs |= apply_patch(0, "", options); + errs |= apply_patch(&state, 0, "", options); read_stdin = 0; continue; - } else if (0 < prefix_length) - arg = prefix_filename(prefix, prefix_length, arg); + } else if (0 < state.prefix_length) + arg = prefix_filename(state.prefix, + state.prefix_length, + arg); fd = open(arg, O_RDONLY); if (fd < 0) die_errno(_("can't open patch '%s'"), arg); read_stdin = 0; set_default_whitespace_mode(whitespace_option); - errs |= apply_patch(fd, arg, options); + errs |= apply_patch(&state, fd, arg, options); close(fd); } set_default_whitespace_mode(whitespace_option); if (read_stdin) - errs |= apply_patch(0, "", options); + errs |= apply_patch(&state, 0, "", options); if (whitespace_error) { if (squelch_whitespace_errors && squelch_whitespace_errors < whitespace_error) { From 6f27b941f2664c1653d0c4edcec5686119f0c023 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:46 +0200 Subject: [PATCH 09/50] builtin/apply: move 'state' init into init_apply_state() When the apply functionality will be libified, the 'struct apply_state' will be used by different pieces of code. To properly initialize a 'struct apply_state', let's provide a nice and easy to use init_apply_state() function. Let's also provide clear_apply_state() to release memory used by 'struct apply_state' members, so that a 'struct apply_state' instance can be easily reused without leaking memory. Note that clear_apply_state() does nothing for now, but it will later. While at it, let's rename 'prefix_' parameter to 'prefix'. Helped-by: Eric Sunshine Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index ae068e7392..52b5d3ed8e 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -4522,7 +4522,25 @@ static int option_parse_directory(const struct option *opt, return 0; } -int cmd_apply(int argc, const char **argv, const char *prefix_) +static void init_apply_state(struct apply_state *state, const char *prefix) +{ + memset(state, 0, sizeof(*state)); + state->prefix = prefix; + state->prefix_length = state->prefix ? strlen(state->prefix) : 0; + + git_apply_config(); + if (apply_default_whitespace) + parse_whitespace_option(apply_default_whitespace); + if (apply_default_ignorewhitespace) + parse_ignorewhitespace_option(apply_default_ignorewhitespace); +} + +static void clear_apply_state(struct apply_state *state) +{ + /* empty for now */ +} + +int cmd_apply(int argc, const char **argv, const char *prefix) { int i; int errs = 0; @@ -4603,15 +4621,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) OPT_END() }; - memset(&state, 0, sizeof(state)); - state.prefix = prefix_; - state.prefix_length = state.prefix ? strlen(state.prefix) : 0; - - git_apply_config(); - if (apply_default_whitespace) - parse_whitespace_option(apply_default_whitespace); - if (apply_default_ignorewhitespace) - parse_ignorewhitespace_option(apply_default_ignorewhitespace); + init_apply_state(&state, prefix); argc = parse_options(argc, argv, state.prefix, builtin_apply_options, apply_usage, 0); @@ -4695,5 +4705,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_) die(_("Unable to write new index file")); } + clear_apply_state(&state); + return !!errs; } From 1da16e1ed85c5be6eb243ca91225757b25088623 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:47 +0200 Subject: [PATCH 10/50] builtin/apply: move 'unidiff_zero' global into 'struct apply_state' To libify the apply functionality the 'unidiff_zero' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 52b5d3ed8e..6c36898904 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -24,6 +24,9 @@ struct apply_state { const char *prefix; int prefix_length; + + /* These boolean parameters control how the apply is done */ + int unidiff_zero; }; /* @@ -37,7 +40,6 @@ struct apply_state { */ static int newfd = -1; -static int unidiff_zero; static int state_p_value = 1; static int p_value_known; static int check_index; @@ -2694,7 +2696,8 @@ static void update_image(struct image *img, * postimage) for the hunk. Find lines that match "preimage" in "img" and * replace the part of "img" with "postimage" text. */ -static int apply_one_fragment(struct image *img, struct fragment *frag, +static int apply_one_fragment(struct apply_state *state, + struct image *img, struct fragment *frag, int inaccurate_eof, unsigned ws_rule, int nth_fragment) { @@ -2836,7 +2839,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag, * without leading context must match at the beginning. */ match_beginning = (!frag->oldpos || - (frag->oldpos == 1 && !unidiff_zero)); + (frag->oldpos == 1 && !state->unidiff_zero)); /* * A hunk without trailing lines must match at the end. @@ -2844,7 +2847,7 @@ static int apply_one_fragment(struct image *img, struct fragment *frag, * from the lack of trailing lines if the patch was generated * with unidiff without any context. */ - match_end = !unidiff_zero && !trailing; + match_end = !state->unidiff_zero && !trailing; pos = frag->newpos ? (frag->newpos - 1) : 0; preimage.buf = oldlines; @@ -3067,7 +3070,7 @@ static int apply_binary(struct image *img, struct patch *patch) return 0; } -static int apply_fragments(struct image *img, struct patch *patch) +static int apply_fragments(struct apply_state *state, struct image *img, struct patch *patch) { struct fragment *frag = patch->fragments; const char *name = patch->old_name ? patch->old_name : patch->new_name; @@ -3080,7 +3083,7 @@ static int apply_fragments(struct image *img, struct patch *patch) while (frag) { nth++; - if (apply_one_fragment(img, frag, inaccurate_eof, ws_rule, nth)) { + if (apply_one_fragment(state, img, frag, inaccurate_eof, ws_rule, nth)) { error(_("patch failed: %s:%ld"), name, frag->oldpos); if (!apply_with_reject) return -1; @@ -3388,8 +3391,11 @@ static int load_current(struct image *image, struct patch *patch) return 0; } -static int try_threeway(struct image *image, struct patch *patch, - struct stat *st, const struct cache_entry *ce) +static int try_threeway(struct apply_state *state, + struct image *image, + struct patch *patch, + struct stat *st, + const struct cache_entry *ce) { unsigned char pre_sha1[20], post_sha1[20], our_sha1[20]; struct strbuf buf = STRBUF_INIT; @@ -3415,7 +3421,7 @@ static int try_threeway(struct image *image, struct patch *patch, img = strbuf_detach(&buf, &len); prepare_image(&tmp_image, img, len, 1); /* Apply the patch to get the post image */ - if (apply_fragments(&tmp_image, patch) < 0) { + if (apply_fragments(state, &tmp_image, patch) < 0) { clear_image(&tmp_image); return -1; } @@ -3459,7 +3465,8 @@ static int try_threeway(struct image *image, struct patch *patch, return 0; } -static int apply_data(struct patch *patch, struct stat *st, const struct cache_entry *ce) +static int apply_data(struct apply_state *state, struct patch *patch, + struct stat *st, const struct cache_entry *ce) { struct image image; @@ -3467,9 +3474,9 @@ static int apply_data(struct patch *patch, struct stat *st, const struct cache_e return -1; if (patch->direct_to_threeway || - apply_fragments(&image, patch) < 0) { + apply_fragments(state, &image, patch) < 0) { /* Note: with --reject, apply_fragments() returns 0 */ - if (!threeway || try_threeway(&image, patch, st, ce) < 0) + if (!threeway || try_threeway(state, &image, patch, st, ce) < 0) return -1; } patch->result = image.buf; @@ -3717,7 +3724,7 @@ static void die_on_unsafe_path(struct patch *patch) * Check and apply the patch in-core; leave the result in patch->result * for the caller to write it out to the final destination. */ -static int check_patch(struct patch *patch) +static int check_patch(struct apply_state *state, struct patch *patch) { struct stat st; const char *old_name = patch->old_name; @@ -3816,13 +3823,13 @@ static int check_patch(struct patch *patch) return error(_("affected file '%s' is beyond a symbolic link"), patch->new_name); - if (apply_data(patch, &st, ce) < 0) + if (apply_data(state, patch, &st, ce) < 0) return error(_("%s: patch does not apply"), name); patch->rejected = 0; return 0; } -static int check_patch_list(struct patch *patch) +static int check_patch_list(struct apply_state *state, struct patch *patch) { int err = 0; @@ -3832,7 +3839,7 @@ static int check_patch_list(struct patch *patch) if (apply_verbosely) say_patch_name(stderr, _("Checking patch %s..."), patch); - err |= check_patch(patch); + err |= check_patch(state, patch); patch = patch->next; } return err; @@ -4434,7 +4441,7 @@ static int apply_patch(struct apply_state *state, } if ((check || apply) && - check_patch_list(list) < 0 && + check_patch_list(state, list) < 0 && !apply_with_reject) exit(1); @@ -4602,7 +4609,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) PARSE_OPT_NOARG, option_parse_space_change }, OPT_BOOL('R', "reverse", &apply_in_reverse, N_("apply the patch in reverse")), - OPT_BOOL(0, "unidiff-zero", &unidiff_zero, + OPT_BOOL(0, "unidiff-zero", &state.unidiff_zero, N_("don't expect at least one line of context")), OPT_BOOL(0, "reject", &apply_with_reject, N_("leave the rejected hunks in corresponding *.rej files")), From 22a7233584b1983e2a7337d3b0f2c13f0cc34651 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:48 +0200 Subject: [PATCH 11/50] builtin/apply: move 'check' global into 'struct apply_state' To libify the apply functionality the 'check' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 6c36898904..55a5541fde 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -25,13 +25,14 @@ struct apply_state { const char *prefix; int prefix_length; + /* These control what gets looked at and modified */ + int check; /* preimage must match working tree, don't actually apply */ + /* These boolean parameters control how the apply is done */ int unidiff_zero; }; /* - * --check turns on checking that the working tree matches the - * files that are being modified, but doesn't apply the patch * --stat does just a diffstat, and doesn't actually apply * --numstat does numeric diffstat, and doesn't actually apply * --index-info shows the old and new index info for paths if available. @@ -48,7 +49,6 @@ static int cached; static int diffstat; static int numstat; static int summary; -static int check; static int apply = 1; static int apply_in_reverse; static int apply_with_reject; @@ -2053,7 +2053,7 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si * without metadata change. A binary patch appears * empty to us here. */ - if ((apply || check) && + if ((apply || state->check) && (!patch->is_binary && !metadata_changes(patch))) die(_("patch with only garbage at line %d"), state_linenr); } @@ -4440,7 +4440,7 @@ static int apply_patch(struct apply_state *state, die(_("unable to read index file")); } - if ((check || apply) && + if ((state->check || apply) && check_patch_list(state, list) < 0 && !apply_with_reject) exit(1); @@ -4579,7 +4579,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("show number of added and deleted lines in decimal notation")), OPT_BOOL(0, "summary", &summary, N_("instead of applying the patch, output a summary for the input")), - OPT_BOOL(0, "check", &check, + OPT_BOOL(0, "check", &state.check, N_("instead of applying the patch, see if the patch is applicable")), OPT_BOOL(0, "index", &check_index, N_("make sure the patch is applicable to the current index")), @@ -4644,7 +4644,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) } if (apply_with_reject) apply = apply_verbosely = 1; - if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor)) + if (!force_apply && (diffstat || numstat || summary || state.check || fake_ancestor)) apply = 0; if (check_index && is_not_gitdir) die(_("--index outside a repository")); From ee87a6e7404549d2be738bd54f2f191e8b5ea352 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:49 +0200 Subject: [PATCH 12/50] builtin/apply: move 'check_index' global into 'struct apply_state' To libify the apply functionality the 'check_index' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 66 +++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 55a5541fde..769383cd5d 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -27,6 +27,7 @@ struct apply_state { /* These control what gets looked at and modified */ int check; /* preimage must match working tree, don't actually apply */ + int check_index; /* preimage must match the indexed version */ /* These boolean parameters control how the apply is done */ int unidiff_zero; @@ -36,14 +37,12 @@ struct apply_state { * --stat does just a diffstat, and doesn't actually apply * --numstat does numeric diffstat, and doesn't actually apply * --index-info shows the old and new index info for paths if available. - * --index updates the cache as well. * --cached updates only the cache without ever touching the working tree. */ static int newfd = -1; static int state_p_value = 1; static int p_value_known; -static int check_index; static int update_index; static int cached; static int diffstat; @@ -3245,13 +3244,14 @@ static int verify_index_match(const struct cache_entry *ce, struct stat *st) #define SUBMODULE_PATCH_WITHOUT_INDEX 1 -static int load_patch_target(struct strbuf *buf, +static int load_patch_target(struct apply_state *state, + struct strbuf *buf, const struct cache_entry *ce, struct stat *st, const char *name, unsigned expected_mode) { - if (cached || check_index) { + if (cached || state->check_index) { if (read_file_or_gitlink(ce, buf)) return error(_("read of %s failed"), name); } else if (name) { @@ -3277,7 +3277,8 @@ static int load_patch_target(struct strbuf *buf, * applying a non-git patch that incrementally updates the tree, * we read from the result of a previous diff. */ -static int load_preimage(struct image *image, +static int load_preimage(struct apply_state *state, + struct image *image, struct patch *patch, struct stat *st, const struct cache_entry *ce) { @@ -3295,7 +3296,7 @@ static int load_preimage(struct image *image, /* We have a patched copy in memory; use that. */ strbuf_add(&buf, previous->result, previous->resultsize); } else { - status = load_patch_target(&buf, ce, st, + status = load_patch_target(state, &buf, ce, st, patch->old_name, patch->old_mode); if (status < 0) return status; @@ -3354,7 +3355,9 @@ static int three_way_merge(struct image *image, * the current contents of the new_name. In no cases other than that * this function will be called. */ -static int load_current(struct image *image, struct patch *patch) +static int load_current(struct apply_state *state, + struct image *image, + struct patch *patch) { struct strbuf buf = STRBUF_INIT; int status, pos; @@ -3381,7 +3384,7 @@ static int load_current(struct image *image, struct patch *patch) if (verify_index_match(ce, &st)) return error(_("%s: does not match index"), name); - status = load_patch_target(&buf, ce, &st, name, mode); + status = load_patch_target(state, &buf, ce, &st, name, mode); if (status < 0) return status; else if (status) @@ -3431,11 +3434,11 @@ static int try_threeway(struct apply_state *state, /* our_sha1[] is ours */ if (patch->is_new) { - if (load_current(&tmp_image, patch)) + if (load_current(state, &tmp_image, patch)) return error("cannot read the current contents of '%s'", patch->new_name); } else { - if (load_preimage(&tmp_image, patch, st, ce)) + if (load_preimage(state, &tmp_image, patch, st, ce)) return error("cannot read the current contents of '%s'", patch->old_name); } @@ -3470,7 +3473,7 @@ static int apply_data(struct apply_state *state, struct patch *patch, { struct image image; - if (load_preimage(&image, patch, st, ce) < 0) + if (load_preimage(state, &image, patch, st, ce) < 0) return -1; if (patch->direct_to_threeway || @@ -3501,7 +3504,10 @@ static int apply_data(struct apply_state *state, struct patch *patch, * check_patch() separately makes sure (and errors out otherwise) that * the path the patch creates does not exist in the current tree. */ -static int check_preimage(struct patch *patch, struct cache_entry **ce, struct stat *st) +static int check_preimage(struct apply_state *state, + struct patch *patch, + struct cache_entry **ce, + struct stat *st) { const char *old_name = patch->old_name; struct patch *previous = NULL; @@ -3524,7 +3530,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s return error(_("%s: %s"), old_name, strerror(errno)); } - if (check_index && !previous) { + if (state->check_index && !previous) { int pos = cache_name_pos(old_name, strlen(old_name)); if (pos < 0) { if (patch->is_new < 0) @@ -3574,11 +3580,13 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s #define EXISTS_IN_INDEX 1 #define EXISTS_IN_WORKTREE 2 -static int check_to_create(const char *new_name, int ok_if_exists) +static int check_to_create(struct apply_state *state, + const char *new_name, + int ok_if_exists) { struct stat nst; - if (check_index && + if (state->check_index && cache_name_pos(new_name, strlen(new_name)) >= 0 && !ok_if_exists) return EXISTS_IN_INDEX; @@ -3654,7 +3662,7 @@ static void prepare_symlink_changes(struct patch *patch) } } -static int path_is_beyond_symlink_1(struct strbuf *name) +static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *name) { do { unsigned int change; @@ -3675,7 +3683,7 @@ static int path_is_beyond_symlink_1(struct strbuf *name) continue; /* otherwise, check the preimage */ - if (check_index) { + if (state->check_index) { struct cache_entry *ce; ce = cache_file_exists(name->buf, name->len, ignore_case); @@ -3690,14 +3698,14 @@ static int path_is_beyond_symlink_1(struct strbuf *name) return 0; } -static int path_is_beyond_symlink(const char *name_) +static int path_is_beyond_symlink(struct apply_state *state, const char *name_) { int ret; struct strbuf name = STRBUF_INIT; assert(*name_ != '\0'); strbuf_addstr(&name, name_); - ret = path_is_beyond_symlink_1(&name); + ret = path_is_beyond_symlink_1(state, &name); strbuf_release(&name); return ret; @@ -3737,7 +3745,7 @@ static int check_patch(struct apply_state *state, struct patch *patch) patch->rejected = 1; /* we will drop this after we succeed */ - status = check_preimage(patch, &ce, &st); + status = check_preimage(state, patch, &ce, &st); if (status) return status; old_name = patch->old_name; @@ -3764,7 +3772,7 @@ static int check_patch(struct apply_state *state, struct patch *patch) if (new_name && ((0 < patch->is_new) || patch->is_rename || patch->is_copy)) { - int err = check_to_create(new_name, ok_if_exists); + int err = check_to_create(state, new_name, ok_if_exists); if (err && threeway) { patch->direct_to_threeway = 1; @@ -3819,7 +3827,7 @@ static int check_patch(struct apply_state *state, struct patch *patch) * is not deposited to a path that is beyond a symbolic link * here. */ - if (!patch->is_delete && path_is_beyond_symlink(patch->new_name)) + if (!patch->is_delete && path_is_beyond_symlink(state, patch->new_name)) return error(_("affected file '%s' is beyond a symbolic link"), patch->new_name); @@ -4431,11 +4439,11 @@ static int apply_patch(struct apply_state *state, if (whitespace_error && (ws_error_action == die_on_ws_error)) apply = 0; - update_index = check_index && apply; + update_index = state->check_index && apply; if (update_index && newfd < 0) newfd = hold_locked_index(&lock_file, 1); - if (check_index) { + if (state->check_index) { if (read_cache() < 0) die(_("unable to read index file")); } @@ -4581,7 +4589,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("instead of applying the patch, output a summary for the input")), OPT_BOOL(0, "check", &state.check, N_("instead of applying the patch, see if the patch is applicable")), - OPT_BOOL(0, "index", &check_index, + OPT_BOOL(0, "index", &state.check_index, N_("make sure the patch is applicable to the current index")), OPT_BOOL(0, "cached", &cached, N_("apply a patch without touching the working tree")), @@ -4640,20 +4648,20 @@ int cmd_apply(int argc, const char **argv, const char *prefix) if (threeway) { if (is_not_gitdir) die(_("--3way outside a repository")); - check_index = 1; + state.check_index = 1; } if (apply_with_reject) apply = apply_verbosely = 1; if (!force_apply && (diffstat || numstat || summary || state.check || fake_ancestor)) apply = 0; - if (check_index && is_not_gitdir) + if (state.check_index && is_not_gitdir) die(_("--index outside a repository")); if (cached) { if (is_not_gitdir) die(_("--cached outside a repository")); - check_index = 1; + state.check_index = 1; } - if (check_index) + if (state.check_index) unsafe_paths = 0; for (i = 0; i < argc; i++) { From 2595a8b146e86a3217cd6ee44bcc889cc2fe774f Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:50 +0200 Subject: [PATCH 13/50] builtin/apply: move 'apply_in_reverse' global into 'struct apply_state' To libify the apply functionality the 'apply_in_reverse' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 50 ++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 769383cd5d..796d990910 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -30,6 +30,7 @@ struct apply_state { int check_index; /* preimage must match the indexed version */ /* These boolean parameters control how the apply is done */ + int apply_in_reverse; int unidiff_zero; }; @@ -49,7 +50,6 @@ static int diffstat; static int numstat; static int summary; static int apply = 1; -static int apply_in_reverse; static int apply_with_reject; static int apply_verbosely; static int allow_overlap; @@ -1556,8 +1556,11 @@ static void check_whitespace(const char *line, int len, unsigned ws_rule) * between a "---" that is part of a patch, and a "---" that starts * the next patch is to look at the line counts.. */ -static int parse_fragment(const char *line, unsigned long size, - struct patch *patch, struct fragment *fragment) +static int parse_fragment(struct apply_state *state, + const char *line, + unsigned long size, + struct patch *patch, + struct fragment *fragment) { int added, deleted; int len = linelen(line, size), offset; @@ -1597,12 +1600,12 @@ static int parse_fragment(const char *line, unsigned long size, if (!deleted && !added) leading++; trailing++; - if (!apply_in_reverse && + if (!state->apply_in_reverse && ws_error_action == correct_ws_error) check_whitespace(line, len, patch->ws_rule); break; case '-': - if (apply_in_reverse && + if (state->apply_in_reverse && ws_error_action != nowarn_ws_error) check_whitespace(line, len, patch->ws_rule); deleted++; @@ -1610,7 +1613,7 @@ static int parse_fragment(const char *line, unsigned long size, trailing = 0; break; case '+': - if (!apply_in_reverse && + if (!state->apply_in_reverse && ws_error_action != nowarn_ws_error) check_whitespace(line, len, patch->ws_rule); added++; @@ -1666,7 +1669,10 @@ static int parse_fragment(const char *line, unsigned long size, * The (fragment->patch, fragment->size) pair points into the memory given * by the caller, not a copy, when we return. */ -static int parse_single_patch(const char *line, unsigned long size, struct patch *patch) +static int parse_single_patch(struct apply_state *state, + const char *line, + unsigned long size, + struct patch *patch) { unsigned long offset = 0; unsigned long oldlines = 0, newlines = 0, context = 0; @@ -1678,7 +1684,7 @@ static int parse_single_patch(const char *line, unsigned long size, struct patch fragment = xcalloc(1, sizeof(*fragment)); fragment->linenr = state_linenr; - len = parse_fragment(line, size, patch, fragment); + len = parse_fragment(state, line, size, patch, fragment); if (len <= 0) die(_("corrupt patch at line %d"), state_linenr); fragment->patch = line; @@ -2008,8 +2014,10 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si ? patch->new_name : patch->old_name); - patchsize = parse_single_patch(buffer + offset + hdrsize, - size - offset - hdrsize, patch); + patchsize = parse_single_patch(state, + buffer + offset + hdrsize, + size - offset - hdrsize, + patch); if (!patchsize) { static const char git_binary[] = "GIT binary patch\n"; @@ -2741,7 +2749,7 @@ static int apply_one_fragment(struct apply_state *state, if (len < size && patch[len] == '\\') plen--; first = *patch; - if (apply_in_reverse) { + if (state->apply_in_reverse) { if (first == '-') first = '+'; else if (first == '+') @@ -2914,7 +2922,7 @@ static int apply_one_fragment(struct apply_state *state, if (apply_verbosely && applied_pos != pos) { int offset = applied_pos - pos; - if (apply_in_reverse) + if (state->apply_in_reverse) offset = 0 - offset; fprintf_ln(stderr, Q_("Hunk #%d succeeded at %d (offset %d line).", @@ -2948,7 +2956,9 @@ static int apply_one_fragment(struct apply_state *state, return (applied_pos < 0); } -static int apply_binary_fragment(struct image *img, struct patch *patch) +static int apply_binary_fragment(struct apply_state *state, + struct image *img, + struct patch *patch) { struct fragment *fragment = patch->fragments; unsigned long len; @@ -2961,7 +2971,7 @@ static int apply_binary_fragment(struct image *img, struct patch *patch) patch->old_name); /* Binary patch is irreversible without the optional second hunk */ - if (apply_in_reverse) { + if (state->apply_in_reverse) { if (!fragment->next) return error("cannot reverse-apply a binary patch " "without the reverse hunk to '%s'", @@ -2994,7 +3004,9 @@ static int apply_binary_fragment(struct image *img, struct patch *patch) * but the preimage prepared by the caller in "img" is freed here * or in the helper function apply_binary_fragment() this calls. */ -static int apply_binary(struct image *img, struct patch *patch) +static int apply_binary(struct apply_state *state, + struct image *img, + struct patch *patch) { const char *name = patch->old_name ? patch->old_name : patch->new_name; unsigned char sha1[20]; @@ -3055,7 +3067,7 @@ static int apply_binary(struct image *img, struct patch *patch) * apply the patch data to it, which is stored * in the patch->fragments->{patch,size}. */ - if (apply_binary_fragment(img, patch)) + if (apply_binary_fragment(state, img, patch)) return error(_("binary patch does not apply to '%s'"), name); @@ -3078,7 +3090,7 @@ static int apply_fragments(struct apply_state *state, struct image *img, struct int nth = 0; if (patch->is_binary) - return apply_binary(img, patch); + return apply_binary(state, img, patch); while (frag) { nth++; @@ -4417,7 +4429,7 @@ static int apply_patch(struct apply_state *state, free_patch(patch); break; } - if (apply_in_reverse) + if (state->apply_in_reverse) reverse_patches(patch); if (use_patch(state, patch)) { patch_stats(patch); @@ -4615,7 +4627,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 0, "ignore-whitespace", NULL, NULL, N_("ignore changes in whitespace when finding context"), PARSE_OPT_NOARG, option_parse_space_change }, - OPT_BOOL('R', "reverse", &apply_in_reverse, + OPT_BOOL('R', "reverse", &state.apply_in_reverse, N_("apply the patch in reverse")), OPT_BOOL(0, "unidiff-zero", &state.unidiff_zero, N_("don't expect at least one line of context")), From 30b5ae4d41c7e5b5655fb0e737db4764a17033c0 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:51 +0200 Subject: [PATCH 14/50] builtin/apply: move 'apply_with_reject' global into 'struct apply_state' To libify the apply functionality the 'apply_with_reject' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 796d990910..8692e2f7ef 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -31,6 +31,7 @@ struct apply_state { /* These boolean parameters control how the apply is done */ int apply_in_reverse; + int apply_with_reject; int unidiff_zero; }; @@ -50,7 +51,6 @@ static int diffstat; static int numstat; static int summary; static int apply = 1; -static int apply_with_reject; static int apply_verbosely; static int allow_overlap; static int no_add; @@ -3096,7 +3096,7 @@ static int apply_fragments(struct apply_state *state, struct image *img, struct nth++; if (apply_one_fragment(state, img, frag, inaccurate_eof, ws_rule, nth)) { error(_("patch failed: %s:%ld"), name, frag->oldpos); - if (!apply_with_reject) + if (!state->apply_with_reject) return -1; frag->rejected = 1; } @@ -4462,11 +4462,11 @@ static int apply_patch(struct apply_state *state, if ((state->check || apply) && check_patch_list(state, list) < 0 && - !apply_with_reject) + !state->apply_with_reject) exit(1); if (apply && write_out_results(list)) { - if (apply_with_reject) + if (state->apply_with_reject) exit(1); /* with --3way, we still need to write the index out */ return 1; @@ -4631,7 +4631,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("apply the patch in reverse")), OPT_BOOL(0, "unidiff-zero", &state.unidiff_zero, N_("don't expect at least one line of context")), - OPT_BOOL(0, "reject", &apply_with_reject, + OPT_BOOL(0, "reject", &state.apply_with_reject, N_("leave the rejected hunks in corresponding *.rej files")), OPT_BOOL(0, "allow-overlap", &allow_overlap, N_("allow overlapping hunks")), @@ -4653,7 +4653,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, state.prefix, builtin_apply_options, apply_usage, 0); - if (apply_with_reject && threeway) + if (state.apply_with_reject && threeway) die("--reject and --3way cannot be used together."); if (cached && threeway) die("--cached and --3way cannot be used together."); @@ -4662,7 +4662,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) die(_("--3way outside a repository")); state.check_index = 1; } - if (apply_with_reject) + if (state.apply_with_reject) apply = apply_verbosely = 1; if (!force_apply && (diffstat || numstat || summary || state.check || fake_ancestor)) apply = 0; From 5cae882d27c99604bc654ea35102d17b178affdd Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:52 +0200 Subject: [PATCH 15/50] builtin/apply: move 'apply_verbosely' global into 'struct apply_state' To libify the apply functionality the 'apply_verbosely' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 8692e2f7ef..07dc89d153 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -32,6 +32,7 @@ struct apply_state { /* These boolean parameters control how the apply is done */ int apply_in_reverse; int apply_with_reject; + int apply_verbosely; int unidiff_zero; }; @@ -51,7 +52,6 @@ static int diffstat; static int numstat; static int summary; static int apply = 1; -static int apply_verbosely; static int allow_overlap; static int no_add; static int threeway; @@ -2805,7 +2805,7 @@ static int apply_one_fragment(struct apply_state *state, /* Ignore it, we already handled it */ break; default: - if (apply_verbosely) + if (state->apply_verbosely) error(_("invalid start of line: '%c'"), first); applied_pos = -1; goto out; @@ -2920,7 +2920,7 @@ static int apply_one_fragment(struct apply_state *state, apply = 0; } - if (apply_verbosely && applied_pos != pos) { + if (state->apply_verbosely && applied_pos != pos) { int offset = applied_pos - pos; if (state->apply_in_reverse) offset = 0 - offset; @@ -2942,7 +2942,7 @@ static int apply_one_fragment(struct apply_state *state, leading, trailing, applied_pos+1); update_image(img, applied_pos, &preimage, &postimage); } else { - if (apply_verbosely) + if (state->apply_verbosely) error(_("while searching for:\n%.*s"), (int)(old - oldlines), oldlines); } @@ -3856,7 +3856,7 @@ static int check_patch_list(struct apply_state *state, struct patch *patch) prepare_symlink_changes(patch); prepare_fn_table(patch); while (patch) { - if (apply_verbosely) + if (state->apply_verbosely) say_patch_name(stderr, _("Checking patch %s..."), patch); err |= check_patch(state, patch); @@ -4287,7 +4287,7 @@ static void write_out_one_result(struct patch *patch, int phase) create_file(patch); } -static int write_out_one_reject(struct patch *patch) +static int write_out_one_reject(struct apply_state *state, struct patch *patch) { FILE *rej; char namebuf[PATH_MAX]; @@ -4302,7 +4302,7 @@ static int write_out_one_reject(struct patch *patch) } if (!cnt) { - if (apply_verbosely) + if (state->apply_verbosely) say_patch_name(stderr, _("Applied patch %s cleanly."), patch); return 0; @@ -4358,7 +4358,7 @@ static int write_out_one_reject(struct patch *patch) return -1; } -static int write_out_results(struct patch *list) +static int write_out_results(struct apply_state *state, struct patch *list) { int phase; int errs = 0; @@ -4373,7 +4373,7 @@ static int write_out_results(struct patch *list) else { write_out_one_result(l, phase); if (phase == 1) { - if (write_out_one_reject(l)) + if (write_out_one_reject(state, l)) errs = 1; if (l->conflicted_threeway) { string_list_append(&cpath, l->new_name); @@ -4437,7 +4437,7 @@ static int apply_patch(struct apply_state *state, listp = &patch->next; } else { - if (apply_verbosely) + if (state->apply_verbosely) say_patch_name(stderr, _("Skipped patch '%s'."), patch); free_patch(patch); skipped_patch++; @@ -4465,7 +4465,7 @@ static int apply_patch(struct apply_state *state, !state->apply_with_reject) exit(1); - if (apply && write_out_results(list)) { + if (apply && write_out_results(state, list)) { if (state->apply_with_reject) exit(1); /* with --3way, we still need to write the index out */ @@ -4635,7 +4635,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("leave the rejected hunks in corresponding *.rej files")), OPT_BOOL(0, "allow-overlap", &allow_overlap, N_("allow overlapping hunks")), - OPT__VERBOSE(&apply_verbosely, N_("be verbose")), + OPT__VERBOSE(&state.apply_verbosely, N_("be verbose")), OPT_BIT(0, "inaccurate-eof", &options, N_("tolerate incorrectly detected missing new-line at the end of file"), INACCURATE_EOF), @@ -4663,7 +4663,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) state.check_index = 1; } if (state.apply_with_reject) - apply = apply_verbosely = 1; + apply = state.apply_verbosely = 1; if (!force_apply && (diffstat || numstat || summary || state.check || fake_ancestor)) apply = 0; if (state.check_index && is_not_gitdir) From 901f9c6d42dd9857ecdac76413014c1497d34614 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:53 +0200 Subject: [PATCH 16/50] builtin/apply: move 'update_index' global into 'struct apply_state' To libify the apply functionality the 'update_index' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 07dc89d153..7b5abb936e 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -28,6 +28,7 @@ struct apply_state { /* These control what gets looked at and modified */ int check; /* preimage must match working tree, don't actually apply */ int check_index; /* preimage must match the indexed version */ + int update_index; /* check_index && apply */ /* These boolean parameters control how the apply is done */ int apply_in_reverse; @@ -46,7 +47,6 @@ static int newfd = -1; static int state_p_value = 1; static int p_value_known; -static int update_index; static int cached; static int diffstat; static int numstat; @@ -4090,9 +4090,9 @@ static void patch_stats(struct patch *patch) } } -static void remove_file(struct patch *patch, int rmdir_empty) +static void remove_file(struct apply_state *state, struct patch *patch, int rmdir_empty) { - if (update_index) { + if (state->update_index) { if (remove_file_from_cache(patch->old_name) < 0) die(_("unable to remove %s from index"), patch->old_name); } @@ -4103,14 +4103,18 @@ static void remove_file(struct patch *patch, int rmdir_empty) } } -static void add_index_file(const char *path, unsigned mode, void *buf, unsigned long size) +static void add_index_file(struct apply_state *state, + const char *path, + unsigned mode, + void *buf, + unsigned long size) { struct stat st; struct cache_entry *ce; int namelen = strlen(path); unsigned ce_size = cache_entry_size(namelen); - if (!update_index) + if (!state->update_index) return; ce = xcalloc(1, ce_size); @@ -4220,13 +4224,14 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned die_errno(_("unable to write file '%s' mode %o"), path, mode); } -static void add_conflicted_stages_file(struct patch *patch) +static void add_conflicted_stages_file(struct apply_state *state, + struct patch *patch) { int stage, namelen; unsigned ce_size, mode; struct cache_entry *ce; - if (!update_index) + if (!state->update_index) return; namelen = strlen(patch->new_name); ce_size = cache_entry_size(namelen); @@ -4247,7 +4252,7 @@ static void add_conflicted_stages_file(struct patch *patch) } } -static void create_file(struct patch *patch) +static void create_file(struct apply_state *state, struct patch *patch) { char *path = patch->new_name; unsigned mode = patch->new_mode; @@ -4259,22 +4264,24 @@ static void create_file(struct patch *patch) create_one_file(path, mode, buf, size); if (patch->conflicted_threeway) - add_conflicted_stages_file(patch); + add_conflicted_stages_file(state, patch); else - add_index_file(path, mode, buf, size); + add_index_file(state, path, mode, buf, size); } /* phase zero is to remove, phase one is to create */ -static void write_out_one_result(struct patch *patch, int phase) +static void write_out_one_result(struct apply_state *state, + struct patch *patch, + int phase) { if (patch->is_delete > 0) { if (phase == 0) - remove_file(patch, 1); + remove_file(state, patch, 1); return; } if (patch->is_new > 0 || patch->is_copy) { if (phase == 1) - create_file(patch); + create_file(state, patch); return; } /* @@ -4282,9 +4289,9 @@ static void write_out_one_result(struct patch *patch, int phase) * thing: remove the old, write the new */ if (phase == 0) - remove_file(patch, patch->is_rename); + remove_file(state, patch, patch->is_rename); if (phase == 1) - create_file(patch); + create_file(state, patch); } static int write_out_one_reject(struct apply_state *state, struct patch *patch) @@ -4371,7 +4378,7 @@ static int write_out_results(struct apply_state *state, struct patch *list) if (l->rejected) errs = 1; else { - write_out_one_result(l, phase); + write_out_one_result(state, l, phase); if (phase == 1) { if (write_out_one_reject(state, l)) errs = 1; @@ -4451,8 +4458,8 @@ static int apply_patch(struct apply_state *state, if (whitespace_error && (ws_error_action == die_on_ws_error)) apply = 0; - update_index = state->check_index && apply; - if (update_index && newfd < 0) + state->update_index = state->check_index && apply; + if (state->update_index && newfd < 0) newfd = hold_locked_index(&lock_file, 1); if (state->check_index) { @@ -4727,7 +4734,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) whitespace_error); } - if (update_index) { + if (state.update_index) { if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) die(_("Unable to write new index file")); } From 6ca4c390933597f20db006445e844797ca7cd2c9 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:54 +0200 Subject: [PATCH 17/50] builtin/apply: move 'allow_overlap' global into 'struct apply_state' To libify the apply functionality the 'allow_overlap' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 7b5abb936e..ad3bec4431 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -31,6 +31,7 @@ struct apply_state { int update_index; /* check_index && apply */ /* These boolean parameters control how the apply is done */ + int allow_overlap; int apply_in_reverse; int apply_with_reject; int apply_verbosely; @@ -52,7 +53,6 @@ static int diffstat; static int numstat; static int summary; static int apply = 1; -static int allow_overlap; static int no_add; static int threeway; static int unsafe_paths; @@ -2627,7 +2627,8 @@ static void remove_last_line(struct image *img) * apply at applied_pos (counts in line numbers) in "img". * Update "img" to remove "preimage" and replace it with "postimage". */ -static void update_image(struct image *img, +static void update_image(struct apply_state *state, + struct image *img, int applied_pos, struct image *preimage, struct image *postimage) @@ -2692,7 +2693,7 @@ static void update_image(struct image *img, memcpy(img->line + applied_pos, postimage->line, postimage->nr * sizeof(*img->line)); - if (!allow_overlap) + if (!state->allow_overlap) for (i = 0; i < postimage->nr; i++) img->line[applied_pos + i].flag |= LINE_PATCHED; img->nr = nr; @@ -2940,7 +2941,7 @@ static int apply_one_fragment(struct apply_state *state, fprintf_ln(stderr, _("Context reduced to (%ld/%ld)" " to apply fragment at %d"), leading, trailing, applied_pos+1); - update_image(img, applied_pos, &preimage, &postimage); + update_image(state, img, applied_pos, &preimage, &postimage); } else { if (state->apply_verbosely) error(_("while searching for:\n%.*s"), @@ -4640,7 +4641,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("don't expect at least one line of context")), OPT_BOOL(0, "reject", &state.apply_with_reject, N_("leave the rejected hunks in corresponding *.rej files")), - OPT_BOOL(0, "allow-overlap", &allow_overlap, + OPT_BOOL(0, "allow-overlap", &state.allow_overlap, N_("allow overlapping hunks")), OPT__VERBOSE(&state.apply_verbosely, N_("be verbose")), OPT_BIT(0, "inaccurate-eof", &options, From 885eefb12d35e416e637a92d8a6e7ac17eefd5cc Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:55 +0200 Subject: [PATCH 18/50] builtin/apply: move 'cached' global into 'struct apply_state' To libify the apply functionality the 'cached' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index ad3bec4431..9cba4606eb 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -26,6 +26,7 @@ struct apply_state { int prefix_length; /* These control what gets looked at and modified */ + int cached; /* apply to the index only */ int check; /* preimage must match working tree, don't actually apply */ int check_index; /* preimage must match the indexed version */ int update_index; /* check_index && apply */ @@ -42,13 +43,11 @@ struct apply_state { * --stat does just a diffstat, and doesn't actually apply * --numstat does numeric diffstat, and doesn't actually apply * --index-info shows the old and new index info for paths if available. - * --cached updates only the cache without ever touching the working tree. */ static int newfd = -1; static int state_p_value = 1; static int p_value_known; -static int cached; static int diffstat; static int numstat; static int summary; @@ -3264,7 +3263,7 @@ static int load_patch_target(struct apply_state *state, const char *name, unsigned expected_mode) { - if (cached || state->check_index) { + if (state->cached || state->check_index) { if (read_file_or_gitlink(ce, buf)) return error(_("read of %s failed"), name); } else if (name) { @@ -3537,7 +3536,7 @@ static int check_preimage(struct apply_state *state, return error(_("path %s has been renamed/deleted"), old_name); if (previous) { st_mode = previous->new_mode; - } else if (!cached) { + } else if (!state->cached) { stat_ret = lstat(old_name, st); if (stat_ret && errno != ENOENT) return error(_("%s: %s"), old_name, strerror(errno)); @@ -3555,9 +3554,9 @@ static int check_preimage(struct apply_state *state, if (checkout_target(&the_index, *ce, st)) return -1; } - if (!cached && verify_index_match(*ce, st)) + if (!state->cached && verify_index_match(*ce, st)) return error(_("%s: does not match index"), old_name); - if (cached) + if (state->cached) st_mode = (*ce)->ce_mode; } else if (stat_ret < 0) { if (patch->is_new < 0) @@ -3565,7 +3564,7 @@ static int check_preimage(struct apply_state *state, return error(_("%s: %s"), old_name, strerror(errno)); } - if (!cached && !previous) + if (!state->cached && !previous) st_mode = ce_mode_from_stat(*ce, st->st_mode); if (patch->is_new < 0) @@ -3603,7 +3602,7 @@ static int check_to_create(struct apply_state *state, cache_name_pos(new_name, strlen(new_name)) >= 0 && !ok_if_exists) return EXISTS_IN_INDEX; - if (cached) + if (state->cached) return 0; if (!lstat(new_name, &nst)) { @@ -4097,7 +4096,7 @@ static void remove_file(struct apply_state *state, struct patch *patch, int rmdi if (remove_file_from_cache(patch->old_name) < 0) die(_("unable to remove %s from index"), patch->old_name); } - if (!cached) { + if (!state->cached) { if (!remove_or_warn(patch->old_mode, patch->old_name) && rmdir_empty) { remove_path(patch->old_name); } @@ -4130,7 +4129,7 @@ static void add_index_file(struct apply_state *state, get_sha1_hex(s, ce->sha1)) die(_("corrupt patch for submodule %s"), path); } else { - if (!cached) { + if (!state->cached) { if (lstat(path, &st) < 0) die_errno(_("unable to stat newly created file '%s'"), path); @@ -4182,9 +4181,13 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, * which is true 99% of the time anyway. If they don't, * we create them and try again. */ -static void create_one_file(char *path, unsigned mode, const char *buf, unsigned long size) +static void create_one_file(struct apply_state *state, + char *path, + unsigned mode, + const char *buf, + unsigned long size) { - if (cached) + if (state->cached) return; if (!try_create_file(path, mode, buf, size)) return; @@ -4262,7 +4265,7 @@ static void create_file(struct apply_state *state, struct patch *patch) if (!mode) mode = S_IFREG | 0644; - create_one_file(path, mode, buf, size); + create_one_file(state, path, mode, buf, size); if (patch->conflicted_threeway) add_conflicted_stages_file(state, patch); @@ -4611,7 +4614,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("instead of applying the patch, see if the patch is applicable")), OPT_BOOL(0, "index", &state.check_index, N_("make sure the patch is applicable to the current index")), - OPT_BOOL(0, "cached", &cached, + OPT_BOOL(0, "cached", &state.cached, N_("apply a patch without touching the working tree")), OPT_BOOL(0, "unsafe-paths", &unsafe_paths, N_("accept a patch that touches outside the working area")), @@ -4663,7 +4666,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) if (state.apply_with_reject && threeway) die("--reject and --3way cannot be used together."); - if (cached && threeway) + if (state.cached && threeway) die("--cached and --3way cannot be used together."); if (threeway) { if (is_not_gitdir) @@ -4676,7 +4679,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) apply = 0; if (state.check_index && is_not_gitdir) die(_("--index outside a repository")); - if (cached) { + if (state.cached) { if (is_not_gitdir) die(_("--cached outside a repository")); state.check_index = 1; From c4f5c39862671e7de1ffca959220ef94385b1972 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:56 +0200 Subject: [PATCH 19/50] builtin/apply: move 'diffstat' global into 'struct apply_state' To libify the apply functionality the 'diffstat' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 9cba4606eb..d940125ee2 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -31,6 +31,9 @@ struct apply_state { int check_index; /* preimage must match the indexed version */ int update_index; /* check_index && apply */ + /* These control cosmetic aspect of the output */ + int diffstat; /* just show a diffstat, and don't actually apply */ + /* These boolean parameters control how the apply is done */ int allow_overlap; int apply_in_reverse; @@ -40,7 +43,6 @@ struct apply_state { }; /* - * --stat does just a diffstat, and doesn't actually apply * --numstat does numeric diffstat, and doesn't actually apply * --index-info shows the old and new index info for paths if available. */ @@ -48,7 +50,6 @@ static int newfd = -1; static int state_p_value = 1; static int p_value_known; -static int diffstat; static int numstat; static int summary; static int apply = 1; @@ -4486,7 +4487,7 @@ static int apply_patch(struct apply_state *state, if (fake_ancestor) build_fake_ancestor(list, fake_ancestor); - if (diffstat) + if (state->diffstat) stat_patch_list(list); if (numstat) @@ -4602,7 +4603,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) 0, option_parse_p }, OPT_BOOL(0, "no-add", &no_add, N_("ignore additions made by the patch")), - OPT_BOOL(0, "stat", &diffstat, + OPT_BOOL(0, "stat", &state.diffstat, N_("instead of applying the patch, output diffstat for the input")), OPT_NOOP_NOARG(0, "allow-binary-replacement"), OPT_NOOP_NOARG(0, "binary"), @@ -4675,7 +4676,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) } if (state.apply_with_reject) apply = state.apply_verbosely = 1; - if (!force_apply && (diffstat || numstat || summary || state.check || fake_ancestor)) + if (!force_apply && (state.diffstat || numstat || summary || state.check || fake_ancestor)) apply = 0; if (state.check_index && is_not_gitdir) die(_("--index outside a repository")); From 179070b91c0ae1baf889f083596398a4f72286ea Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:57 +0200 Subject: [PATCH 20/50] builtin/apply: move 'numstat' global into 'struct apply_state' To libify the apply functionality the 'numstat' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index d940125ee2..47a45a71d5 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -33,6 +33,7 @@ struct apply_state { /* These control cosmetic aspect of the output */ int diffstat; /* just show a diffstat, and don't actually apply */ + int numstat; /* just show a numeric diffstat, and don't actually apply */ /* These boolean parameters control how the apply is done */ int allow_overlap; @@ -43,14 +44,12 @@ struct apply_state { }; /* - * --numstat does numeric diffstat, and doesn't actually apply * --index-info shows the old and new index info for paths if available. */ static int newfd = -1; static int state_p_value = 1; static int p_value_known; -static int numstat; static int summary; static int apply = 1; static int no_add; @@ -4490,7 +4489,7 @@ static int apply_patch(struct apply_state *state, if (state->diffstat) stat_patch_list(list); - if (numstat) + if (state->numstat) numstat_patch_list(list); if (summary) @@ -4607,7 +4606,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("instead of applying the patch, output diffstat for the input")), OPT_NOOP_NOARG(0, "allow-binary-replacement"), OPT_NOOP_NOARG(0, "binary"), - OPT_BOOL(0, "numstat", &numstat, + OPT_BOOL(0, "numstat", &state.numstat, N_("show number of added and deleted lines in decimal notation")), OPT_BOOL(0, "summary", &summary, N_("instead of applying the patch, output a summary for the input")), @@ -4676,7 +4675,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) } if (state.apply_with_reject) apply = state.apply_verbosely = 1; - if (!force_apply && (state.diffstat || numstat || summary || state.check || fake_ancestor)) + if (!force_apply && (state.diffstat || state.numstat || summary || state.check || fake_ancestor)) apply = 0; if (state.check_index && is_not_gitdir) die(_("--index outside a repository")); From 79a3efda795a88403cea3e9ff321b4b668f393d9 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:58 +0200 Subject: [PATCH 21/50] builtin/apply: move 'summary' global into 'struct apply_state' To libify the apply functionality the 'summary' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 47a45a71d5..f174a42a55 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -34,6 +34,7 @@ struct apply_state { /* These control cosmetic aspect of the output */ int diffstat; /* just show a diffstat, and don't actually apply */ int numstat; /* just show a numeric diffstat, and don't actually apply */ + int summary; /* just report creation, deletion, etc, and don't actually apply */ /* These boolean parameters control how the apply is done */ int allow_overlap; @@ -50,7 +51,6 @@ static int newfd = -1; static int state_p_value = 1; static int p_value_known; -static int summary; static int apply = 1; static int no_add; static int threeway; @@ -4492,7 +4492,7 @@ static int apply_patch(struct apply_state *state, if (state->numstat) numstat_patch_list(list); - if (summary) + if (state->summary) summary_patch_list(list); free_patch_list(list); @@ -4608,7 +4608,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) OPT_NOOP_NOARG(0, "binary"), OPT_BOOL(0, "numstat", &state.numstat, N_("show number of added and deleted lines in decimal notation")), - OPT_BOOL(0, "summary", &summary, + OPT_BOOL(0, "summary", &state.summary, N_("instead of applying the patch, output a summary for the input")), OPT_BOOL(0, "check", &state.check, N_("instead of applying the patch, see if the patch is applicable")), @@ -4675,7 +4675,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) } if (state.apply_with_reject) apply = state.apply_verbosely = 1; - if (!force_apply && (state.diffstat || state.numstat || summary || state.check || fake_ancestor)) + if (!force_apply && (state.diffstat || state.numstat || state.summary || state.check || fake_ancestor)) apply = 0; if (state.check_index && is_not_gitdir) die(_("--index outside a repository")); From b12e888f7a9489b964ad266b27d7fcfa62fa78e4 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:10:59 +0200 Subject: [PATCH 22/50] builtin/apply: move 'threeway' global into 'struct apply_state' To libify the apply functionality the 'threeway' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index f174a42a55..d00017baf1 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -41,6 +41,7 @@ struct apply_state { int apply_in_reverse; int apply_with_reject; int apply_verbosely; + int threeway; int unidiff_zero; }; @@ -53,7 +54,6 @@ static int state_p_value = 1; static int p_value_known; static int apply = 1; static int no_add; -static int threeway; static int unsafe_paths; static const char *fake_ancestor; static int line_termination = '\n'; @@ -3491,7 +3491,7 @@ static int apply_data(struct apply_state *state, struct patch *patch, if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) { /* Note: with --reject, apply_fragments() returns 0 */ - if (!threeway || try_threeway(state, &image, patch, st, ce) < 0) + if (!state->threeway || try_threeway(state, &image, patch, st, ce) < 0) return -1; } patch->result = image.buf; @@ -3786,7 +3786,7 @@ static int check_patch(struct apply_state *state, struct patch *patch) ((0 < patch->is_new) || patch->is_rename || patch->is_copy)) { int err = check_to_create(state, new_name, ok_if_exists); - if (err && threeway) { + if (err && state->threeway) { patch->direct_to_threeway = 1; } else switch (err) { case 0: @@ -4620,7 +4620,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("accept a patch that touches outside the working area")), OPT_BOOL(0, "apply", &force_apply, N_("also apply the patch (use with --stat/--summary/--check)")), - OPT_BOOL('3', "3way", &threeway, + OPT_BOOL('3', "3way", &state.threeway, N_( "attempt three-way merge if a patch does not apply")), OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor, N_("build a temporary index based on embedded index information")), @@ -4664,11 +4664,11 @@ int cmd_apply(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, state.prefix, builtin_apply_options, apply_usage, 0); - if (state.apply_with_reject && threeway) + if (state.apply_with_reject && state.threeway) die("--reject and --3way cannot be used together."); - if (state.cached && threeway) + if (state.cached && state.threeway) die("--cached and --3way cannot be used together."); - if (threeway) { + if (state.threeway) { if (is_not_gitdir) die(_("--3way outside a repository")); state.check_index = 1; From 1ff36a107f609978dedd8c5b56aad8ca6276f975 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:00 +0200 Subject: [PATCH 23/50] builtin/apply: move 'no_add' global into 'struct apply_state' To libify the apply functionality the 'no_add' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index d00017baf1..604e7bf8ff 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -41,6 +41,7 @@ struct apply_state { int apply_in_reverse; int apply_with_reject; int apply_verbosely; + int no_add; int threeway; int unidiff_zero; }; @@ -53,7 +54,6 @@ static int newfd = -1; static int state_p_value = 1; static int p_value_known; static int apply = 1; -static int no_add; static int unsafe_paths; static const char *fake_ancestor; static int line_termination = '\n'; @@ -2782,7 +2782,7 @@ static int apply_one_fragment(struct apply_state *state, /* Fall-through for ' ' */ case '+': /* --no-add does not add new lines */ - if (first == '+' && no_add) + if (first == '+' && state->no_add) break; start = newlines.len; @@ -4600,7 +4600,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 'p', NULL, NULL, N_("num"), N_("remove leading slashes from traditional diff paths"), 0, option_parse_p }, - OPT_BOOL(0, "no-add", &no_add, + OPT_BOOL(0, "no-add", &state.no_add, N_("ignore additions made by the patch")), OPT_BOOL(0, "stat", &state.diffstat, N_("instead of applying the patch, output diffstat for the input")), From 6c0c2bf56c7a3484d157661fb4660f5aefe67a83 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:01 +0200 Subject: [PATCH 24/50] builtin/apply: move 'unsafe_paths' global into 'struct apply_state' To libify the apply functionality the 'unsafe_paths' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 604e7bf8ff..4ef83c1be5 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -44,6 +44,7 @@ struct apply_state { int no_add; int threeway; int unidiff_zero; + int unsafe_paths; }; /* @@ -54,7 +55,6 @@ static int newfd = -1; static int state_p_value = 1; static int p_value_known; static int apply = 1; -static int unsafe_paths; static const char *fake_ancestor; static int line_termination = '\n'; static unsigned int p_context = UINT_MAX; @@ -3827,7 +3827,7 @@ static int check_patch(struct apply_state *state, struct patch *patch) } } - if (!unsafe_paths) + if (!state->unsafe_paths) die_on_unsafe_path(patch); /* @@ -4616,7 +4616,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("make sure the patch is applicable to the current index")), OPT_BOOL(0, "cached", &state.cached, N_("apply a patch without touching the working tree")), - OPT_BOOL(0, "unsafe-paths", &unsafe_paths, + OPT_BOOL(0, "unsafe-paths", &state.unsafe_paths, N_("accept a patch that touches outside the working area")), OPT_BOOL(0, "apply", &force_apply, N_("also apply the patch (use with --stat/--summary/--check)")), @@ -4685,7 +4685,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) state.check_index = 1; } if (state.check_index) - unsafe_paths = 0; + state.unsafe_paths = 0; for (i = 0; i < argc; i++) { const char *arg = argv[i]; From f4c9eaa49c5ed87b304a40b95b1d06d46a8cbfa9 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:02 +0200 Subject: [PATCH 25/50] builtin/apply: move 'line_termination' global into 'struct apply_state' To libify the apply functionality the 'line_termination' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 4ef83c1be5..95cd60a3ee 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -45,6 +45,9 @@ struct apply_state { int threeway; int unidiff_zero; int unsafe_paths; + + /* Other non boolean parameters */ + int line_termination; }; /* @@ -56,7 +59,6 @@ static int state_p_value = 1; static int p_value_known; static int apply = 1; static const char *fake_ancestor; -static int line_termination = '\n'; static unsigned int p_context = UINT_MAX; static const char * const apply_usage[] = { N_("git apply [] [...]"), @@ -3977,7 +3979,8 @@ static void stat_patch_list(struct patch *patch) print_stat_summary(stdout, files, adds, dels); } -static void numstat_patch_list(struct patch *patch) +static void numstat_patch_list(struct apply_state *state, + struct patch *patch) { for ( ; patch; patch = patch->next) { const char *name; @@ -3986,7 +3989,7 @@ static void numstat_patch_list(struct patch *patch) printf("-\t-\t"); else printf("%d\t%d\t", patch->lines_added, patch->lines_deleted); - write_name_quoted(name, stdout, line_termination); + write_name_quoted(name, stdout, state->line_termination); } } @@ -4490,7 +4493,7 @@ static int apply_patch(struct apply_state *state, stat_patch_list(list); if (state->numstat) - numstat_patch_list(list); + numstat_patch_list(state, list); if (state->summary) summary_patch_list(list); @@ -4565,6 +4568,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) memset(state, 0, sizeof(*state)); state->prefix = prefix; state->prefix_length = state->prefix ? strlen(state->prefix) : 0; + state->line_termination = '\n'; git_apply_config(); if (apply_default_whitespace) @@ -4625,7 +4629,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor, N_("build a temporary index based on embedded index information")), /* Think twice before adding "--nul" synonym to this */ - OPT_SET_INT('z', NULL, &line_termination, + OPT_SET_INT('z', NULL, &state.line_termination, N_("paths are separated with NUL character"), '\0'), OPT_INTEGER('C', NULL, &p_context, N_("ensure at least lines of context match")), From a0bfaf0796e416bb1cecd03e30af3e189a039a29 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:03 +0200 Subject: [PATCH 26/50] builtin/apply: move 'fake_ancestor' global into 'struct apply_state' To libify the apply functionality the 'fake_ancestor' variable should not be static and global to the file. Let's move it into 'struct apply_state'. By the way remove a comment about '--index-info' that was renamed '--build-fake-ancestor' in commit 26b28007689d27a921ea90e5a29fc8eb74b0d297 (apply: get rid of --index-info in favor of --build-fake-ancestor, Sep 17 2007). Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 95cd60a3ee..59b0f1b00a 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -47,18 +47,15 @@ struct apply_state { int unsafe_paths; /* Other non boolean parameters */ + const char *fake_ancestor; int line_termination; }; -/* - * --index-info shows the old and new index info for paths if available. - */ static int newfd = -1; static int state_p_value = 1; static int p_value_known; static int apply = 1; -static const char *fake_ancestor; static unsigned int p_context = UINT_MAX; static const char * const apply_usage[] = { N_("git apply [] [...]"), @@ -4486,8 +4483,8 @@ static int apply_patch(struct apply_state *state, return 1; } - if (fake_ancestor) - build_fake_ancestor(list, fake_ancestor); + if (state->fake_ancestor) + build_fake_ancestor(list, state->fake_ancestor); if (state->diffstat) stat_patch_list(list); @@ -4626,7 +4623,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("also apply the patch (use with --stat/--summary/--check)")), OPT_BOOL('3', "3way", &state.threeway, N_( "attempt three-way merge if a patch does not apply")), - OPT_FILENAME(0, "build-fake-ancestor", &fake_ancestor, + OPT_FILENAME(0, "build-fake-ancestor", &state.fake_ancestor, N_("build a temporary index based on embedded index information")), /* Think twice before adding "--nul" synonym to this */ OPT_SET_INT('z', NULL, &state.line_termination, @@ -4679,7 +4676,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) } if (state.apply_with_reject) apply = state.apply_verbosely = 1; - if (!force_apply && (state.diffstat || state.numstat || state.summary || state.check || fake_ancestor)) + if (!force_apply && (state.diffstat || state.numstat || state.summary || state.check || state.fake_ancestor)) apply = 0; if (state.check_index && is_not_gitdir) die(_("--index outside a repository")); From a48f9bb1b31329b29eed9808844c147f613b59ad Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:04 +0200 Subject: [PATCH 27/50] builtin/apply: move 'p_context' global into 'struct apply_state' To libify the apply functionality the 'p_context' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 59b0f1b00a..3c9f05262b 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -49,6 +49,7 @@ struct apply_state { /* Other non boolean parameters */ const char *fake_ancestor; int line_termination; + unsigned int p_context; }; static int newfd = -1; @@ -56,7 +57,6 @@ static int newfd = -1; static int state_p_value = 1; static int p_value_known; static int apply = 1; -static unsigned int p_context = UINT_MAX; static const char * const apply_usage[] = { N_("git apply [] [...]"), NULL @@ -2872,7 +2872,7 @@ static int apply_one_fragment(struct apply_state *state, break; /* Am I at my context limits? */ - if ((leading <= p_context) && (trailing <= p_context)) + if ((leading <= state->p_context) && (trailing <= state->p_context)) break; if (match_beginning || match_end) { match_beginning = match_end = 0; @@ -4566,6 +4566,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) state->prefix = prefix; state->prefix_length = state->prefix ? strlen(state->prefix) : 0; state->line_termination = '\n'; + state->p_context = UINT_MAX; git_apply_config(); if (apply_default_whitespace) @@ -4628,7 +4629,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) /* Think twice before adding "--nul" synonym to this */ OPT_SET_INT('z', NULL, &state.line_termination, N_("paths are separated with NUL character"), '\0'), - OPT_INTEGER('C', NULL, &p_context, + OPT_INTEGER('C', NULL, &state.p_context, N_("ensure at least lines of context match")), { OPTION_CALLBACK, 0, "whitespace", &whitespace_option, N_("action"), N_("detect new or modified lines that have whitespace errors"), From 574f5a59d85153309ea9856f425ca610074e1116 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:05 +0200 Subject: [PATCH 28/50] builtin/apply: move 'apply' global into 'struct apply_state' To libify the apply functionality the 'apply' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 3c9f05262b..c0c18ce9fd 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -26,6 +26,7 @@ struct apply_state { int prefix_length; /* These control what gets looked at and modified */ + int apply; /* this is not a dry-run */ int cached; /* apply to the index only */ int check; /* preimage must match working tree, don't actually apply */ int check_index; /* preimage must match the indexed version */ @@ -56,7 +57,7 @@ static int newfd = -1; static int state_p_value = 1; static int p_value_known; -static int apply = 1; + static const char * const apply_usage[] = { N_("git apply [] [...]"), NULL @@ -126,10 +127,11 @@ static void parse_ignorewhitespace_option(const char *option) die(_("unrecognized whitespace ignore option '%s'"), option); } -static void set_default_whitespace_mode(const char *whitespace_option) +static void set_default_whitespace_mode(struct apply_state *state, + const char *whitespace_option) { if (!whitespace_option && !apply_default_whitespace) - ws_error_action = (apply ? warn_on_ws_error : nowarn_ws_error); + ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); } /* @@ -2058,7 +2060,7 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si * without metadata change. A binary patch appears * empty to us here. */ - if ((apply || state->check) && + if ((state->apply || state->check) && (!patch->is_binary && !metadata_changes(patch))) die(_("patch with only garbage at line %d"), state_linenr); } @@ -2916,7 +2918,7 @@ static int apply_one_fragment(struct apply_state *state, * apply_data->apply_fragments->apply_one_fragment */ if (ws_error_action == die_on_ws_error) - apply = 0; + state->apply = 0; } if (state->apply_verbosely && applied_pos != pos) { @@ -4460,9 +4462,9 @@ static int apply_patch(struct apply_state *state, die(_("unrecognized input")); if (whitespace_error && (ws_error_action == die_on_ws_error)) - apply = 0; + state->apply = 0; - state->update_index = state->check_index && apply; + state->update_index = state->check_index && state->apply; if (state->update_index && newfd < 0) newfd = hold_locked_index(&lock_file, 1); @@ -4471,12 +4473,12 @@ static int apply_patch(struct apply_state *state, die(_("unable to read index file")); } - if ((state->check || apply) && + if ((state->check || state->apply) && check_patch_list(state, list) < 0 && !state->apply_with_reject) exit(1); - if (apply && write_out_results(state, list)) { + if (state->apply && write_out_results(state, list)) { if (state->apply_with_reject) exit(1); /* with --3way, we still need to write the index out */ @@ -4565,6 +4567,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) memset(state, 0, sizeof(*state)); state->prefix = prefix; state->prefix_length = state->prefix ? strlen(state->prefix) : 0; + state->apply = 1; state->line_termination = '\n'; state->p_context = UINT_MAX; @@ -4676,9 +4679,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix) state.check_index = 1; } if (state.apply_with_reject) - apply = state.apply_verbosely = 1; + state.apply = state.apply_verbosely = 1; if (!force_apply && (state.diffstat || state.numstat || state.summary || state.check || state.fake_ancestor)) - apply = 0; + state.apply = 0; if (state.check_index && is_not_gitdir) die(_("--index outside a repository")); if (state.cached) { @@ -4706,11 +4709,11 @@ int cmd_apply(int argc, const char **argv, const char *prefix) if (fd < 0) die_errno(_("can't open patch '%s'"), arg); read_stdin = 0; - set_default_whitespace_mode(whitespace_option); + set_default_whitespace_mode(&state, whitespace_option); errs |= apply_patch(&state, fd, arg, options); close(fd); } - set_default_whitespace_mode(whitespace_option); + set_default_whitespace_mode(&state, whitespace_option); if (read_stdin) errs |= apply_patch(&state, 0, "", options); if (whitespace_error) { @@ -4728,7 +4731,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) "%d lines add whitespace errors.", whitespace_error), whitespace_error); - if (applied_after_fixing_ws && apply) + if (applied_after_fixing_ws && state.apply) warning("%d line%s applied after" " fixing whitespace errors.", applied_after_fixing_ws, From b802355863814b331ffc4ae029b228472e874d1f Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:06 +0200 Subject: [PATCH 29/50] builtin/apply: move 'patch_input_file' global into 'struct apply_state' To libify the apply functionality the 'patch_input_file' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index c0c18ce9fd..fa9002898c 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -49,6 +49,7 @@ struct apply_state { /* Other non boolean parameters */ const char *fake_ancestor; + const char *patch_input_file; int line_termination; unsigned int p_context; }; @@ -79,7 +80,6 @@ static enum ws_ignore { } ws_ignore_action = ignore_ws_none; -static const char *patch_input_file; static struct strbuf root = STRBUF_INIT; static void parse_whitespace_option(const char *option) @@ -1525,7 +1525,11 @@ static int find_header(struct apply_state *state, return -1; } -static void record_ws_error(unsigned result, const char *line, int len, int linenr) +static void record_ws_error(struct apply_state *state, + unsigned result, + const char *line, + int len, + int linenr) { char *err; @@ -1539,15 +1543,18 @@ static void record_ws_error(unsigned result, const char *line, int len, int line err = whitespace_error_string(result); fprintf(stderr, "%s:%d: %s.\n%.*s\n", - patch_input_file, linenr, err, len, line); + state->patch_input_file, linenr, err, len, line); free(err); } -static void check_whitespace(const char *line, int len, unsigned ws_rule) +static void check_whitespace(struct apply_state *state, + const char *line, + int len, + unsigned ws_rule) { unsigned result = ws_check(line + 1, len - 1, ws_rule); - record_ws_error(result, line + 1, len - 2, state_linenr); + record_ws_error(state, result, line + 1, len - 2, state_linenr); } /* @@ -1602,12 +1609,12 @@ static int parse_fragment(struct apply_state *state, trailing++; if (!state->apply_in_reverse && ws_error_action == correct_ws_error) - check_whitespace(line, len, patch->ws_rule); + check_whitespace(state, line, len, patch->ws_rule); break; case '-': if (state->apply_in_reverse && ws_error_action != nowarn_ws_error) - check_whitespace(line, len, patch->ws_rule); + check_whitespace(state, line, len, patch->ws_rule); deleted++; oldlines--; trailing = 0; @@ -1615,7 +1622,7 @@ static int parse_fragment(struct apply_state *state, case '+': if (!state->apply_in_reverse && ws_error_action != nowarn_ws_error) - check_whitespace(line, len, patch->ws_rule); + check_whitespace(state, line, len, patch->ws_rule); added++; newlines--; trailing = 0; @@ -2904,7 +2911,7 @@ static int apply_one_fragment(struct apply_state *state, preimage.nr + applied_pos >= img->nr && (ws_rule & WS_BLANK_AT_EOF) && ws_error_action != nowarn_ws_error) { - record_ws_error(WS_BLANK_AT_EOF, "+", 1, + record_ws_error(state, WS_BLANK_AT_EOF, "+", 1, found_new_blank_lines_at_end); if (ws_error_action == correct_ws_error) { while (new_blank_lines_at_end--) @@ -4427,7 +4434,7 @@ static int apply_patch(struct apply_state *state, struct patch *list = NULL, **listp = &list; int skipped_patch = 0; - patch_input_file = filename; + state->patch_input_file = filename; read_patch_file(&buf, fd); offset = 0; while (offset < buf.len) { From 82f0dfca542e95b74ff967f10fb4247e11a2d9d9 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:07 +0200 Subject: [PATCH 30/50] builtin/apply: move 'limit_by_name' global into 'struct apply_state' To libify the apply functionality the 'limit_by_name' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index fa9002898c..0e3de17d05 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -52,6 +52,9 @@ struct apply_state { const char *patch_input_file; int line_termination; unsigned int p_context; + + /* Exclude and include path parameters */ + struct string_list limit_by_name; }; static int newfd = -1; @@ -1958,13 +1961,14 @@ static void prefix_patch(struct apply_state *state, struct patch *p) * include/exclude */ -static struct string_list limit_by_name; static int has_include; -static void add_name_limit(const char *name, int exclude) +static void add_name_limit(struct apply_state *state, + const char *name, + int exclude) { struct string_list_item *it; - it = string_list_append(&limit_by_name, name); + it = string_list_append(&state->limit_by_name, name); it->util = exclude ? NULL : (void *) 1; } @@ -1982,8 +1986,8 @@ static int use_patch(struct apply_state *state, struct patch *p) } /* See if it matches any of exclude/include rule */ - for (i = 0; i < limit_by_name.nr; i++) { - struct string_list_item *it = &limit_by_name.items[i]; + for (i = 0; i < state->limit_by_name.nr; i++) { + struct string_list_item *it = &state->limit_by_name.items[i]; if (!wildmatch(it->string, pathname, 0, NULL)) return (it->util != NULL); } @@ -4520,14 +4524,16 @@ static void git_apply_config(void) static int option_parse_exclude(const struct option *opt, const char *arg, int unset) { - add_name_limit(arg, 1); + struct apply_state *state = opt->value; + add_name_limit(state, arg, 1); return 0; } static int option_parse_include(const struct option *opt, const char *arg, int unset) { - add_name_limit(arg, 0); + struct apply_state *state = opt->value; + add_name_limit(state, arg, 0); has_include = 1; return 0; } @@ -4587,7 +4593,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) static void clear_apply_state(struct apply_state *state) { - /* empty for now */ + string_list_clear(&state->limit_by_name, 0); } int cmd_apply(int argc, const char **argv, const char *prefix) @@ -4603,10 +4609,10 @@ int cmd_apply(int argc, const char **argv, const char *prefix) const char *whitespace_option = NULL; struct option builtin_apply_options[] = { - { OPTION_CALLBACK, 0, "exclude", NULL, N_("path"), + { OPTION_CALLBACK, 0, "exclude", &state, N_("path"), N_("don't apply changes matching the given path"), 0, option_parse_exclude }, - { OPTION_CALLBACK, 0, "include", NULL, N_("path"), + { OPTION_CALLBACK, 0, "include", &state, N_("path"), N_("apply changes matching the given path"), 0, option_parse_include }, { OPTION_CALLBACK, 'p', NULL, NULL, N_("num"), From 0c1138cbdbf7a82f8373077b77a1878f742a5222 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:08 +0200 Subject: [PATCH 31/50] builtin/apply: move 'has_include' global into 'struct apply_state' To libify the apply functionality the 'has_include' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 0e3de17d05..ebbc7111f8 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -55,6 +55,7 @@ struct apply_state { /* Exclude and include path parameters */ struct string_list limit_by_name; + int has_include; }; static int newfd = -1; @@ -1961,7 +1962,6 @@ static void prefix_patch(struct apply_state *state, struct patch *p) * include/exclude */ -static int has_include; static void add_name_limit(struct apply_state *state, const char *name, int exclude) @@ -1997,7 +1997,7 @@ static int use_patch(struct apply_state *state, struct patch *p) * not used. Otherwise, we saw bunch of exclude rules (or none) * and such a path is used. */ - return !has_include; + return !state->has_include; } @@ -4534,7 +4534,7 @@ static int option_parse_include(const struct option *opt, { struct apply_state *state = opt->value; add_name_limit(state, arg, 0); - has_include = 1; + state->has_include = 1; return 0; } From dbd23433e7b3d95bb03b44e9da86f713f1e35e17 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:09 +0200 Subject: [PATCH 32/50] builtin/apply: move 'p_value' global into 'struct apply_state' To libify the apply functionality the 'p_value' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 151 +++++++++++++++++++++++++++++++----------------- 1 file changed, 99 insertions(+), 52 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index ebbc7111f8..843fafd629 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -51,6 +51,7 @@ struct apply_state { const char *fake_ancestor; const char *patch_input_file; int line_termination; + int p_value; unsigned int p_context; /* Exclude and include path parameters */ @@ -60,7 +61,6 @@ struct apply_state { static int newfd = -1; -static int state_p_value = 1; static int p_value_known; static const char * const apply_usage[] = { @@ -881,24 +881,24 @@ static void parse_traditional_patch(struct apply_state *state, q = guess_p_value(state, second); if (p < 0) p = q; if (0 <= p && p == q) { - state_p_value = p; + state->p_value = p; p_value_known = 1; } } if (is_dev_null(first)) { patch->is_new = 1; patch->is_delete = 0; - name = find_name_traditional(second, NULL, state_p_value); + name = find_name_traditional(second, NULL, state->p_value); patch->new_name = name; } else if (is_dev_null(second)) { patch->is_new = 0; patch->is_delete = 1; - name = find_name_traditional(first, NULL, state_p_value); + name = find_name_traditional(first, NULL, state->p_value); patch->old_name = name; } else { char *first_name; - first_name = find_name_traditional(first, NULL, state_p_value); - name = find_name_traditional(second, first_name, state_p_value); + first_name = find_name_traditional(first, NULL, state->p_value); + name = find_name_traditional(second, first_name, state->p_value); free(first_name); if (has_epoch_timestamp(first)) { patch->is_new = 1; @@ -917,7 +917,9 @@ static void parse_traditional_patch(struct apply_state *state, die(_("unable to find filename in patch at line %d"), state_linenr); } -static int gitdiff_hdrend(const char *line, struct patch *patch) +static int gitdiff_hdrend(struct apply_state *state, + const char *line, + struct patch *patch) { return -1; } @@ -934,10 +936,14 @@ static int gitdiff_hdrend(const char *line, struct patch *patch) #define DIFF_OLD_NAME 0 #define DIFF_NEW_NAME 1 -static void gitdiff_verify_name(const char *line, int isnull, char **name, int side) +static void gitdiff_verify_name(struct apply_state *state, + const char *line, + int isnull, + char **name, + int side) { if (!*name && !isnull) { - *name = find_name(line, NULL, state_p_value, TERM_TAB); + *name = find_name(line, NULL, state->p_value, TERM_TAB); return; } @@ -947,7 +953,7 @@ static void gitdiff_verify_name(const char *line, int isnull, char **name, int s if (isnull) die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), *name, state_linenr); - another = find_name(line, NULL, state_p_value, TERM_TAB); + another = find_name(line, NULL, state->p_value, TERM_TAB); if (!another || memcmp(another, *name, len + 1)) die((side == DIFF_NEW_NAME) ? _("git apply: bad git-diff - inconsistent new filename on line %d") : @@ -960,81 +966,105 @@ static void gitdiff_verify_name(const char *line, int isnull, char **name, int s } } -static int gitdiff_oldname(const char *line, struct patch *patch) +static int gitdiff_oldname(struct apply_state *state, + const char *line, + struct patch *patch) { - gitdiff_verify_name(line, patch->is_new, &patch->old_name, + gitdiff_verify_name(state, line, + patch->is_new, &patch->old_name, DIFF_OLD_NAME); return 0; } -static int gitdiff_newname(const char *line, struct patch *patch) +static int gitdiff_newname(struct apply_state *state, + const char *line, + struct patch *patch) { - gitdiff_verify_name(line, patch->is_delete, &patch->new_name, + gitdiff_verify_name(state, line, + patch->is_delete, &patch->new_name, DIFF_NEW_NAME); return 0; } -static int gitdiff_oldmode(const char *line, struct patch *patch) +static int gitdiff_oldmode(struct apply_state *state, + const char *line, + struct patch *patch) { patch->old_mode = strtoul(line, NULL, 8); return 0; } -static int gitdiff_newmode(const char *line, struct patch *patch) +static int gitdiff_newmode(struct apply_state *state, + const char *line, + struct patch *patch) { patch->new_mode = strtoul(line, NULL, 8); return 0; } -static int gitdiff_delete(const char *line, struct patch *patch) +static int gitdiff_delete(struct apply_state *state, + const char *line, + struct patch *patch) { patch->is_delete = 1; free(patch->old_name); patch->old_name = xstrdup_or_null(patch->def_name); - return gitdiff_oldmode(line, patch); + return gitdiff_oldmode(state, line, patch); } -static int gitdiff_newfile(const char *line, struct patch *patch) +static int gitdiff_newfile(struct apply_state *state, + const char *line, + struct patch *patch) { patch->is_new = 1; free(patch->new_name); patch->new_name = xstrdup_or_null(patch->def_name); - return gitdiff_newmode(line, patch); + return gitdiff_newmode(state, line, patch); } -static int gitdiff_copysrc(const char *line, struct patch *patch) +static int gitdiff_copysrc(struct apply_state *state, + const char *line, + struct patch *patch) { patch->is_copy = 1; free(patch->old_name); - patch->old_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); + patch->old_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } -static int gitdiff_copydst(const char *line, struct patch *patch) +static int gitdiff_copydst(struct apply_state *state, + const char *line, + struct patch *patch) { patch->is_copy = 1; free(patch->new_name); - patch->new_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); + patch->new_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } -static int gitdiff_renamesrc(const char *line, struct patch *patch) +static int gitdiff_renamesrc(struct apply_state *state, + const char *line, + struct patch *patch) { patch->is_rename = 1; free(patch->old_name); - patch->old_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); + patch->old_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } -static int gitdiff_renamedst(const char *line, struct patch *patch) +static int gitdiff_renamedst(struct apply_state *state, + const char *line, + struct patch *patch) { patch->is_rename = 1; free(patch->new_name); - patch->new_name = find_name(line, NULL, state_p_value ? state_p_value - 1 : 0, 0); + patch->new_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } -static int gitdiff_similarity(const char *line, struct patch *patch) +static int gitdiff_similarity(struct apply_state *state, + const char *line, + struct patch *patch) { unsigned long val = strtoul(line, NULL, 10); if (val <= 100) @@ -1042,7 +1072,9 @@ static int gitdiff_similarity(const char *line, struct patch *patch) return 0; } -static int gitdiff_dissimilarity(const char *line, struct patch *patch) +static int gitdiff_dissimilarity(struct apply_state *state, + const char *line, + struct patch *patch) { unsigned long val = strtoul(line, NULL, 10); if (val <= 100) @@ -1050,7 +1082,9 @@ static int gitdiff_dissimilarity(const char *line, struct patch *patch) return 0; } -static int gitdiff_index(const char *line, struct patch *patch) +static int gitdiff_index(struct apply_state *state, + const char *line, + struct patch *patch) { /* * index line is N hexadecimal, "..", N hexadecimal, @@ -1087,7 +1121,9 @@ static int gitdiff_index(const char *line, struct patch *patch) * This is normal for a diff that doesn't change anything: we'll fall through * into the next diff. Tell the parser to break out. */ -static int gitdiff_unrecognized(const char *line, struct patch *patch) +static int gitdiff_unrecognized(struct apply_state *state, + const char *line, + struct patch *patch) { return -1; } @@ -1096,15 +1132,17 @@ static int gitdiff_unrecognized(const char *line, struct patch *patch) * Skip p_value leading components from "line"; as we do not accept * absolute paths, return NULL in that case. */ -static const char *skip_tree_prefix(const char *line, int llen) +static const char *skip_tree_prefix(struct apply_state *state, + const char *line, + int llen) { int nslash; int i; - if (!state_p_value) + if (!state->p_value) return (llen && line[0] == '/') ? NULL : line; - nslash = state_p_value; + nslash = state->p_value; for (i = 0; i < llen; i++) { int ch = line[i]; if (ch == '/' && --nslash <= 0) @@ -1121,7 +1159,9 @@ static const char *skip_tree_prefix(const char *line, int llen) * creation or deletion of an empty file. In any of these cases, * both sides are the same name under a/ and b/ respectively. */ -static char *git_header_name(const char *line, int llen) +static char *git_header_name(struct apply_state *state, + const char *line, + int llen) { const char *name; const char *second = NULL; @@ -1139,7 +1179,7 @@ static char *git_header_name(const char *line, int llen) goto free_and_fail1; /* strip the a/b prefix including trailing slash */ - cp = skip_tree_prefix(first.buf, first.len); + cp = skip_tree_prefix(state, first.buf, first.len); if (!cp) goto free_and_fail1; strbuf_remove(&first, 0, cp - first.buf); @@ -1156,7 +1196,7 @@ static char *git_header_name(const char *line, int llen) if (*second == '"') { if (unquote_c_style(&sp, second, NULL)) goto free_and_fail1; - cp = skip_tree_prefix(sp.buf, sp.len); + cp = skip_tree_prefix(state, sp.buf, sp.len); if (!cp) goto free_and_fail1; /* They must match, otherwise ignore */ @@ -1167,7 +1207,7 @@ static char *git_header_name(const char *line, int llen) } /* unquoted second */ - cp = skip_tree_prefix(second, line + llen - second); + cp = skip_tree_prefix(state, second, line + llen - second); if (!cp) goto free_and_fail1; if (line + llen - cp != first.len || @@ -1182,7 +1222,7 @@ static char *git_header_name(const char *line, int llen) } /* unquoted first name */ - name = skip_tree_prefix(line, llen); + name = skip_tree_prefix(state, line, llen); if (!name) return NULL; @@ -1198,7 +1238,7 @@ static char *git_header_name(const char *line, int llen) if (unquote_c_style(&sp, second, NULL)) goto free_and_fail2; - np = skip_tree_prefix(sp.buf, sp.len); + np = skip_tree_prefix(state, sp.buf, sp.len); if (!np) goto free_and_fail2; @@ -1242,7 +1282,7 @@ static char *git_header_name(const char *line, int llen) */ if (!name[len + 1]) return NULL; /* no postimage name */ - second = skip_tree_prefix(name + len + 1, + second = skip_tree_prefix(state, name + len + 1, line_len - (len + 1)); if (!second) return NULL; @@ -1258,7 +1298,11 @@ static char *git_header_name(const char *line, int llen) } /* Verify that we recognize the lines following a git header */ -static int parse_git_header(const char *line, int len, unsigned int size, struct patch *patch) +static int parse_git_header(struct apply_state *state, + const char *line, + int len, + unsigned int size, + struct patch *patch) { unsigned long offset; @@ -1272,7 +1316,7 @@ static int parse_git_header(const char *line, int len, unsigned int size, struct * or removing or adding empty files), so we get * the default name from the header. */ - patch->def_name = git_header_name(line, len); + patch->def_name = git_header_name(state, line, len); if (patch->def_name && root.len) { char *s = xstrfmt("%s%s", root.buf, patch->def_name); free(patch->def_name); @@ -1285,7 +1329,7 @@ static int parse_git_header(const char *line, int len, unsigned int size, struct for (offset = len ; size > 0 ; offset += len, size -= len, line += len, state_linenr++) { static const struct opentry { const char *str; - int (*fn)(const char *, struct patch *); + int (*fn)(struct apply_state *, const char *, struct patch *); } optable[] = { { "@@ -", gitdiff_hdrend }, { "--- ", gitdiff_oldname }, @@ -1315,7 +1359,7 @@ static int parse_git_header(const char *line, int len, unsigned int size, struct int oplen = strlen(p->str); if (len < oplen || memcmp(p->str, line, oplen)) continue; - if (p->fn(line + oplen, patch) < 0) + if (p->fn(state, line + oplen, patch) < 0) return offset; break; } @@ -1485,7 +1529,7 @@ static int find_header(struct apply_state *state, * or mode change, so we handle that specially */ if (!memcmp("diff --git ", line, 11)) { - int git_hdr_len = parse_git_header(line, len, size, patch); + int git_hdr_len = parse_git_header(state, line, len, size, patch); if (git_hdr_len <= len) continue; if (!patch->old_name && !patch->new_name) { @@ -1494,8 +1538,8 @@ static int find_header(struct apply_state *state, "%d leading pathname component (line %d)", "git diff header lacks filename information when removing " "%d leading pathname components (line %d)", - state_p_value), - state_p_value, state_linenr); + state->p_value), + state->p_value, state_linenr); patch->old_name = xstrdup(patch->def_name); patch->new_name = xstrdup(patch->def_name); } @@ -4539,9 +4583,11 @@ static int option_parse_include(const struct option *opt, } static int option_parse_p(const struct option *opt, - const char *arg, int unset) + const char *arg, + int unset) { - state_p_value = atoi(arg); + struct apply_state *state = opt->value; + state->p_value = atoi(arg); p_value_known = 1; return 0; } @@ -4582,6 +4628,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) state->prefix_length = state->prefix ? strlen(state->prefix) : 0; state->apply = 1; state->line_termination = '\n'; + state->p_value = 1; state->p_context = UINT_MAX; git_apply_config(); @@ -4615,7 +4662,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 0, "include", &state, N_("path"), N_("apply changes matching the given path"), 0, option_parse_include }, - { OPTION_CALLBACK, 'p', NULL, NULL, N_("num"), + { OPTION_CALLBACK, 'p', NULL, &state, N_("num"), N_("remove leading slashes from traditional diff paths"), 0, option_parse_p }, OPT_BOOL(0, "no-add", &state.no_add, From b76184e41003c6bd4731d79474c72449f854b37c Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:10 +0200 Subject: [PATCH 33/50] builtin/apply: move 'p_value_known' global into 'struct apply_state' To libify the apply functionality the 'p_value_known' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 843fafd629..e1b68d4cb7 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -52,6 +52,7 @@ struct apply_state { const char *patch_input_file; int line_termination; int p_value; + int p_value_known; unsigned int p_context; /* Exclude and include path parameters */ @@ -61,8 +62,6 @@ struct apply_state { static int newfd = -1; -static int p_value_known; - static const char * const apply_usage[] = { N_("git apply [] [...]"), NULL @@ -875,14 +874,14 @@ static void parse_traditional_patch(struct apply_state *state, first += 4; /* skip "--- " */ second += 4; /* skip "+++ " */ - if (!p_value_known) { + if (!state->p_value_known) { int p, q; p = guess_p_value(state, first); q = guess_p_value(state, second); if (p < 0) p = q; if (0 <= p && p == q) { state->p_value = p; - p_value_known = 1; + state->p_value_known = 1; } } if (is_dev_null(first)) { @@ -4588,7 +4587,7 @@ static int option_parse_p(const struct option *opt, { struct apply_state *state = opt->value; state->p_value = atoi(arg); - p_value_known = 1; + state->p_value_known = 1; return 0; } From 36371e4c7ef87a2895b954284c29e8beff576084 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:11 +0200 Subject: [PATCH 34/50] builtin/apply: move 'root' global into 'struct apply_state' To libify the apply functionality the 'root' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 82 +++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index e1b68d4cb7..5dc1d899f8 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -51,6 +51,7 @@ struct apply_state { const char *fake_ancestor; const char *patch_input_file; int line_termination; + struct strbuf root; int p_value; int p_value_known; unsigned int p_context; @@ -83,8 +84,6 @@ static enum ws_ignore { } ws_ignore_action = ignore_ws_none; -static struct strbuf root = STRBUF_INIT; - static void parse_whitespace_option(const char *option) { if (!option) { @@ -474,7 +473,10 @@ static char *squash_slash(char *name) return name; } -static char *find_name_gnu(const char *line, const char *def, int p_value) +static char *find_name_gnu(struct apply_state *state, + const char *line, + const char *def, + int p_value) { struct strbuf name = STRBUF_INIT; char *cp; @@ -498,8 +500,8 @@ static char *find_name_gnu(const char *line, const char *def, int p_value) } strbuf_remove(&name, 0, cp - name.buf); - if (root.len) - strbuf_insert(&name, 0, root.buf, root.len); + if (state->root.len) + strbuf_insert(&name, 0, state->root.buf, state->root.len); return squash_slash(strbuf_detach(&name, NULL)); } @@ -662,8 +664,12 @@ static size_t diff_timestamp_len(const char *line, size_t len) return line + len - end; } -static char *find_name_common(const char *line, const char *def, - int p_value, const char *end, int terminate) +static char *find_name_common(struct apply_state *state, + const char *line, + const char *def, + int p_value, + const char *end, + int terminate) { int len; const char *start = NULL; @@ -701,32 +707,39 @@ static char *find_name_common(const char *line, const char *def, return squash_slash(xstrdup(def)); } - if (root.len) { - char *ret = xstrfmt("%s%.*s", root.buf, len, start); + if (state->root.len) { + char *ret = xstrfmt("%s%.*s", state->root.buf, len, start); return squash_slash(ret); } return squash_slash(xmemdupz(start, len)); } -static char *find_name(const char *line, char *def, int p_value, int terminate) +static char *find_name(struct apply_state *state, + const char *line, + char *def, + int p_value, + int terminate) { if (*line == '"') { - char *name = find_name_gnu(line, def, p_value); + char *name = find_name_gnu(state, line, def, p_value); if (name) return name; } - return find_name_common(line, def, p_value, NULL, terminate); + return find_name_common(state, line, def, p_value, NULL, terminate); } -static char *find_name_traditional(const char *line, char *def, int p_value) +static char *find_name_traditional(struct apply_state *state, + const char *line, + char *def, + int p_value) { size_t len; size_t date_len; if (*line == '"') { - char *name = find_name_gnu(line, def, p_value); + char *name = find_name_gnu(state, line, def, p_value); if (name) return name; } @@ -734,10 +747,10 @@ static char *find_name_traditional(const char *line, char *def, int p_value) len = strchrnul(line, '\n') - line; date_len = diff_timestamp_len(line, len); if (!date_len) - return find_name_common(line, def, p_value, NULL, TERM_TAB); + return find_name_common(state, line, def, p_value, NULL, TERM_TAB); len -= date_len; - return find_name_common(line, def, p_value, line + len, 0); + return find_name_common(state, line, def, p_value, line + len, 0); } static int count_slashes(const char *cp) @@ -762,7 +775,7 @@ static int guess_p_value(struct apply_state *state, const char *nameline) if (is_dev_null(nameline)) return -1; - name = find_name_traditional(nameline, NULL, 0); + name = find_name_traditional(state, nameline, NULL, 0); if (!name) return -1; cp = strchr(name, '/'); @@ -887,17 +900,17 @@ static void parse_traditional_patch(struct apply_state *state, if (is_dev_null(first)) { patch->is_new = 1; patch->is_delete = 0; - name = find_name_traditional(second, NULL, state->p_value); + name = find_name_traditional(state, second, NULL, state->p_value); patch->new_name = name; } else if (is_dev_null(second)) { patch->is_new = 0; patch->is_delete = 1; - name = find_name_traditional(first, NULL, state->p_value); + name = find_name_traditional(state, first, NULL, state->p_value); patch->old_name = name; } else { char *first_name; - first_name = find_name_traditional(first, NULL, state->p_value); - name = find_name_traditional(second, first_name, state->p_value); + first_name = find_name_traditional(state, first, NULL, state->p_value); + name = find_name_traditional(state, second, first_name, state->p_value); free(first_name); if (has_epoch_timestamp(first)) { patch->is_new = 1; @@ -942,7 +955,7 @@ static void gitdiff_verify_name(struct apply_state *state, int side) { if (!*name && !isnull) { - *name = find_name(line, NULL, state->p_value, TERM_TAB); + *name = find_name(state, line, NULL, state->p_value, TERM_TAB); return; } @@ -952,7 +965,7 @@ static void gitdiff_verify_name(struct apply_state *state, if (isnull) die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), *name, state_linenr); - another = find_name(line, NULL, state->p_value, TERM_TAB); + another = find_name(state, line, NULL, state->p_value, TERM_TAB); if (!another || memcmp(another, *name, len + 1)) die((side == DIFF_NEW_NAME) ? _("git apply: bad git-diff - inconsistent new filename on line %d") : @@ -1027,7 +1040,7 @@ static int gitdiff_copysrc(struct apply_state *state, { patch->is_copy = 1; free(patch->old_name); - patch->old_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + patch->old_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } @@ -1037,7 +1050,7 @@ static int gitdiff_copydst(struct apply_state *state, { patch->is_copy = 1; free(patch->new_name); - patch->new_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + patch->new_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } @@ -1047,7 +1060,7 @@ static int gitdiff_renamesrc(struct apply_state *state, { patch->is_rename = 1; free(patch->old_name); - patch->old_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + patch->old_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } @@ -1057,7 +1070,7 @@ static int gitdiff_renamedst(struct apply_state *state, { patch->is_rename = 1; free(patch->new_name); - patch->new_name = find_name(line, NULL, state->p_value ? state->p_value - 1 : 0, 0); + patch->new_name = find_name(state, line, NULL, state->p_value ? state->p_value - 1 : 0, 0); return 0; } @@ -1316,8 +1329,8 @@ static int parse_git_header(struct apply_state *state, * the default name from the header. */ patch->def_name = git_header_name(state, line, len); - if (patch->def_name && root.len) { - char *s = xstrfmt("%s%s", root.buf, patch->def_name); + if (patch->def_name && state->root.len) { + char *s = xstrfmt("%s%s", state->root.buf, patch->def_name); free(patch->def_name); patch->def_name = s; } @@ -4614,9 +4627,10 @@ static int option_parse_whitespace(const struct option *opt, static int option_parse_directory(const struct option *opt, const char *arg, int unset) { - strbuf_reset(&root); - strbuf_addstr(&root, arg); - strbuf_complete(&root, '/'); + struct apply_state *state = opt->value; + strbuf_reset(&state->root); + strbuf_addstr(&state->root, arg); + strbuf_complete(&state->root, '/'); return 0; } @@ -4629,6 +4643,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) state->line_termination = '\n'; state->p_value = 1; state->p_context = UINT_MAX; + strbuf_init(&state->root, 0); git_apply_config(); if (apply_default_whitespace) @@ -4640,6 +4655,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) static void clear_apply_state(struct apply_state *state) { string_list_clear(&state->limit_by_name, 0); + strbuf_release(&state->root); } int cmd_apply(int argc, const char **argv, const char *prefix) @@ -4717,7 +4733,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) OPT_BIT(0, "recount", &options, N_("do not trust the line counts in the hunk headers"), RECOUNT), - { OPTION_CALLBACK, 0, "directory", NULL, N_("root"), + { OPTION_CALLBACK, 0, "directory", &state, N_("root"), N_("prepend to all filenames"), 0, option_parse_directory }, OPT_END() From 5460cd0b1000078846e2850eeaba3573965c1faf Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:12 +0200 Subject: [PATCH 35/50] builtin/apply: move 'whitespace_error' global into 'struct apply_state' To libify the apply functionality the 'whitespace_error' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 5dc1d899f8..44717b2fdf 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -59,6 +59,9 @@ struct apply_state { /* Exclude and include path parameters */ struct string_list limit_by_name; int has_include; + + /* These control whitespace errors */ + int whitespace_error; }; static int newfd = -1; @@ -74,7 +77,6 @@ static enum ws_error_action { die_on_ws_error, correct_ws_error } ws_error_action = warn_on_ws_error; -static int whitespace_error; static int squelch_whitespace_errors = 5; static int applied_after_fixing_ws; @@ -1596,9 +1598,9 @@ static void record_ws_error(struct apply_state *state, if (!result) return; - whitespace_error++; + state->whitespace_error++; if (squelch_whitespace_errors && - squelch_whitespace_errors < whitespace_error) + squelch_whitespace_errors < state->whitespace_error) return; err = whitespace_error_string(result); @@ -2855,7 +2857,7 @@ static int apply_one_fragment(struct apply_state *state, start = newlines.len; if (first != '+' || - !whitespace_error || + !state->whitespace_error || ws_error_action != correct_ws_error) { strbuf_add(&newlines, patch + 1, plen); } @@ -4528,7 +4530,7 @@ static int apply_patch(struct apply_state *state, if (!list && !skipped_patch) die(_("unrecognized input")); - if (whitespace_error && (ws_error_action == die_on_ws_error)) + if (state->whitespace_error && (ws_error_action == die_on_ws_error)) state->apply = 0; state->update_index = state->check_index && state->apply; @@ -4791,11 +4793,11 @@ int cmd_apply(int argc, const char **argv, const char *prefix) set_default_whitespace_mode(&state, whitespace_option); if (read_stdin) errs |= apply_patch(&state, 0, "", options); - if (whitespace_error) { + if (state.whitespace_error) { if (squelch_whitespace_errors && - squelch_whitespace_errors < whitespace_error) { + squelch_whitespace_errors < state.whitespace_error) { int squelched = - whitespace_error - squelch_whitespace_errors; + state.whitespace_error - squelch_whitespace_errors; warning(Q_("squelched %d whitespace error", "squelched %d whitespace errors", squelched), @@ -4804,18 +4806,18 @@ int cmd_apply(int argc, const char **argv, const char *prefix) if (ws_error_action == die_on_ws_error) die(Q_("%d line adds whitespace errors.", "%d lines add whitespace errors.", - whitespace_error), - whitespace_error); + state.whitespace_error), + state.whitespace_error); if (applied_after_fixing_ws && state.apply) warning("%d line%s applied after" " fixing whitespace errors.", applied_after_fixing_ws, applied_after_fixing_ws == 1 ? "" : "s"); - else if (whitespace_error) + else if (state.whitespace_error) warning(Q_("%d line adds whitespace errors.", "%d lines add whitespace errors.", - whitespace_error), - whitespace_error); + state.whitespace_error), + state.whitespace_error); } if (state.update_index) { From 161fcbe9884466e95cf5b1c7cd22f64a16a24045 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:13 +0200 Subject: [PATCH 36/50] builtin/apply: move 'whitespace_option' into 'struct apply_state' This will enable further refactoring, and it is more coherent and simpler if all the option_parse_*() functions are passed a 'struct apply_state' instance in opt->value. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 44717b2fdf..78205f8053 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -61,6 +61,7 @@ struct apply_state { int has_include; /* These control whitespace errors */ + const char *whitespace_option; int whitespace_error; }; @@ -4619,9 +4620,9 @@ static int option_parse_space_change(const struct option *opt, static int option_parse_whitespace(const struct option *opt, const char *arg, int unset) { - const char **whitespace_option = opt->value; + struct apply_state *state = opt->value; - *whitespace_option = arg; + state->whitespace_option = arg; parse_whitespace_option(arg); return 0; } @@ -4670,8 +4671,6 @@ int cmd_apply(int argc, const char **argv, const char *prefix) int read_stdin = 1; struct apply_state state; - const char *whitespace_option = NULL; - struct option builtin_apply_options[] = { { OPTION_CALLBACK, 0, "exclude", &state, N_("path"), N_("don't apply changes matching the given path"), @@ -4711,7 +4710,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) N_("paths are separated with NUL character"), '\0'), OPT_INTEGER('C', NULL, &state.p_context, N_("ensure at least lines of context match")), - { OPTION_CALLBACK, 0, "whitespace", &whitespace_option, N_("action"), + { OPTION_CALLBACK, 0, "whitespace", &state, N_("action"), N_("detect new or modified lines that have whitespace errors"), 0, option_parse_whitespace }, { OPTION_CALLBACK, 0, "ignore-space-change", NULL, NULL, @@ -4786,11 +4785,11 @@ int cmd_apply(int argc, const char **argv, const char *prefix) if (fd < 0) die_errno(_("can't open patch '%s'"), arg); read_stdin = 0; - set_default_whitespace_mode(&state, whitespace_option); + set_default_whitespace_mode(&state, state.whitespace_option); errs |= apply_patch(&state, fd, arg, options); close(fd); } - set_default_whitespace_mode(&state, whitespace_option); + set_default_whitespace_mode(&state, state.whitespace_option); if (read_stdin) errs |= apply_patch(&state, 0, "", options); if (state.whitespace_error) { From 8bcba3d0d60d859c1494cdb59301cf84befcdfaa Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:14 +0200 Subject: [PATCH 37/50] builtin/apply: remove whitespace_option arg from set_default_whitespace_mode() A previous change has move the whitespace_option variable from cmd_apply into 'struct apply_state', so that we can now avoid passing it separately to set_default_whitespace_mode(). Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 78205f8053..523ed74a6c 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -132,10 +132,9 @@ static void parse_ignorewhitespace_option(const char *option) die(_("unrecognized whitespace ignore option '%s'"), option); } -static void set_default_whitespace_mode(struct apply_state *state, - const char *whitespace_option) +static void set_default_whitespace_mode(struct apply_state *state) { - if (!whitespace_option && !apply_default_whitespace) + if (!state->whitespace_option && !apply_default_whitespace) ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); } @@ -4785,11 +4784,11 @@ int cmd_apply(int argc, const char **argv, const char *prefix) if (fd < 0) die_errno(_("can't open patch '%s'"), arg); read_stdin = 0; - set_default_whitespace_mode(&state, state.whitespace_option); + set_default_whitespace_mode(&state); errs |= apply_patch(&state, fd, arg, options); close(fd); } - set_default_whitespace_mode(&state, state.whitespace_option); + set_default_whitespace_mode(&state); if (read_stdin) errs |= apply_patch(&state, 0, "", options); if (state.whitespace_error) { From 70e1d53df17bc8fa81f3583a50f76753a8bac154 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:15 +0200 Subject: [PATCH 38/50] builtin/apply: move 'squelch_whitespace_errors' into 'struct apply_state' To libify the apply functionality the 'squelch_whitespace_errors' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 523ed74a6c..619b8fb125 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -63,6 +63,7 @@ struct apply_state { /* These control whitespace errors */ const char *whitespace_option; int whitespace_error; + int squelch_whitespace_errors; }; static int newfd = -1; @@ -78,7 +79,6 @@ static enum ws_error_action { die_on_ws_error, correct_ws_error } ws_error_action = warn_on_ws_error; -static int squelch_whitespace_errors = 5; static int applied_after_fixing_ws; static enum ws_ignore { @@ -87,7 +87,7 @@ static enum ws_ignore { } ws_ignore_action = ignore_ws_none; -static void parse_whitespace_option(const char *option) +static void parse_whitespace_option(struct apply_state *state, const char *option) { if (!option) { ws_error_action = warn_on_ws_error; @@ -107,7 +107,7 @@ static void parse_whitespace_option(const char *option) } if (!strcmp(option, "error-all")) { ws_error_action = die_on_ws_error; - squelch_whitespace_errors = 0; + state->squelch_whitespace_errors = 0; return; } if (!strcmp(option, "strip") || !strcmp(option, "fix")) { @@ -1599,8 +1599,8 @@ static void record_ws_error(struct apply_state *state, return; state->whitespace_error++; - if (squelch_whitespace_errors && - squelch_whitespace_errors < state->whitespace_error) + if (state->squelch_whitespace_errors && + state->squelch_whitespace_errors < state->whitespace_error) return; err = whitespace_error_string(result); @@ -4620,9 +4620,8 @@ static int option_parse_whitespace(const struct option *opt, const char *arg, int unset) { struct apply_state *state = opt->value; - state->whitespace_option = arg; - parse_whitespace_option(arg); + parse_whitespace_option(state, arg); return 0; } @@ -4645,11 +4644,12 @@ static void init_apply_state(struct apply_state *state, const char *prefix) state->line_termination = '\n'; state->p_value = 1; state->p_context = UINT_MAX; + state->squelch_whitespace_errors = 5; strbuf_init(&state->root, 0); git_apply_config(); if (apply_default_whitespace) - parse_whitespace_option(apply_default_whitespace); + parse_whitespace_option(state, apply_default_whitespace); if (apply_default_ignorewhitespace) parse_ignorewhitespace_option(apply_default_ignorewhitespace); } @@ -4792,10 +4792,10 @@ int cmd_apply(int argc, const char **argv, const char *prefix) if (read_stdin) errs |= apply_patch(&state, 0, "", options); if (state.whitespace_error) { - if (squelch_whitespace_errors && - squelch_whitespace_errors < state.whitespace_error) { + if (state.squelch_whitespace_errors && + state.squelch_whitespace_errors < state.whitespace_error) { int squelched = - state.whitespace_error - squelch_whitespace_errors; + state.whitespace_error - state.squelch_whitespace_errors; warning(Q_("squelched %d whitespace error", "squelched %d whitespace errors", squelched), From 7243f5f3507abe3d083ec18e44bc7cb464fa06f4 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:16 +0200 Subject: [PATCH 39/50] builtin/apply: move 'applied_after_fixing_ws' into 'struct apply_state' To libify the apply functionality the 'applied_after_fixing_ws' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 619b8fb125..91b6283a97 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -64,6 +64,7 @@ struct apply_state { const char *whitespace_option; int whitespace_error; int squelch_whitespace_errors; + int applied_after_fixing_ws; }; static int newfd = -1; @@ -79,7 +80,6 @@ static enum ws_error_action { die_on_ws_error, correct_ws_error } ws_error_action = warn_on_ws_error; -static int applied_after_fixing_ws; static enum ws_ignore { ignore_ws_none, @@ -2862,7 +2862,7 @@ static int apply_one_fragment(struct apply_state *state, strbuf_add(&newlines, patch + 1, plen); } else { - ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &applied_after_fixing_ws); + ws_fix_copy(&newlines, patch + 1, plen, ws_rule, &state->applied_after_fixing_ws); } add_line_info(&postimage, newlines.buf + start, newlines.len - start, (first == '+' ? 0 : LINE_COMMON)); @@ -4806,11 +4806,11 @@ int cmd_apply(int argc, const char **argv, const char *prefix) "%d lines add whitespace errors.", state.whitespace_error), state.whitespace_error); - if (applied_after_fixing_ws && state.apply) + if (state.applied_after_fixing_ws && state.apply) warning("%d line%s applied after" " fixing whitespace errors.", - applied_after_fixing_ws, - applied_after_fixing_ws == 1 ? "" : "s"); + state.applied_after_fixing_ws, + state.applied_after_fixing_ws == 1 ? "" : "s"); else if (state.whitespace_error) warning(Q_("%d line adds whitespace errors.", "%d lines add whitespace errors.", From e9c6b279b8226b2ab93a6a550a654640ccc5b256 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:17 +0200 Subject: [PATCH 40/50] builtin/apply: move 'ws_error_action' into 'struct apply_state' To libify the apply functionality the 'ws_error_action' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 61 ++++++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 91b6283a97..61d809a99e 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -21,6 +21,13 @@ #include "ll-merge.h" #include "rerere.h" +enum ws_error_action { + nowarn_ws_error, + warn_on_ws_error, + die_on_ws_error, + correct_ws_error +}; + struct apply_state { const char *prefix; int prefix_length; @@ -61,6 +68,7 @@ struct apply_state { int has_include; /* These control whitespace errors */ + enum ws_error_action ws_error_action; const char *whitespace_option; int whitespace_error; int squelch_whitespace_errors; @@ -74,12 +82,6 @@ static const char * const apply_usage[] = { NULL }; -static enum ws_error_action { - nowarn_ws_error, - warn_on_ws_error, - die_on_ws_error, - correct_ws_error -} ws_error_action = warn_on_ws_error; static enum ws_ignore { ignore_ws_none, @@ -90,28 +92,28 @@ static enum ws_ignore { static void parse_whitespace_option(struct apply_state *state, const char *option) { if (!option) { - ws_error_action = warn_on_ws_error; + state->ws_error_action = warn_on_ws_error; return; } if (!strcmp(option, "warn")) { - ws_error_action = warn_on_ws_error; + state->ws_error_action = warn_on_ws_error; return; } if (!strcmp(option, "nowarn")) { - ws_error_action = nowarn_ws_error; + state->ws_error_action = nowarn_ws_error; return; } if (!strcmp(option, "error")) { - ws_error_action = die_on_ws_error; + state->ws_error_action = die_on_ws_error; return; } if (!strcmp(option, "error-all")) { - ws_error_action = die_on_ws_error; + state->ws_error_action = die_on_ws_error; state->squelch_whitespace_errors = 0; return; } if (!strcmp(option, "strip") || !strcmp(option, "fix")) { - ws_error_action = correct_ws_error; + state->ws_error_action = correct_ws_error; return; } die(_("unrecognized whitespace option '%s'"), option); @@ -135,7 +137,7 @@ static void parse_ignorewhitespace_option(const char *option) static void set_default_whitespace_mode(struct apply_state *state) { if (!state->whitespace_option && !apply_default_whitespace) - ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); + state->ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); } /* @@ -1670,12 +1672,12 @@ static int parse_fragment(struct apply_state *state, leading++; trailing++; if (!state->apply_in_reverse && - ws_error_action == correct_ws_error) + state->ws_error_action == correct_ws_error) check_whitespace(state, line, len, patch->ws_rule); break; case '-': if (state->apply_in_reverse && - ws_error_action != nowarn_ws_error) + state->ws_error_action != nowarn_ws_error) check_whitespace(state, line, len, patch->ws_rule); deleted++; oldlines--; @@ -1683,7 +1685,7 @@ static int parse_fragment(struct apply_state *state, break; case '+': if (!state->apply_in_reverse && - ws_error_action != nowarn_ws_error) + state->ws_error_action != nowarn_ws_error) check_whitespace(state, line, len, patch->ws_rule); added++; newlines--; @@ -2396,7 +2398,8 @@ static int line_by_line_fuzzy_match(struct image *img, return 1; } -static int match_fragment(struct image *img, +static int match_fragment(struct apply_state *state, + struct image *img, struct image *preimage, struct image *postimage, unsigned long try, @@ -2417,7 +2420,7 @@ static int match_fragment(struct image *img, preimage_limit = preimage->nr; if (match_end && (preimage->nr + try_lno != img->nr)) return 0; - } else if (ws_error_action == correct_ws_error && + } else if (state->ws_error_action == correct_ws_error && (ws_rule & WS_BLANK_AT_EOF)) { /* * This hunk extends beyond the end of img, and we are @@ -2489,7 +2492,7 @@ static int match_fragment(struct image *img, return line_by_line_fuzzy_match(img, preimage, postimage, try, try_lno, preimage_limit); - if (ws_error_action != correct_ws_error) + if (state->ws_error_action != correct_ws_error) return 0; /* @@ -2601,7 +2604,8 @@ static int match_fragment(struct image *img, return 0; } -static int find_pos(struct image *img, +static int find_pos(struct apply_state *state, + struct image *img, struct image *preimage, struct image *postimage, int line, @@ -2645,7 +2649,7 @@ static int find_pos(struct image *img, try_lno = line; for (i = 0; ; i++) { - if (match_fragment(img, preimage, postimage, + if (match_fragment(state, img, preimage, postimage, try, try_lno, ws_rule, match_beginning, match_end)) return try_lno; @@ -2858,7 +2862,7 @@ static int apply_one_fragment(struct apply_state *state, start = newlines.len; if (first != '+' || !state->whitespace_error || - ws_error_action != correct_ws_error) { + state->ws_error_action != correct_ws_error) { strbuf_add(&newlines, patch + 1, plen); } else { @@ -2936,7 +2940,7 @@ static int apply_one_fragment(struct apply_state *state, for (;;) { - applied_pos = find_pos(img, &preimage, &postimage, pos, + applied_pos = find_pos(state, img, &preimage, &postimage, pos, ws_rule, match_beginning, match_end); if (applied_pos >= 0) @@ -2972,10 +2976,10 @@ static int apply_one_fragment(struct apply_state *state, if (new_blank_lines_at_end && preimage.nr + applied_pos >= img->nr && (ws_rule & WS_BLANK_AT_EOF) && - ws_error_action != nowarn_ws_error) { + state->ws_error_action != nowarn_ws_error) { record_ws_error(state, WS_BLANK_AT_EOF, "+", 1, found_new_blank_lines_at_end); - if (ws_error_action == correct_ws_error) { + if (state->ws_error_action == correct_ws_error) { while (new_blank_lines_at_end--) remove_last_line(&postimage); } @@ -2986,7 +2990,7 @@ static int apply_one_fragment(struct apply_state *state, * apply_patch->check_patch_list->check_patch-> * apply_data->apply_fragments->apply_one_fragment */ - if (ws_error_action == die_on_ws_error) + if (state->ws_error_action == die_on_ws_error) state->apply = 0; } @@ -4530,7 +4534,7 @@ static int apply_patch(struct apply_state *state, if (!list && !skipped_patch) die(_("unrecognized input")); - if (state->whitespace_error && (ws_error_action == die_on_ws_error)) + if (state->whitespace_error && (state->ws_error_action == die_on_ws_error)) state->apply = 0; state->update_index = state->check_index && state->apply; @@ -4645,6 +4649,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) state->p_value = 1; state->p_context = UINT_MAX; state->squelch_whitespace_errors = 5; + state->ws_error_action = warn_on_ws_error; strbuf_init(&state->root, 0); git_apply_config(); @@ -4801,7 +4806,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) squelched), squelched); } - if (ws_error_action == die_on_ws_error) + if (state.ws_error_action == die_on_ws_error) die(Q_("%d line adds whitespace errors.", "%d lines add whitespace errors.", state.whitespace_error), From 10a9ddba2c3478c8080acc1b2c83d75d09ee2492 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:18 +0200 Subject: [PATCH 41/50] builtin/apply: move 'ws_ignore_action' into 'struct apply_state' To libify the apply functionality the 'ws_ignore_action' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 61d809a99e..e5bc9cc1cc 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -28,6 +28,12 @@ enum ws_error_action { correct_ws_error }; + +enum ws_ignore { + ignore_ws_none, + ignore_ws_change +}; + struct apply_state { const char *prefix; int prefix_length; @@ -69,6 +75,7 @@ struct apply_state { /* These control whitespace errors */ enum ws_error_action ws_error_action; + enum ws_ignore ws_ignore_action; const char *whitespace_option; int whitespace_error; int squelch_whitespace_errors; @@ -82,13 +89,6 @@ static const char * const apply_usage[] = { NULL }; - -static enum ws_ignore { - ignore_ws_none, - ignore_ws_change -} ws_ignore_action = ignore_ws_none; - - static void parse_whitespace_option(struct apply_state *state, const char *option) { if (!option) { @@ -119,16 +119,17 @@ static void parse_whitespace_option(struct apply_state *state, const char *optio die(_("unrecognized whitespace option '%s'"), option); } -static void parse_ignorewhitespace_option(const char *option) +static void parse_ignorewhitespace_option(struct apply_state *state, + const char *option) { if (!option || !strcmp(option, "no") || !strcmp(option, "false") || !strcmp(option, "never") || !strcmp(option, "none")) { - ws_ignore_action = ignore_ws_none; + state->ws_ignore_action = ignore_ws_none; return; } if (!strcmp(option, "change")) { - ws_ignore_action = ignore_ws_change; + state->ws_ignore_action = ignore_ws_change; return; } die(_("unrecognized whitespace ignore option '%s'"), option); @@ -2488,7 +2489,7 @@ static int match_fragment(struct apply_state *state, * fuzzy matching. We collect all the line length information because * we need it to adjust whitespace if we match. */ - if (ws_ignore_action == ignore_ws_change) + if (state->ws_ignore_action == ignore_ws_change) return line_by_line_fuzzy_match(img, preimage, postimage, try, try_lno, preimage_limit); @@ -4611,12 +4612,13 @@ static int option_parse_p(const struct option *opt, } static int option_parse_space_change(const struct option *opt, - const char *arg, int unset) + const char *arg, int unset) { + struct apply_state *state = opt->value; if (unset) - ws_ignore_action = ignore_ws_none; + state->ws_ignore_action = ignore_ws_none; else - ws_ignore_action = ignore_ws_change; + state->ws_ignore_action = ignore_ws_change; return 0; } @@ -4650,13 +4652,14 @@ static void init_apply_state(struct apply_state *state, const char *prefix) state->p_context = UINT_MAX; state->squelch_whitespace_errors = 5; state->ws_error_action = warn_on_ws_error; + state->ws_ignore_action = ignore_ws_none; strbuf_init(&state->root, 0); git_apply_config(); if (apply_default_whitespace) parse_whitespace_option(state, apply_default_whitespace); if (apply_default_ignorewhitespace) - parse_ignorewhitespace_option(apply_default_ignorewhitespace); + parse_ignorewhitespace_option(state, apply_default_ignorewhitespace); } static void clear_apply_state(struct apply_state *state) @@ -4717,10 +4720,10 @@ int cmd_apply(int argc, const char **argv, const char *prefix) { OPTION_CALLBACK, 0, "whitespace", &state, N_("action"), N_("detect new or modified lines that have whitespace errors"), 0, option_parse_whitespace }, - { OPTION_CALLBACK, 0, "ignore-space-change", NULL, NULL, + { OPTION_CALLBACK, 0, "ignore-space-change", &state, NULL, N_("ignore changes in whitespace when finding context"), PARSE_OPT_NOARG, option_parse_space_change }, - { OPTION_CALLBACK, 0, "ignore-whitespace", NULL, NULL, + { OPTION_CALLBACK, 0, "ignore-whitespace", &state, NULL, N_("ignore changes in whitespace when finding context"), PARSE_OPT_NOARG, option_parse_space_change }, OPT_BOOL('R', "reverse", &state.apply_in_reverse, From 1ffec303ab043c392e480d37df2b34e40f3d4bd0 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:19 +0200 Subject: [PATCH 42/50] builtin/apply: move 'max_change' and 'max_len' into 'struct apply_state' To libify the apply functionality the 'max_change' and 'max_len' variables should not be static and global to the file. Let's move them into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 49 +++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index e5bc9cc1cc..9e7d1810e5 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -73,6 +73,14 @@ struct apply_state { struct string_list limit_by_name; int has_include; + /* + * For "diff-stat" like behaviour, we keep track of the biggest change + * we've seen, and the longest filename. That allows us to do simple + * scaling. + */ + int max_change; + int max_len; + /* These control whitespace errors */ enum ws_error_action ws_error_action; enum ws_ignore ws_ignore_action; @@ -141,13 +149,6 @@ static void set_default_whitespace_mode(struct apply_state *state) state->ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); } -/* - * For "diff-stat" like behaviour, we keep track of the biggest change - * we've seen, and the longest filename. That allows us to do simple - * scaling. - */ -static int max_change, max_len; - /* * Various "current state", notably line numbers and what * file (and how) we're patching right now.. The "is_xxxx" @@ -2172,7 +2173,7 @@ static const char pluses[] = static const char minuses[]= "----------------------------------------------------------------------"; -static void show_stats(struct patch *patch) +static void show_stats(struct apply_state *state, struct patch *patch) { struct strbuf qname = STRBUF_INIT; char *cp = patch->new_name ? patch->new_name : patch->old_name; @@ -2183,7 +2184,7 @@ static void show_stats(struct patch *patch) /* * "scale" the filename */ - max = max_len; + max = state->max_len; if (max > 50) max = 50; @@ -2206,13 +2207,13 @@ static void show_stats(struct patch *patch) /* * scale the add/delete */ - max = max + max_change > 70 ? 70 - max : max_change; + max = max + state->max_change > 70 ? 70 - max : state->max_change; add = patch->lines_added; del = patch->lines_deleted; - if (max_change > 0) { - int total = ((add + del) * max + max_change / 2) / max_change; - add = (add * max + max_change / 2) / max_change; + if (state->max_change > 0) { + int total = ((add + del) * max + state->max_change / 2) / state->max_change; + add = (add * max + state->max_change / 2) / state->max_change; del = total - add; } printf("%5d %.*s%.*s\n", patch->lines_added + patch->lines_deleted, @@ -4038,7 +4039,7 @@ static void build_fake_ancestor(struct patch *list, const char *filename) discard_index(&result); } -static void stat_patch_list(struct patch *patch) +static void stat_patch_list(struct apply_state *state, struct patch *patch) { int files, adds, dels; @@ -4046,7 +4047,7 @@ static void stat_patch_list(struct patch *patch) files++; adds += patch->lines_added; dels += patch->lines_deleted; - show_stats(patch); + show_stats(state, patch); } print_stat_summary(stdout, files, adds, dels); @@ -4144,25 +4145,25 @@ static void summary_patch_list(struct patch *patch) } } -static void patch_stats(struct patch *patch) +static void patch_stats(struct apply_state *state, struct patch *patch) { int lines = patch->lines_added + patch->lines_deleted; - if (lines > max_change) - max_change = lines; + if (lines > state->max_change) + state->max_change = lines; if (patch->old_name) { int len = quote_c_style(patch->old_name, NULL, NULL, 0); if (!len) len = strlen(patch->old_name); - if (len > max_len) - max_len = len; + if (len > state->max_len) + state->max_len = len; } if (patch->new_name) { int len = quote_c_style(patch->new_name, NULL, NULL, 0); if (!len) len = strlen(patch->new_name); - if (len > max_len) - max_len = len; + if (len > state->max_len) + state->max_len = len; } } @@ -4519,7 +4520,7 @@ static int apply_patch(struct apply_state *state, if (state->apply_in_reverse) reverse_patches(patch); if (use_patch(state, patch)) { - patch_stats(patch); + patch_stats(state, patch); *listp = patch; listp = &patch->next; } @@ -4563,7 +4564,7 @@ static int apply_patch(struct apply_state *state, build_fake_ancestor(list, state->fake_ancestor); if (state->diffstat) - stat_patch_list(list); + stat_patch_list(state, list); if (state->numstat) numstat_patch_list(state, list); From d7263d097c4510d864f8c9ff808bc9b377f0bf8f Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:20 +0200 Subject: [PATCH 43/50] builtin/apply: move 'state_linenr' global into 'struct apply_state' To libify the apply functionality the 'state_linenr' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 71 +++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 9e7d1810e5..dd56a8e93a 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -73,6 +73,9 @@ struct apply_state { struct string_list limit_by_name; int has_include; + /* Various "current state" */ + int linenr; /* current line number */ + /* * For "diff-stat" like behaviour, we keep track of the biggest change * we've seen, and the longest filename. That allows us to do simple @@ -149,13 +152,6 @@ static void set_default_whitespace_mode(struct apply_state *state) state->ws_error_action = (state->apply ? warn_on_ws_error : nowarn_ws_error); } -/* - * Various "current state", notably line numbers and what - * file (and how) we're patching right now.. The "is_xxxx" - * things are flags, where -1 means "don't know yet". - */ -static int state_linenr = 1; - /* * This represents one "hunk" from a patch, starting with * "@@ -oldpos,oldlines +newpos,newlines @@" marker. The @@ -932,7 +928,7 @@ static void parse_traditional_patch(struct apply_state *state, } } if (!name) - die(_("unable to find filename in patch at line %d"), state_linenr); + die(_("unable to find filename in patch at line %d"), state->linenr); } static int gitdiff_hdrend(struct apply_state *state, @@ -970,17 +966,17 @@ static void gitdiff_verify_name(struct apply_state *state, char *another; if (isnull) die(_("git apply: bad git-diff - expected /dev/null, got %s on line %d"), - *name, state_linenr); + *name, state->linenr); another = find_name(state, line, NULL, state->p_value, TERM_TAB); if (!another || memcmp(another, *name, len + 1)) die((side == DIFF_NEW_NAME) ? _("git apply: bad git-diff - inconsistent new filename on line %d") : - _("git apply: bad git-diff - inconsistent old filename on line %d"), state_linenr); + _("git apply: bad git-diff - inconsistent old filename on line %d"), state->linenr); free(another); } else { /* expect "/dev/null" */ if (memcmp("/dev/null", line, 9) || line[9] != '\n') - die(_("git apply: bad git-diff - expected /dev/null on line %d"), state_linenr); + die(_("git apply: bad git-diff - expected /dev/null on line %d"), state->linenr); } } @@ -1343,8 +1339,8 @@ static int parse_git_header(struct apply_state *state, line += len; size -= len; - state_linenr++; - for (offset = len ; size > 0 ; offset += len, size -= len, line += len, state_linenr++) { + state->linenr++; + for (offset = len ; size > 0 ; offset += len, size -= len, line += len, state->linenr++) { static const struct opentry { const char *str; int (*fn)(struct apply_state *, const char *, struct patch *); @@ -1515,7 +1511,7 @@ static int find_header(struct apply_state *state, patch->is_new = patch->is_delete = -1; patch->old_mode = patch->new_mode = 0; patch->old_name = patch->new_name = NULL; - for (offset = 0; size > 0; offset += len, size -= len, line += len, state_linenr++) { + for (offset = 0; size > 0; offset += len, size -= len, line += len, state->linenr++) { unsigned long nextlen; len = linelen(line, size); @@ -1536,7 +1532,7 @@ static int find_header(struct apply_state *state, if (parse_fragment_header(line, len, &dummy) < 0) continue; die(_("patch fragment without header at line %d: %.*s"), - state_linenr, (int)len-1, line); + state->linenr, (int)len-1, line); } if (size < len + 6) @@ -1557,13 +1553,13 @@ static int find_header(struct apply_state *state, "git diff header lacks filename information when removing " "%d leading pathname components (line %d)", state->p_value), - state->p_value, state_linenr); + state->p_value, state->linenr); patch->old_name = xstrdup(patch->def_name); patch->new_name = xstrdup(patch->def_name); } if (!patch->is_delete && !patch->new_name) die("git diff header lacks filename information " - "(line %d)", state_linenr); + "(line %d)", state->linenr); patch->is_toplevel_relative = 1; *hdrsize = git_hdr_len; return offset; @@ -1585,7 +1581,7 @@ static int find_header(struct apply_state *state, /* Ok, we'll consider it a patch */ parse_traditional_patch(state, line, line+len, patch); *hdrsize = len + nextlen; - state_linenr += 2; + state->linenr += 2; return offset; } return -1; @@ -1620,7 +1616,7 @@ static void check_whitespace(struct apply_state *state, { unsigned result = ws_check(line + 1, len - 1, ws_rule); - record_ws_error(state, result, line + 1, len - 2, state_linenr); + record_ws_error(state, result, line + 1, len - 2, state->linenr); } /* @@ -1653,11 +1649,11 @@ static int parse_fragment(struct apply_state *state, /* Parse the thing.. */ line += len; size -= len; - state_linenr++; + state->linenr++; added = deleted = 0; for (offset = len; 0 < size; - offset += len, size -= len, line += len, state_linenr++) { + offset += len, size -= len, line += len, state->linenr++) { if (!oldlines && !newlines) break; len = linelen(line, size); @@ -1756,10 +1752,10 @@ static int parse_single_patch(struct apply_state *state, int len; fragment = xcalloc(1, sizeof(*fragment)); - fragment->linenr = state_linenr; + fragment->linenr = state->linenr; len = parse_fragment(state, line, size, patch, fragment); if (len <= 0) - die(_("corrupt patch at line %d"), state_linenr); + die(_("corrupt patch at line %d"), state->linenr); fragment->patch = line; fragment->size = len; oldlines += fragment->oldlines; @@ -1845,7 +1841,8 @@ static char *inflate_it(const void *data, unsigned long size, * points at an allocated memory that the caller must free, so * it is marked as "->free_patch = 1". */ -static struct fragment *parse_binary_hunk(char **buf_p, +static struct fragment *parse_binary_hunk(struct apply_state *state, + char **buf_p, unsigned long *sz_p, int *status_p, int *used_p) @@ -1887,13 +1884,13 @@ static struct fragment *parse_binary_hunk(char **buf_p, else return NULL; - state_linenr++; + state->linenr++; buffer += llen; while (1) { int byte_length, max_byte_length, newsize; llen = linelen(buffer, size); used += llen; - state_linenr++; + state->linenr++; if (llen == 1) { /* consume the blank line */ buffer++; @@ -1947,7 +1944,7 @@ static struct fragment *parse_binary_hunk(char **buf_p, free(data); *status_p = -1; error(_("corrupt binary patch at line %d: %.*s"), - state_linenr-1, llen-1, buffer); + state->linenr-1, llen-1, buffer); return NULL; } @@ -1956,7 +1953,10 @@ static struct fragment *parse_binary_hunk(char **buf_p, * -1 in case of error, * the length of the parsed binary patch otherwise */ -static int parse_binary(char *buffer, unsigned long size, struct patch *patch) +static int parse_binary(struct apply_state *state, + char *buffer, + unsigned long size, + struct patch *patch) { /* * We have read "GIT binary patch\n"; what follows is a line @@ -1977,15 +1977,15 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch) int status; int used, used_1; - forward = parse_binary_hunk(&buffer, &size, &status, &used); + forward = parse_binary_hunk(state, &buffer, &size, &status, &used); if (!forward && !status) /* there has to be one hunk (forward hunk) */ - return error(_("unrecognized binary patch at line %d"), state_linenr-1); + return error(_("unrecognized binary patch at line %d"), state->linenr-1); if (status) /* otherwise we already gave an error message */ return status; - reverse = parse_binary_hunk(&buffer, &size, &status, &used_1); + reverse = parse_binary_hunk(state, &buffer, &size, &status, &used_1); if (reverse) used += used_1; else if (status) { @@ -2100,8 +2100,8 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si if (llen == sizeof(git_binary) - 1 && !memcmp(git_binary, buffer + hd, llen)) { int used; - state_linenr++; - used = parse_binary(buffer + hd + llen, + state->linenr++; + used = parse_binary(state, buffer + hd + llen, size - hd - llen, patch); if (used < 0) return -1; @@ -2121,7 +2121,7 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si int len = strlen(binhdr[i]); if (len < size - hd && !memcmp(binhdr[i], buffer + hd, len)) { - state_linenr++; + state->linenr++; patch->is_binary = 1; patchsize = llen; break; @@ -2135,7 +2135,7 @@ static int parse_chunk(struct apply_state *state, char *buffer, unsigned long si */ if ((state->apply || state->check) && (!patch->is_binary && !metadata_changes(patch))) - die(_("patch with only garbage at line %d"), state_linenr); + die(_("patch with only garbage at line %d"), state->linenr); } return offset + hdrsize + patchsize; @@ -4654,6 +4654,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) state->squelch_whitespace_errors = 5; state->ws_error_action = warn_on_ws_error; state->ws_ignore_action = ignore_ws_none; + state->linenr = 1; strbuf_init(&state->root, 0); git_apply_config(); From 71dac5cef57daacb35a56b4b54e1a30bc6417968 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:21 +0200 Subject: [PATCH 44/50] builtin/apply: move 'fn_table' global into 'struct apply_state' To libify the apply functionality the 'fn_table' variable should not be static and global to the file. Let's move it into 'struct apply_state'. As fn_table is cleared at the end of apply_patch(), it is not necessary to clear it in clear_apply_state(). Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index dd56a8e93a..47622bee69 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -84,6 +84,12 @@ struct apply_state { int max_change; int max_len; + /* + * Records filenames that have been touched, in order to handle + * the case where more than one patches touch the same file. + */ + struct string_list fn_table; + /* These control whitespace errors */ enum ws_error_action ws_error_action; enum ws_ignore ws_ignore_action; @@ -271,13 +277,6 @@ struct image { struct line *line; }; -/* - * Records filenames that have been touched, in order to handle - * the case where more than one patches touch the same file. - */ - -static struct string_list fn_table; - static uint32_t hash_line(const char *cp, size_t len) { size_t i; @@ -3207,14 +3206,14 @@ static int read_file_or_gitlink(const struct cache_entry *ce, struct strbuf *buf return read_blob_object(buf, ce->sha1, ce->ce_mode); } -static struct patch *in_fn_table(const char *name) +static struct patch *in_fn_table(struct apply_state *state, const char *name) { struct string_list_item *item; if (name == NULL) return NULL; - item = string_list_lookup(&fn_table, name); + item = string_list_lookup(&state->fn_table, name); if (item != NULL) return (struct patch *)item->util; @@ -3246,7 +3245,7 @@ static int was_deleted(struct patch *patch) return patch == PATH_WAS_DELETED; } -static void add_to_fn_table(struct patch *patch) +static void add_to_fn_table(struct apply_state *state, struct patch *patch) { struct string_list_item *item; @@ -3256,7 +3255,7 @@ static void add_to_fn_table(struct patch *patch) * file creations and copies */ if (patch->new_name != NULL) { - item = string_list_insert(&fn_table, patch->new_name); + item = string_list_insert(&state->fn_table, patch->new_name); item->util = patch; } @@ -3265,12 +3264,12 @@ static void add_to_fn_table(struct patch *patch) * later chunks shouldn't patch old names */ if ((patch->new_name == NULL) || (patch->is_rename)) { - item = string_list_insert(&fn_table, patch->old_name); + item = string_list_insert(&state->fn_table, patch->old_name); item->util = PATH_WAS_DELETED; } } -static void prepare_fn_table(struct patch *patch) +static void prepare_fn_table(struct apply_state *state, struct patch *patch) { /* * store information about incoming file deletion @@ -3278,7 +3277,7 @@ static void prepare_fn_table(struct patch *patch) while (patch) { if ((patch->new_name == NULL) || (patch->is_rename)) { struct string_list_item *item; - item = string_list_insert(&fn_table, patch->old_name); + item = string_list_insert(&state->fn_table, patch->old_name); item->util = PATH_TO_BE_DELETED; } patch = patch->next; @@ -3299,7 +3298,9 @@ static int checkout_target(struct index_state *istate, return 0; } -static struct patch *previous_patch(struct patch *patch, int *gone) +static struct patch *previous_patch(struct apply_state *state, + struct patch *patch, + int *gone) { struct patch *previous; @@ -3307,7 +3308,7 @@ static struct patch *previous_patch(struct patch *patch, int *gone) if (patch->is_copy || patch->is_rename) return NULL; /* "git" patches do not depend on the order */ - previous = in_fn_table(patch->old_name); + previous = in_fn_table(state, patch->old_name); if (!previous) return NULL; @@ -3376,7 +3377,7 @@ static int load_preimage(struct apply_state *state, struct patch *previous; int status; - previous = previous_patch(patch, &status); + previous = previous_patch(state, patch, &status); if (status) return error(_("path %s has been renamed/deleted"), patch->old_name); @@ -3572,7 +3573,7 @@ static int apply_data(struct apply_state *state, struct patch *patch, } patch->result = image.buf; patch->resultsize = image.len; - add_to_fn_table(patch); + add_to_fn_table(state, patch); free(image.line_allocated); if (0 < patch->is_delete && patch->resultsize) @@ -3606,7 +3607,7 @@ static int check_preimage(struct apply_state *state, return 0; assert(patch->is_new <= 0); - previous = previous_patch(patch, &status); + previous = previous_patch(state, patch, &status); if (status) return error(_("path %s has been renamed/deleted"), old_name); @@ -3852,7 +3853,7 @@ static int check_patch(struct apply_state *state, struct patch *patch) * B and rename from A to B is handled the same way by asking * was_deleted(). */ - if ((tpatch = in_fn_table(new_name)) && + if ((tpatch = in_fn_table(state, new_name)) && (was_deleted(tpatch) || to_be_deleted(tpatch))) ok_if_exists = 1; else @@ -3930,7 +3931,7 @@ static int check_patch_list(struct apply_state *state, struct patch *patch) int err = 0; prepare_symlink_changes(patch); - prepare_fn_table(patch); + prepare_fn_table(state, patch); while (patch) { if (state->apply_verbosely) say_patch_name(stderr, @@ -4574,7 +4575,7 @@ static int apply_patch(struct apply_state *state, free_patch_list(list); strbuf_release(&buf); - string_list_clear(&fn_table, 0); + string_list_clear(&state->fn_table, 0); return 0; } @@ -4668,6 +4669,8 @@ static void clear_apply_state(struct apply_state *state) { string_list_clear(&state->limit_by_name, 0); strbuf_release(&state->root); + + /* &state->fn_table is cleared at the end of apply_patch() */ } int cmd_apply(int argc, const char **argv, const char *prefix) From 2f63cea963667d17271d96196b6ef1605790032a Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:22 +0200 Subject: [PATCH 45/50] builtin/apply: move 'symlink_changes' global into 'struct apply_state' To libify the apply functionality the 'symlink_changes' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 50 +++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 47622bee69..980bb34522 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -34,6 +34,20 @@ enum ws_ignore { ignore_ws_change }; +/* + * We need to keep track of how symlinks in the preimage are + * manipulated by the patches. A patch to add a/b/c where a/b + * is a symlink should not be allowed to affect the directory + * the symlink points at, but if the same patch removes a/b, + * it is perfectly fine, as the patch removes a/b to make room + * to create a directory a/b so that a/b/c can be created. + * + * See also "struct string_list symlink_changes" in "struct + * apply_state". + */ +#define SYMLINK_GOES_AWAY 01 +#define SYMLINK_IN_RESULT 02 + struct apply_state { const char *prefix; int prefix_length; @@ -75,6 +89,7 @@ struct apply_state { /* Various "current state" */ int linenr; /* current line number */ + struct string_list symlink_changes; /* we have to track symlinks */ /* * For "diff-stat" like behaviour, we keep track of the biggest change @@ -3702,52 +3717,42 @@ static int check_to_create(struct apply_state *state, return 0; } -/* - * We need to keep track of how symlinks in the preimage are - * manipulated by the patches. A patch to add a/b/c where a/b - * is a symlink should not be allowed to affect the directory - * the symlink points at, but if the same patch removes a/b, - * it is perfectly fine, as the patch removes a/b to make room - * to create a directory a/b so that a/b/c can be created. - */ -static struct string_list symlink_changes; -#define SYMLINK_GOES_AWAY 01 -#define SYMLINK_IN_RESULT 02 - -static uintptr_t register_symlink_changes(const char *path, uintptr_t what) +static uintptr_t register_symlink_changes(struct apply_state *state, + const char *path, + uintptr_t what) { struct string_list_item *ent; - ent = string_list_lookup(&symlink_changes, path); + ent = string_list_lookup(&state->symlink_changes, path); if (!ent) { - ent = string_list_insert(&symlink_changes, path); + ent = string_list_insert(&state->symlink_changes, path); ent->util = (void *)0; } ent->util = (void *)(what | ((uintptr_t)ent->util)); return (uintptr_t)ent->util; } -static uintptr_t check_symlink_changes(const char *path) +static uintptr_t check_symlink_changes(struct apply_state *state, const char *path) { struct string_list_item *ent; - ent = string_list_lookup(&symlink_changes, path); + ent = string_list_lookup(&state->symlink_changes, path); if (!ent) return 0; return (uintptr_t)ent->util; } -static void prepare_symlink_changes(struct patch *patch) +static void prepare_symlink_changes(struct apply_state *state, struct patch *patch) { for ( ; patch; patch = patch->next) { if ((patch->old_name && S_ISLNK(patch->old_mode)) && (patch->is_rename || patch->is_delete)) /* the symlink at patch->old_name is removed */ - register_symlink_changes(patch->old_name, SYMLINK_GOES_AWAY); + register_symlink_changes(state, patch->old_name, SYMLINK_GOES_AWAY); if (patch->new_name && S_ISLNK(patch->new_mode)) /* the symlink at patch->new_name is created or remains */ - register_symlink_changes(patch->new_name, SYMLINK_IN_RESULT); + register_symlink_changes(state, patch->new_name, SYMLINK_IN_RESULT); } } @@ -3761,7 +3766,7 @@ static int path_is_beyond_symlink_1(struct apply_state *state, struct strbuf *na if (!name->len) break; name->buf[name->len] = '\0'; - change = check_symlink_changes(name->buf); + change = check_symlink_changes(state, name->buf); if (change & SYMLINK_IN_RESULT) return 1; if (change & SYMLINK_GOES_AWAY) @@ -3930,7 +3935,7 @@ static int check_patch_list(struct apply_state *state, struct patch *patch) { int err = 0; - prepare_symlink_changes(patch); + prepare_symlink_changes(state, patch); prepare_fn_table(state, patch); while (patch) { if (state->apply_verbosely) @@ -4668,6 +4673,7 @@ static void init_apply_state(struct apply_state *state, const char *prefix) static void clear_apply_state(struct apply_state *state) { string_list_clear(&state->limit_by_name, 0); + string_list_clear(&state->symlink_changes, 0); strbuf_release(&state->root); /* &state->fn_table is cleared at the end of apply_patch() */ From c84a86c99526b88cfd7664888ecbfd28f35a025f Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:23 +0200 Subject: [PATCH 46/50] builtin/apply: move 'state' check into check_apply_state() To libify the apply functionality we should provide a function to check that the values in a 'struct apply_state' instance are coherent. Let's move the code to do that into a new check_apply_state() function. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 52 +++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 980bb34522..8095026d33 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -4679,11 +4679,38 @@ static void clear_apply_state(struct apply_state *state) /* &state->fn_table is cleared at the end of apply_patch() */ } +static void check_apply_state(struct apply_state *state, int force_apply) +{ + int is_not_gitdir = !startup_info->have_repository; + + if (state->apply_with_reject && state->threeway) + die("--reject and --3way cannot be used together."); + if (state->cached && state->threeway) + die("--cached and --3way cannot be used together."); + if (state->threeway) { + if (is_not_gitdir) + die(_("--3way outside a repository")); + state->check_index = 1; + } + if (state->apply_with_reject) + state->apply = state->apply_verbosely = 1; + if (!force_apply && (state->diffstat || state->numstat || state->summary || state->check || state->fake_ancestor)) + state->apply = 0; + if (state->check_index && is_not_gitdir) + die(_("--index outside a repository")); + if (state->cached) { + if (is_not_gitdir) + die(_("--cached outside a repository")); + state->check_index = 1; + } + if (state->check_index) + state->unsafe_paths = 0; +} + int cmd_apply(int argc, const char **argv, const char *prefix) { int i; int errs = 0; - int is_not_gitdir = !startup_info->have_repository; int force_apply = 0; int options = 0; int read_stdin = 1; @@ -4763,28 +4790,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, state.prefix, builtin_apply_options, apply_usage, 0); - if (state.apply_with_reject && state.threeway) - die("--reject and --3way cannot be used together."); - if (state.cached && state.threeway) - die("--cached and --3way cannot be used together."); - if (state.threeway) { - if (is_not_gitdir) - die(_("--3way outside a repository")); - state.check_index = 1; - } - if (state.apply_with_reject) - state.apply = state.apply_verbosely = 1; - if (!force_apply && (state.diffstat || state.numstat || state.summary || state.check || state.fake_ancestor)) - state.apply = 0; - if (state.check_index && is_not_gitdir) - die(_("--index outside a repository")); - if (state.cached) { - if (is_not_gitdir) - die(_("--cached outside a repository")); - state.check_index = 1; - } - if (state.check_index) - state.unsafe_paths = 0; + check_apply_state(&state, force_apply); for (i = 0; i < argc; i++) { const char *arg = argv[i]; From 91b769c48f4cf46d9514770849a1bf9cb33430c3 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 24 May 2016 10:11:24 +0200 Subject: [PATCH 47/50] builtin/apply: move applying patches into apply_all_patches() To libify the apply functionality we should provide a function to apply many patches. Let's move the code to do that into a new apply_all_patches() function. Reviewed-by: Stefan Beller Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 129 ++++++++++++++++++++++++++---------------------- 1 file changed, 71 insertions(+), 58 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 8095026d33..5027f1b504 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -4707,13 +4707,80 @@ static void check_apply_state(struct apply_state *state, int force_apply) state->unsafe_paths = 0; } -int cmd_apply(int argc, const char **argv, const char *prefix) +static int apply_all_patches(struct apply_state *state, + int argc, + const char **argv, + int options) { int i; int errs = 0; + int read_stdin = 1; + + for (i = 0; i < argc; i++) { + const char *arg = argv[i]; + int fd; + + if (!strcmp(arg, "-")) { + errs |= apply_patch(state, 0, "", options); + read_stdin = 0; + continue; + } else if (0 < state->prefix_length) + arg = prefix_filename(state->prefix, + state->prefix_length, + arg); + + fd = open(arg, O_RDONLY); + if (fd < 0) + die_errno(_("can't open patch '%s'"), arg); + read_stdin = 0; + set_default_whitespace_mode(state); + errs |= apply_patch(state, fd, arg, options); + close(fd); + } + set_default_whitespace_mode(state); + if (read_stdin) + errs |= apply_patch(state, 0, "", options); + + if (state->whitespace_error) { + if (state->squelch_whitespace_errors && + state->squelch_whitespace_errors < state->whitespace_error) { + int squelched = + state->whitespace_error - state->squelch_whitespace_errors; + warning(Q_("squelched %d whitespace error", + "squelched %d whitespace errors", + squelched), + squelched); + } + if (state->ws_error_action == die_on_ws_error) + die(Q_("%d line adds whitespace errors.", + "%d lines add whitespace errors.", + state->whitespace_error), + state->whitespace_error); + if (state->applied_after_fixing_ws && state->apply) + warning("%d line%s applied after" + " fixing whitespace errors.", + state->applied_after_fixing_ws, + state->applied_after_fixing_ws == 1 ? "" : "s"); + else if (state->whitespace_error) + warning(Q_("%d line adds whitespace errors.", + "%d lines add whitespace errors.", + state->whitespace_error), + state->whitespace_error); + } + + if (state->update_index) { + if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) + die(_("Unable to write new index file")); + } + + return !!errs; +} + +int cmd_apply(int argc, const char **argv, const char *prefix) +{ int force_apply = 0; int options = 0; - int read_stdin = 1; + int ret; struct apply_state state; struct option builtin_apply_options[] = { @@ -4792,63 +4859,9 @@ int cmd_apply(int argc, const char **argv, const char *prefix) check_apply_state(&state, force_apply); - for (i = 0; i < argc; i++) { - const char *arg = argv[i]; - int fd; - - if (!strcmp(arg, "-")) { - errs |= apply_patch(&state, 0, "", options); - read_stdin = 0; - continue; - } else if (0 < state.prefix_length) - arg = prefix_filename(state.prefix, - state.prefix_length, - arg); - - fd = open(arg, O_RDONLY); - if (fd < 0) - die_errno(_("can't open patch '%s'"), arg); - read_stdin = 0; - set_default_whitespace_mode(&state); - errs |= apply_patch(&state, fd, arg, options); - close(fd); - } - set_default_whitespace_mode(&state); - if (read_stdin) - errs |= apply_patch(&state, 0, "", options); - if (state.whitespace_error) { - if (state.squelch_whitespace_errors && - state.squelch_whitespace_errors < state.whitespace_error) { - int squelched = - state.whitespace_error - state.squelch_whitespace_errors; - warning(Q_("squelched %d whitespace error", - "squelched %d whitespace errors", - squelched), - squelched); - } - if (state.ws_error_action == die_on_ws_error) - die(Q_("%d line adds whitespace errors.", - "%d lines add whitespace errors.", - state.whitespace_error), - state.whitespace_error); - if (state.applied_after_fixing_ws && state.apply) - warning("%d line%s applied after" - " fixing whitespace errors.", - state.applied_after_fixing_ws, - state.applied_after_fixing_ws == 1 ? "" : "s"); - else if (state.whitespace_error) - warning(Q_("%d line adds whitespace errors.", - "%d lines add whitespace errors.", - state.whitespace_error), - state.whitespace_error); - } - - if (state.update_index) { - if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) - die(_("Unable to write new index file")); - } + ret = apply_all_patches(&state, argc, argv, options); clear_apply_state(&state); - return !!errs; + return ret; } From 8f31fac365c312aa9109a7a1fc1014e56ed473d2 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 3 Jun 2016 18:58:51 +0200 Subject: [PATCH 48/50] builtin/apply: add 'lock_file' pointer into 'struct apply_state' We cannot have a 'struct lock_file' allocated on the stack, as lockfile.c keeps a linked list of all created lock_file structures. Also 'struct apply_state' users might later want the same 'struct lock_file' instance to be reused by different series of calls to the apply api. So let's add a 'struct lock_file *lock_file' pointer into 'struct apply_state' and have the user of 'struct apply_state' allocate memory for the actual 'struct lock_file' instance. Let's also add an argument to init_apply_state(), so that the caller can easily supply a pointer to the allocated instance. Helped-by: Eric Sunshine Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 5027f1b504..cc635ebd1a 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -52,6 +52,12 @@ struct apply_state { const char *prefix; int prefix_length; + /* + * Since lockfile.c keeps a linked list of all created + * lock_file structures, it isn't safe to free(lock_file). + */ + struct lock_file *lock_file; + /* These control what gets looked at and modified */ int apply; /* this is not a dry-run */ int cached; /* apply to the index only */ @@ -4547,7 +4553,7 @@ static int apply_patch(struct apply_state *state, state->update_index = state->check_index && state->apply; if (state->update_index && newfd < 0) - newfd = hold_locked_index(&lock_file, 1); + newfd = hold_locked_index(state->lock_file, 1); if (state->check_index) { if (read_cache() < 0) @@ -4648,11 +4654,14 @@ static int option_parse_directory(const struct option *opt, return 0; } -static void init_apply_state(struct apply_state *state, const char *prefix) +static void init_apply_state(struct apply_state *state, + const char *prefix, + struct lock_file *lock_file) { memset(state, 0, sizeof(*state)); state->prefix = prefix; state->prefix_length = state->prefix ? strlen(state->prefix) : 0; + state->lock_file = lock_file; state->apply = 1; state->line_termination = '\n'; state->p_value = 1; @@ -4705,6 +4714,8 @@ static void check_apply_state(struct apply_state *state, int force_apply) } if (state->check_index) state->unsafe_paths = 0; + if (!state->lock_file) + die("BUG: state->lock_file should not be NULL"); } static int apply_all_patches(struct apply_state *state, @@ -4769,7 +4780,7 @@ static int apply_all_patches(struct apply_state *state, } if (state->update_index) { - if (write_locked_index(&the_index, &lock_file, COMMIT_LOCK)) + if (write_locked_index(&the_index, state->lock_file, COMMIT_LOCK)) die(_("Unable to write new index file")); } @@ -4852,7 +4863,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix) OPT_END() }; - init_apply_state(&state, prefix); + init_apply_state(&state, prefix, &lock_file); argc = parse_options(argc, argv, state.prefix, builtin_apply_options, apply_usage, 0); From a1bc3dd46433c6e7e6f1ca5f3bd5429858a60078 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 3 Jun 2016 18:58:52 +0200 Subject: [PATCH 49/50] builtin/apply: move 'newfd' global into 'struct apply_state' To libify the apply functionality the 'newfd' variable should not be static and global to the file. Let's move it into 'struct apply_state'. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- builtin/apply.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index cc635ebd1a..7338ee6b68 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -57,6 +57,7 @@ struct apply_state { * lock_file structures, it isn't safe to free(lock_file). */ struct lock_file *lock_file; + int newfd; /* These control what gets looked at and modified */ int apply; /* this is not a dry-run */ @@ -120,8 +121,6 @@ struct apply_state { int applied_after_fixing_ws; }; -static int newfd = -1; - static const char * const apply_usage[] = { N_("git apply [] [...]"), NULL @@ -4552,8 +4551,8 @@ static int apply_patch(struct apply_state *state, state->apply = 0; state->update_index = state->check_index && state->apply; - if (state->update_index && newfd < 0) - newfd = hold_locked_index(state->lock_file, 1); + if (state->update_index && state->newfd < 0) + state->newfd = hold_locked_index(state->lock_file, 1); if (state->check_index) { if (read_cache() < 0) @@ -4662,6 +4661,7 @@ static void init_apply_state(struct apply_state *state, state->prefix = prefix; state->prefix_length = state->prefix ? strlen(state->prefix) : 0; state->lock_file = lock_file; + state->newfd = -1; state->apply = 1; state->line_termination = '\n'; state->p_value = 1; @@ -4782,6 +4782,7 @@ static int apply_all_patches(struct apply_state *state, if (state->update_index) { if (write_locked_index(&the_index, state->lock_file, COMMIT_LOCK)) die(_("Unable to write new index file")); + state->newfd = -1; } return !!errs; From a7d4c49a8201f75699bf59852ef8e345f41a12b6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 6 Jun 2016 13:11:02 -0700 Subject: [PATCH 50/50] builtin/apply: remove misleading comment on lock_file field Just like pointer field like prefix, the piece of memory pointed at by lock_file field is not owned by the apply_state structure. It is true that the caller needs to be careful about the lifetime rule for lockfile instances, but that is none of this API's business. Signed-off-by: Junio C Hamano --- builtin/apply.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/builtin/apply.c b/builtin/apply.c index 7338ee6b68..b3eb704725 100644 --- a/builtin/apply.c +++ b/builtin/apply.c @@ -52,10 +52,7 @@ struct apply_state { const char *prefix; int prefix_length; - /* - * Since lockfile.c keeps a linked list of all created - * lock_file structures, it isn't safe to free(lock_file). - */ + /* These are lock_file related */ struct lock_file *lock_file; int newfd;