git-apply --reject: send rejects to .rej files.
authorJunio C Hamano <junkio@cox.net>
Fri, 18 Aug 2006 10:10:19 +0000 (03:10 -0700)
committerJunio C Hamano <junkio@cox.net>
Fri, 18 Aug 2006 10:10:19 +0000 (03:10 -0700)
... just like everybody else does, instead of sending it to the standard
output, which was just silly.

Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-apply.c
t/t4117-apply-reject.sh

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;
index 3362819c3a21a731d2fe0b53128cb2cb1d51ea90..1cf9a2e7a7a0fe4cea4b68ab4792ac26b3247bb5 100755 (executable)
@@ -23,6 +23,12 @@ test_expect_success setup '
                echo $i
        done >file1 &&
        git diff >patch.1 &&
+       cat file1 >clean &&
+
+       for i in 1 E 2 3 4 5 6 7 8 9 10 11 12 C 13 14 15 16 17 18 19 20 F 21
+       do
+               echo $i
+       done >expected &&
 
        mv file1 file2 &&
        git update-index --add --remove file1 file2 &&
@@ -53,25 +59,30 @@ test_expect_success 'apply without --reject should fail' '
 
 test_expect_success 'apply with --reject should fail but update the file' '
 
-       cat saved.file1 >file1
+       cat saved.file1 >file1 &&
+       rm -f file1.rej file2.rej &&
 
-       if git apply --reject patch.1 >rejects
+       if git apply --reject patch.1
        then
                echo "succeeds with --reject?"
                exit 1
        fi
-       cat rejects
-       for i in 1 E 2 3 4 5 6 7 8 9 10 11 12 C 13 14 15 16 17 18 19 20 F 21
-       do
-               echo $i
-       done >expected.file1 &&
 
-       diff -u file1 expected.file1
+       diff -u file1 expected &&
+
+       cat file1.rej &&
+
+       if test -f file2.rej
+       then
+               echo "file2 should not have been touched"
+               exit 1
+       fi
 '
 
 test_expect_success 'apply with --reject should fail but update the file' '
 
-       cat saved.file1 >file1
+       cat saved.file1 >file1 &&
+       rm -f file1.rej file2.rej file2 &&
 
        if git apply --reject patch.2 >rejects
        then
@@ -79,18 +90,20 @@ test_expect_success 'apply with --reject should fail but update the file' '
                exit 1
        fi
 
-       cat rejects
-
-       for i in 1 E 2 3 4 5 6 7 8 9 10 11 12 C 13 14 15 16 17 18 19 20 F 21
-       do
-               echo $i
-       done >expected.file2 &&
-
        test -f file1 && {
                echo "file1 still exists?"
                exit 1
        }
-       diff -u file2 expected.file2
+       diff -u file2 expected &&
+
+       cat file2.rej &&
+
+       if test -f file1.rej
+       then
+               echo "file2 should not have been touched"
+               exit 1
+       fi
+
 '
 
 test_done