]> git.ipfire.org Git - thirdparty/git.git/blobdiff - apply.c
Start the 2.46 cycle
[thirdparty/git.git] / apply.c
diff --git a/apply.c b/apply.c
index 785e055949c4aaa649ee4d1c982d5c6a4a3d23cc..901b67e6255af4174a1e5a00cf01de4d2545d659 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -7,21 +7,34 @@
  *
  */
 
-#include "cache.h"
+#include "git-compat-util.h"
+#include "abspath.h"
+#include "base85.h"
 #include "config.h"
-#include "object-store.h"
-#include "blob.h"
+#include "object-store-ll.h"
 #include "delta.h"
 #include "diff.h"
 #include "dir.h"
+#include "environment.h"
+#include "gettext.h"
+#include "hex.h"
 #include "xdiff-interface.h"
-#include "ll-merge.h"
+#include "merge-ll.h"
 #include "lockfile.h"
+#include "name-hash.h"
+#include "object-name.h"
+#include "object-file.h"
 #include "parse-options.h"
+#include "path.h"
 #include "quote.h"
+#include "read-cache.h"
 #include "rerere.h"
 #include "apply.h"
 #include "entry.h"
+#include "setup.h"
+#include "symlinks.h"
+#include "wildmatch.h"
+#include "ws.h"
 
 struct gitdiff_data {
        struct strbuf *root;
@@ -64,7 +77,8 @@ static int parse_whitespace_option(struct apply_state *state, const char *option
                return 0;
        }
        /*
-        * Please update $__git_whitespacelist in git-completion.bash
+        * Please update $__git_whitespacelist in git-completion.bash,
+        * Documentation/git-apply.txt, and Documentation/git-am.txt
         * when you add new options.
         */
        return error(_("unrecognized whitespace option '%s'"), option);
@@ -398,9 +412,10 @@ static void say_patch_name(FILE *output, const char *fmt, struct patch *patch)
 
 static int read_patch_file(struct strbuf *sb, int fd)
 {
-       if (strbuf_read(sb, fd, 0) < 0 || sb->len >= MAX_APPLY_SIZE)
-               return error_errno("git apply: failed to read");
-
+       if (strbuf_read(sb, fd, 0) < 0)
+               return error_errno(_("failed to read patch"));
+       else if (sb->len >= MAX_APPLY_SIZE)
+               return error(_("patch too large"));
        /*
         * Make sure that we have some slop in the buffer
         * so that we can do speculative "memcmp" etc, and
@@ -2212,7 +2227,8 @@ static void reverse_patches(struct patch *p)
                struct fragment *frag = p->fragments;
 
                SWAP(p->new_name, p->old_name);
-               SWAP(p->new_mode, p->old_mode);
+               if (p->new_mode)
+                       SWAP(p->new_mode, p->old_mode);
                SWAP(p->is_new, p->is_delete);
                SWAP(p->lines_added, p->lines_deleted);
                SWAP(p->old_oid_prefix, p->new_oid_prefix);
@@ -3208,7 +3224,8 @@ static int apply_binary(struct apply_state *state,
                unsigned long size;
                char *result;
 
-               result = read_object_file(&oid, &type, &size);
+               result = repo_read_object_file(the_repository, &oid, &type,
+                                              &size);
                if (!result)
                        return error(_("the necessary postimage %s for "
                                       "'%s' cannot be read"),
@@ -3271,7 +3288,8 @@ static int read_blob_object(struct strbuf *buf, const struct object_id *oid, uns
                unsigned long sz;
                char *result;
 
-               result = read_object_file(oid, &type, &sz);
+               result = repo_read_object_file(the_repository, oid, &type,
+                                              &sz);
                if (!result)
                        return -1;
                /* XXX read_sha1_file NUL-terminates */
@@ -3499,7 +3517,8 @@ static int resolve_to(struct image *image, const struct object_id *result_id)
 
        clear_image(image);
 
-       image->buf = read_object_file(result_id, &type, &size);
+       image->buf = repo_read_object_file(the_repository, result_id, &type,
+                                          &size);
        if (!image->buf || type != OBJ_BLOB)
                die("unable to read blob object %s", oid_to_hex(result_id));
        image->len = size;
@@ -3617,7 +3636,7 @@ static int try_threeway(struct apply_state *state,
        /* Preimage the patch was prepared for */
        if (patch->is_new)
                write_object_file("", 0, OBJ_BLOB, &pre_oid);
-       else if (get_oid(patch->old_oid_prefix, &pre_oid) ||
+       else if (repo_get_oid(the_repository, patch->old_oid_prefix, &pre_oid) ||
                 read_blob_object(&buf, &pre_oid, patch->old_mode))
                return error(_("repository lacks the necessary blob to perform 3-way merge."));
 
@@ -3693,8 +3712,10 @@ static int apply_data(struct apply_state *state, struct patch *patch,
                        fprintf(stderr, _("Falling back to direct application...\n"));
 
                /* Note: with --reject, apply_fragments() returns 0 */
-               if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0)
+               if (patch->direct_to_threeway || apply_fragments(state, &image, patch) < 0) {
+                       clear_image(&image);
                        return -1;
+               }
        }
        patch->result = image.buf;
        patch->resultsize = image.len;
@@ -3767,8 +3788,17 @@ static int check_preimage(struct apply_state *state,
                return error_errno("%s", old_name);
        }
 
-       if (!state->cached && !previous)
-               st_mode = ce_mode_from_stat(*ce, st->st_mode);
+       if (!state->cached && !previous) {
+               if (*ce && !(*ce)->ce_mode)
+                       BUG("ce_mode == 0 for path '%s'", old_name);
+
+               if (trust_executable_bit)
+                       st_mode = ce_mode_from_stat(*ce, st->st_mode);
+               else if (*ce)
+                       st_mode = (*ce)->ce_mode;
+               else
+                       st_mode = patch->old_mode;
+       }
 
        if (patch->is_new < 0)
                patch->is_new = 0;
@@ -4134,7 +4164,7 @@ static int build_fake_ancestor(struct apply_state *state, struct patch *list)
                        else
                                return error(_("sha1 information is lacking or "
                                               "useless for submodule %s"), name);
-               } else if (!get_oid_blob(patch->old_oid_prefix, &oid)) {
+               } else if (!repo_get_oid_blob(the_repository, patch->old_oid_prefix, &oid)) {
                        ; /* ok */
                } else if (!patch->lines_added && !patch->lines_deleted) {
                        /* mode-only change: update the current */
@@ -4420,6 +4450,7 @@ static int create_one_file(struct apply_state *state,
                           const char *buf,
                           unsigned long size)
 {
+       char *newpath = NULL;
        int res;
 
        if (state->cached)
@@ -4481,24 +4512,26 @@ static int create_one_file(struct apply_state *state,
                unsigned int nr = getpid();
 
                for (;;) {
-                       char newpath[PATH_MAX];
-                       mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
+                       newpath = mkpathdup("%s~%u", path, nr);
                        res = try_create_file(state, newpath, mode, buf, size);
                        if (res < 0)
-                               return -1;
+                               goto out;
                        if (!res) {
                                if (!rename(newpath, path))
-                                       return 0;
+                                       goto out;
                                unlink_or_warn(newpath);
                                break;
                        }
                        if (errno != EEXIST)
                                break;
                        ++nr;
+                       FREE_AND_NULL(newpath);
                }
        }
-       return error_errno(_("unable to write file '%s' mode %o"),
-                          path, mode);
+       res = error_errno(_("unable to write file '%s' mode %o"), path, mode);
+out:
+       free(newpath);
+       return res;
 }
 
 static int add_conflicted_stages_file(struct apply_state *state,
@@ -4581,7 +4614,7 @@ static int write_out_one_result(struct apply_state *state,
 static int write_out_one_reject(struct apply_state *state, struct patch *patch)
 {
        FILE *rej;
-       char namebuf[PATH_MAX];
+       char *namebuf;
        struct fragment *frag;
        int fd, cnt = 0;
        struct strbuf sb = STRBUF_INIT;
@@ -4614,28 +4647,30 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
                say_patch_name(stderr, sb.buf, patch);
        strbuf_release(&sb);
 
-       cnt = strlen(patch->new_name);
-       if (ARRAY_SIZE(namebuf) <= cnt + 5) {
-               cnt = ARRAY_SIZE(namebuf) - 5;
-               warning(_("truncating .rej filename to %.*s.rej"),
-                       cnt - 1, patch->new_name);
-       }
-       memcpy(namebuf, patch->new_name, cnt);
-       memcpy(namebuf + cnt, ".rej", 5);
+       namebuf = xstrfmt("%s.rej", patch->new_name);
 
        fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
        if (fd < 0) {
-               if (errno != EEXIST)
-                       return error_errno(_("cannot open %s"), namebuf);
-               if (unlink(namebuf))
-                       return error_errno(_("cannot unlink '%s'"), namebuf);
+               if (errno != EEXIST) {
+                       error_errno(_("cannot open %s"), namebuf);
+                       goto error;
+               }
+               if (unlink(namebuf)) {
+                       error_errno(_("cannot unlink '%s'"), namebuf);
+                       goto error;
+               }
                fd = open(namebuf, O_CREAT | O_EXCL | O_WRONLY, 0666);
-               if (fd < 0)
-                       return error_errno(_("cannot open %s"), namebuf);
+               if (fd < 0) {
+                       error_errno(_("cannot open %s"), namebuf);
+                       goto error;
+               }
        }
        rej = fdopen(fd, "w");
-       if (!rej)
-               return error_errno(_("cannot open %s"), namebuf);
+       if (!rej) {
+               error_errno(_("cannot open %s"), namebuf);
+               close(fd);
+               goto error;
+       }
 
        /* Normal git tools never deal with .rej, so do not pretend
         * this is a git patch by saying --git or giving extended
@@ -4659,6 +4694,8 @@ static int write_out_one_reject(struct apply_state *state, struct patch *patch)
                        fputc('\n', rej);
        }
        fclose(rej);
+error:
+       free(namebuf);
        return -1;
 }