git-apply --reject: send rejects to .rej files.
[gitweb.git] / builtin-apply.c
index 7dea913836d08ae3eb394b1fd73b9c92002f6cc7..668be9ce65caf4e284070f4a92a32e6b194fa284 100644 (file)
@@ -2242,36 +2242,61 @@ static void write_out_one_result(struct patch *patch, int phase)
 
 static int write_out_one_reject(struct patch *patch)
 {
+       FILE *rej;
+       char namebuf[PATH_MAX];
        struct fragment *frag;
-       int rejects = 0;
+       int cnt = 0;
 
-       for (rejects = 0, frag = patch->fragments; frag; frag = frag->next) {
+       for (cnt = 0, frag = patch->fragments; frag; frag = frag->next) {
                if (!frag->rejected)
                        continue;
-               if (rejects == 0) {
-                       rejects = 1;
-                       printf("** Rejected hunk(s) for ");
-                       if (patch->old_name && patch->new_name &&
-                           strcmp(patch->old_name, patch->new_name)) {
-                               write_name_quoted(NULL, 0,
-                                                 patch->old_name, 1, stdout);
-                               fputs(" => ", stdout);
-                               write_name_quoted(NULL, 0,
-                                                 patch->new_name, 1, stdout);
-                       }
-                       else {
-                               const char *n = patch->new_name;
-                               if (!n)
-                                       n = patch->old_name;
-                               write_name_quoted(NULL, 0, n, 1, stdout);
-                       }
-                       printf(" **\n");
+               cnt++;
+       }
+
+       if (!cnt)
+               return 0;
+
+       /* This should not happen, because a removal patch that leaves
+        * contents are marked "rejected" at the patch level.
+        */
+       if (!patch->new_name)
+               die("internal error");
+
+       cnt = strlen(patch->new_name);
+       if (ARRAY_SIZE(namebuf) <= cnt + 5) {
+               cnt = ARRAY_SIZE(namebuf) - 5;
+               fprintf(stderr,
+                       "warning: truncating .rej filename to %.*s.rej",
+                       cnt - 1, patch->new_name);
+       }
+       memcpy(namebuf, patch->new_name, cnt);
+       memcpy(namebuf + cnt, ".rej", 5);
+
+       rej = fopen(namebuf, "w");
+       if (!rej)
+               return error("cannot open %s: %s", namebuf, strerror(errno));
+
+       /* Normal git tools never deal with .rej, so do not pretend
+        * this is a git patch by saying --git nor give extended
+        * headers.  While at it, maybe please "kompare" that wants
+        * the trailing TAB and some garbage at the end of line ;-).
+        */
+       fprintf(rej, "diff a/%s b/%s\t(rejected hunks)\n",
+               patch->new_name, patch->new_name);
+       for (cnt = 0, frag = patch->fragments;
+            frag;
+            cnt++, frag = frag->next) {
+               if (!frag->rejected) {
+                       fprintf(stderr, "Hunk #%d applied cleanly.\n", cnt);
+                       continue;
                }
-               printf("%.*s", frag->size, frag->patch);
+               fprintf(stderr, "Rejected hunk #%d.\n", cnt);
+               fprintf(rej, "%.*s", frag->size, frag->patch);
                if (frag->patch[frag->size-1] != '\n')
-                       putchar('\n');
+                       fputc('\n', rej);
        }
-       return rejects;
+       fclose(rej);
+       return -1;
 }
 
 static int write_out_results(struct patch *list, int skipped_patch)
@@ -2288,16 +2313,9 @@ static int write_out_results(struct patch *list, int skipped_patch)
                while (l) {
                        if (l->rejected)
                                errs = 1;
-                       else
+                       else {
                                write_out_one_result(l, phase);
-                       l = l->next;
-               }
-       }
-       if (apply_with_reject) {
-               l = list;
-               while (l) {
-                       if (!l->rejected) {
-                               if (write_out_one_reject(l))
+                               if (phase == 1 && write_out_one_reject(l))
                                        errs = 1;
                        }
                        l = l->next;