Code

git-checkout: Test for relative path use.
[git.git] / builtin-apply.c
index fec96a8d9d24cafe492a8dbe40bdb470244ea9f5..8411b38c7963852bffeb6dea1494399e8c9daa02 100644 (file)
@@ -41,7 +41,7 @@ static int apply_in_reverse;
 static int apply_with_reject;
 static int apply_verbosely;
 static int no_add;
-static int show_index_info;
+static const char *fake_ancestor;
 static int line_termination = '\n';
 static unsigned long p_context = ULONG_MAX;
 static const char apply_usage[] =
@@ -152,7 +152,7 @@ struct patch {
        unsigned int is_rename:1;
        struct fragment *fragments;
        char *result;
-       unsigned long resultsize;
+       size_t resultsize;
        char old_sha1_prefix[41];
        char new_sha1_prefix[41];
        struct patch *next;
@@ -178,12 +178,9 @@ static void say_patch_name(FILE *output, const char *pre, struct patch *patch, c
 #define CHUNKSIZE (8192)
 #define SLOP (16)
 
-static void *read_patch_file(int fd, size_t *sizep)
+static void read_patch_file(struct strbuf *sb, int fd)
 {
-       struct strbuf buf;
-
-       strbuf_init(&buf, 0);
-       if (strbuf_read(&buf, fd, 0) < 0)
+       if (strbuf_read(sb, fd, 0) < 0)
                die("git-apply: read returned %s", strerror(errno));
 
        /*
@@ -191,9 +188,8 @@ static void *read_patch_file(int fd, size_t *sizep)
         * so that we can do speculative "memcmp" etc, and
         * see to it that it is NUL-filled.
         */
-       strbuf_grow(&buf, SLOP);
-       memset(buf.buf + buf.len, 0, SLOP);
-       return strbuf_detach(&buf, sizep);
+       strbuf_grow(sb, SLOP);
+       memset(sb->buf + sb->len, 0, SLOP);
 }
 
 static unsigned long linelen(const char *buffer, unsigned long size)
@@ -2146,9 +2142,12 @@ static int get_current_sha1(const char *path, unsigned char *sha1)
        return 0;
 }
 
-static void show_index_list(struct patch *list)
+/* Build an index that contains the just the files needed for a 3way merge */
+static void build_fake_ancestor(struct patch *list, const char *filename)
 {
        struct patch *patch;
+       struct index_state result = { 0 };
+       int fd;
 
        /* Once we start supporting the reverse patch, it may be
         * worth showing the new sha1 prefix, but until then...
@@ -2156,11 +2155,12 @@ static void show_index_list(struct patch *list)
        for (patch = list; patch; patch = patch->next) {
                const unsigned char *sha1_ptr;
                unsigned char sha1[20];
+               struct cache_entry *ce;
                const char *name;
 
                name = patch->old_name ? patch->old_name : patch->new_name;
                if (0 < patch->is_new)
-                       sha1_ptr = null_sha1;
+                       continue;
                else if (get_sha1(patch->old_sha1_prefix, sha1))
                        /* git diff has no index line for mode/type changes */
                        if (!patch->lines_added && !patch->lines_deleted) {
@@ -2175,13 +2175,16 @@ static void show_index_list(struct patch *list)
                else
                        sha1_ptr = sha1;
 
-               printf("%06o %s ",patch->old_mode, sha1_to_hex(sha1_ptr));
-               if (line_termination && quote_c_style(name, NULL, NULL, 0))
-                       quote_c_style(name, NULL, stdout, 0);
-               else
-                       fputs(name, stdout);
-               putchar(line_termination);
+               ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
+               if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
+                       die ("Could not add %s to temporary index", name);
        }
+
+       fd = open(filename, O_WRONLY | O_CREAT, 0666);
+       if (fd < 0 || write_index(&result, fd) || close(fd))
+               die ("Could not write temporary index to %s", filename);
+
+       discard_index(&result);
 }
 
 static void stat_patch_list(struct patch *patch)
@@ -2633,22 +2636,22 @@ static void prefix_patches(struct patch *p)
 
 static int apply_patch(int fd, const char *filename, int inaccurate_eof)
 {
-       unsigned long offset, size;
-       char *buffer = read_patch_file(fd, &size);
+       size_t offset;
+       struct strbuf buf;
        struct patch *list = NULL, **listp = &list;
        int skipped_patch = 0;
 
+       strbuf_init(&buf, 0);
        patch_input_file = filename;
-       if (!buffer)
-               return -1;
+       read_patch_file(&buf, fd);
        offset = 0;
-       while (size > 0) {
+       while (offset < buf.len) {
                struct patch *patch;
                int nr;
 
                patch = xcalloc(1, sizeof(*patch));
                patch->inaccurate_eof = inaccurate_eof;
-               nr = parse_chunk(buffer + offset, size, patch);
+               nr = parse_chunk(buf.buf + offset, buf.len - offset, patch);
                if (nr < 0)
                        break;
                if (apply_in_reverse)
@@ -2666,7 +2669,6 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
                        skipped_patch++;
                }
                offset += nr;
-               size -= nr;
        }
 
        if (whitespace_error && (new_whitespace == error_on_whitespace))
@@ -2689,8 +2691,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
        if (apply && write_out_results(list, skipped_patch))
                exit(1);
 
-       if (show_index_info)
-               show_index_list(list);
+       if (fake_ancestor)
+               build_fake_ancestor(list, fake_ancestor);
 
        if (diffstat)
                stat_patch_list(list);
@@ -2701,7 +2703,7 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
        if (summary)
                summary_patch_list(list);
 
-       free(buffer);
+       strbuf_release(&buf);
        return 0;
 }
 
@@ -2798,9 +2800,11 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
                        apply = 1;
                        continue;
                }
-               if (!strcmp(arg, "--index-info")) {
+               if (!strcmp(arg, "--build-fake-ancestor")) {
                        apply = 0;
-                       show_index_info = 1;
+                       if (++i >= argc)
+                               die ("need a filename");
+                       fake_ancestor = argv[i];
                        continue;
                }
                if (!strcmp(arg, "-z")) {