]> git.ipfire.org Git - thirdparty/git.git/blobdiff - apply.c
commit-graph.c: ensure graph layers respect core.sharedRepository
[thirdparty/git.git] / apply.c
diff --git a/apply.c b/apply.c
index cde95369bb3f3a9c763108fd91e1e48e0e455e29..144c19aaca80d943e237ffd84f215a49415e0d5a 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -32,7 +32,7 @@ static void git_apply_config(void)
 {
        git_config_get_string_const("apply.whitespace", &apply_default_whitespace);
        git_config_get_string_const("apply.ignorewhitespace", &apply_default_ignorewhitespace);
-       git_config(git_default_config, NULL);
+       git_config(git_xmerge_config, NULL);
 }
 
 static int parse_whitespace_option(struct apply_state *state, const char *option)
@@ -450,7 +450,7 @@ static char *find_name_gnu(struct strbuf *root,
 
        /*
         * Proposed "new-style" GNU patch/diff format; see
-        * https://public-inbox.org/git/7vll0wvb2a.fsf@assigned-by-dhcp.cox.net/
+        * https://lore.kernel.org/git/7vll0wvb2a.fsf@assigned-by-dhcp.cox.net/
         */
        if (unquote_c_style(&name, line, NULL)) {
                strbuf_release(&name);
@@ -1361,11 +1361,32 @@ int parse_git_diff_header(struct strbuf *root,
                        if (check_header_line(*linenr, patch))
                                return -1;
                        if (res > 0)
-                               return offset;
+                               goto done;
                        break;
                }
        }
 
+done:
+       if (!patch->old_name && !patch->new_name) {
+               if (!patch->def_name) {
+                       error(Q_("git diff header lacks filename information when removing "
+                                "%d leading pathname component (line %d)",
+                                "git diff header lacks filename information when removing "
+                                "%d leading pathname components (line %d)",
+                                parse_hdr_state.p_value),
+                             parse_hdr_state.p_value, *linenr);
+                       return -128;
+               }
+               patch->old_name = xstrdup(patch->def_name);
+               patch->new_name = xstrdup(patch->def_name);
+       }
+       if ((!patch->new_name && !patch->is_delete) ||
+           (!patch->old_name && !patch->is_new)) {
+               error(_("git diff header lacks filename information "
+                       "(line %d)"), *linenr);
+               return -128;
+       }
+       patch->is_toplevel_relative = 1;
        return offset;
 }
 
@@ -1546,26 +1567,6 @@ static int find_header(struct apply_state *state,
                                return -128;
                        if (git_hdr_len <= len)
                                continue;
-                       if (!patch->old_name && !patch->new_name) {
-                               if (!patch->def_name) {
-                                       error(Q_("git diff header lacks filename information when removing "
-                                                       "%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);
-                                       return -128;
-                               }
-                               patch->old_name = xstrdup(patch->def_name);
-                               patch->new_name = xstrdup(patch->def_name);
-                       }
-                       if ((!patch->new_name && !patch->is_delete) ||
-                           (!patch->old_name && !patch->is_new)) {
-                               error(_("git diff header lacks filename information "
-                                            "(line %d)"), state->linenr);
-                               return -128;
-                       }
-                       patch->is_toplevel_relative = 1;
                        *hdrsize = git_hdr_len;
                        return offset;
                }
@@ -2660,6 +2661,16 @@ static int find_pos(struct apply_state *state,
        unsigned long backwards, forwards, current;
        int backwards_lno, forwards_lno, current_lno;
 
+       /*
+        * When running with --allow-overlap, it is possible that a hunk is
+        * seen that pretends to start at the beginning (but no longer does),
+        * and that *still* needs to match the end. So trust `match_end` more
+        * than `match_beginning`.
+        */
+       if (state->allow_overlap && match_beginning && match_end &&
+           img->nr - preimage->nr != 0)
+               match_beginning = 0;
+
        /*
         * If match_beginning or match_end is specified, there is no
         * point starting from a wrong line that will never match and
@@ -3146,7 +3157,8 @@ static int apply_binary(struct apply_state *state,
                 * See if the old one matches what the patch
                 * applies to.
                 */
-               hash_object_file(img->buf, img->len, blob_type, &oid);
+               hash_object_file(the_hash_algo, img->buf, img->len, blob_type,
+                                &oid);
                if (strcmp(oid_to_hex(&oid), patch->old_oid_prefix))
                        return error(_("the patch applies to '%s' (%s), "
                                       "which does not match the "
@@ -3191,7 +3203,8 @@ static int apply_binary(struct apply_state *state,
                                     name);
 
                /* verify that the result matches */
-               hash_object_file(img->buf, img->len, blob_type, &oid);
+               hash_object_file(the_hash_algo, img->buf, img->len, blob_type,
+                                &oid);
                if (strcmp(oid_to_hex(&oid), patch->new_oid_prefix))
                        return error(_("binary patch to '%s' creates incorrect result (expecting %s, got %s)"),
                                name, patch->new_oid_prefix, oid_to_hex(&oid));
@@ -4182,8 +4195,8 @@ static void show_rename_copy(struct patch *p)
                old_name = slash_old + 1;
                new_name = slash_new + 1;
        }
-       /* p->old_name thru old_name is the common prefix, and old_name and new_name
-        * through the end of names are renames
+       /* p->old_name through old_name is the common prefix, and old_name and
+        * new_name through the end of names are renames
         */
        if (old_name != p->old_name)
                printf(" %s %.*s{%s => %s} (%d%%)\n", renamecopy,
@@ -4336,7 +4349,7 @@ static int try_create_file(struct apply_state *state, const char *path,
        if (fd < 0)
                return 1;
 
-       if (convert_to_working_tree(state->repo->index, path, buf, size, &nbuf)) {
+       if (convert_to_working_tree(state->repo->index, path, buf, size, &nbuf, NULL)) {
                size = nbuf.len;
                buf  = nbuf.buf;
        }
@@ -4643,6 +4656,7 @@ static int apply_patch(struct apply_state *state,
        struct patch *list = NULL, **listp = &list;
        int skipped_patch = 0;
        int res = 0;
+       int flush_attributes = 0;
 
        state->patch_input_file = filename;
        if (read_patch_file(&buf, fd) < 0)
@@ -4670,6 +4684,14 @@ static int apply_patch(struct apply_state *state,
                        patch_stats(state, patch);
                        *listp = patch;
                        listp = &patch->next;
+
+                       if ((patch->new_name &&
+                            ends_with_path_components(patch->new_name,
+                                                      GITATTRIBUTES_FILE)) ||
+                           (patch->old_name &&
+                            ends_with_path_components(patch->old_name,
+                                                      GITATTRIBUTES_FILE)))
+                               flush_attributes = 1;
                }
                else {
                        if (state->apply_verbosity > verbosity_normal)
@@ -4746,6 +4768,8 @@ static int apply_patch(struct apply_state *state,
        if (state->summary && state->apply_verbosity > verbosity_silent)
                summary_patch_list(list);
 
+       if (flush_attributes)
+               reset_parsed_attributes();
 end:
        free_patch_list(list);
        strbuf_release(&buf);