git checkout: do not allow switching to a tree-ish that is not a commit
[gitweb.git] / builtin-apply.c
index 2216a0bf7cd53adc31346f66a3b9786a1d688bad..50b623e54c003fb5bbe183568d13f496c3c41c25 100644 (file)
@@ -13,6 +13,7 @@
 #include "delta.h"
 #include "builtin.h"
 #include "string-list.h"
+#include "dir.h"
 
 /*
  *  --check turns on checking that the working tree matches the
@@ -274,7 +275,7 @@ static void say_patch_name(FILE *output, const char *pre,
 static void read_patch_file(struct strbuf *sb, int fd)
 {
        if (strbuf_read(sb, fd, 0) < 0)
-               die("git-apply: read returned %s", strerror(errno));
+               die("git apply: read returned %s", strerror(errno));
 
        /*
         * Make sure that we have some slop in the buffer
@@ -506,17 +507,17 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
                name = orig_name;
                len = strlen(name);
                if (isnull)
-                       die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
+                       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);
                if (!another || memcmp(another, name, len))
-                       die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
+                       die("git apply: bad git-diff - inconsistent %s filename on line %d", oldnew, 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);
+                       die("git apply: bad git-diff - expected /dev/null on line %d", linenr);
                return NULL;
        }
 }
@@ -809,6 +810,13 @@ static int parse_git_header(char *line, int len, unsigned int size, struct patch
         * the default name from the header.
         */
        patch->def_name = git_header_name(line, len);
+       if (patch->def_name && root) {
+               char *s = xmalloc(root_len + strlen(patch->def_name) + 1);
+               strcpy(s, root);
+               strcpy(s + root_len, patch->def_name);
+               free(patch->def_name);
+               patch->def_name = s;
+       }
 
        line += len;
        size -= len;
@@ -1696,7 +1704,7 @@ static int match_fragment(struct image *img,
                fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
 
                /* Try fixing the line in the target */
-               if (sizeof(tgtfixbuf) < tgtlen)
+               if (sizeof(tgtfixbuf) > tgtlen)
                        tgtfix = tgtfixbuf;
                else
                        tgtfix = xmalloc(tgtlen);
@@ -1996,6 +2004,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
        /*
         * A hunk to change lines at the beginning would begin with
         * @@ -1,L +N,M @@
+        * but we need to be careful.  -U0 that inserts before the second
+        * line also has this pattern.
         *
         * And a hunk to add to an empty file would begin with
         * @@ -0,0 +N,M @@
@@ -2003,7 +2013,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
         * In other words, a hunk that is (frag->oldpos <= 1) with or
         * without leading context must match at the beginning.
         */
-       match_beginning = frag->oldpos <= 1;
+       match_beginning = (!frag->oldpos ||
+                          (frag->oldpos == 1 && !unidiff_zero));
 
        /*
         * A hunk without trailing lines must match at the end.
@@ -2582,6 +2593,8 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
                        sha1_ptr = sha1;
 
                ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
+               if (!ce)
+                       die("make_cache_entry failed for path '%s'", name);
                if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
                        die ("Could not add %s to temporary index", name);
        }
@@ -2732,15 +2745,7 @@ static void remove_file(struct patch *patch, int rmdir_empty)
                                warning("unable to remove submodule %s",
                                        patch->old_name);
                } else if (!unlink(patch->old_name) && rmdir_empty) {
-                       char *name = xstrdup(patch->old_name);
-                       char *end = strrchr(name, '/');
-                       while (end) {
-                               *end = 0;
-                               if (rmdir(name))
-                                       break;
-                               end = strrchr(name, '/');
-                       }
-                       free(name);
+                       remove_path(patch->old_name);
                }
        }
 }
@@ -2845,8 +2850,8 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
                unsigned int nr = getpid();
 
                for (;;) {
-                       const char *newpath;
-                       newpath = mkpath("%s~%u", path, nr);
+                       char newpath[PATH_MAX];
+                       mksnpath(newpath, sizeof(newpath), "%s~%u", path, nr);
                        if (!try_create_file(newpath, mode, buf, size)) {
                                if (!rename(newpath, path))
                                        return;