]> git.neil.brown.name Git - wiggle.git/commitdiff
Improve parsing of diff3 output.
authorNeil Brown <neilb@suse.de>
Wed, 24 Mar 2010 07:53:02 +0000 (18:53 +1100)
committerNeil Brown <neilb@suse.de>
Wed, 24 Mar 2010 07:53:02 +0000 (18:53 +1100)
When diff3 discovers the the 1st and 3rd files match, but differ from
the 2nd it reports:

<<<<<<<
content from second file
=======
content from 1st and 3rd file
>>>>>>>

without a ||||||| line at all.

Enhance the extract code to recognise this.

Signed-off-by: NeilBrown <neilb@suse.de>
extract.c

index 2a991e035980fa4a41e4e31a73397e3a0e1e35ee..08917a212b23bdd4053a61277540c2fdc88750d5 100644 (file)
--- a/extract.c
+++ b/extract.c
@@ -219,6 +219,8 @@ int split_merge(struct stream f, struct stream *f1, struct stream *f2, struct st
                 *  1 in file 1 of conflict
                 *  2 in file 2 of conflict
                 *  3 in file 3 of conflict
+                *  4 in file 2 but expecting 1/3 next
+                *  5 in file 1/3
                 */
                int len = end-cp;
                lineno++;
@@ -228,8 +230,35 @@ int split_merge(struct stream f, struct stream *f1, struct stream *f2, struct st
                            strncmp(cp, "<<<<<<<", 7)==0 &&
                            (cp[7] == ' ' || cp[7] == '\n')
                                ) {
+                               char *peek;
                                state = 1;
                                skip_eol(&cp, end);
+                               /* diff3 will do something a bit strange in
+                                * the 1st and 3rd sections are the same.
+                                * it reports
+                                * <<<<<<<
+                                * 2nd
+                                * =======
+                                * 1st and 3rd
+                                * >>>>>>>
+                                * Without a ||||||| at all.
+                                * so to know if we are in '1' or '2', skip forward
+                                * having a peek.
+                                */
+                               peek = cp;
+                               while (peek < end) {
+                                       if (end-peek >= 8 &&
+                                           (peek[7] == ' ' || peek[7] == '\n')) {
+                                               if (strncmp(peek, "|||||||", 7) == 0 ||
+                                                   strncmp(peek, ">>>>>>>", 7) == 0)
+                                                       break;
+                                               else if (strncmp(peek, "=======", 7) == 0) {
+                                                       state = 4;
+                                                       break;
+                                               }
+                                       }
+                                       skip_eol(&peek, end);
+                               }
                        } else {
                                char *cp2= cp;
                                copyline(&r1, &cp2, end);
@@ -268,6 +297,29 @@ int split_merge(struct stream f, struct stream *f1, struct stream *f2, struct st
                        } else
                                copyline(&r3, &cp, end);
                        break;
+               case 4:
+                       if (len>=8 &&
+                           strncmp(cp, "=======", 7)==0 &&
+                           (cp[7] == ' ' || cp[7] == '\n')
+                               ) {
+                               state = 5;
+                               skip_eol(&cp, end);
+                       } else
+                               copyline(&r2, &cp, end);
+                       break;
+               case 5:
+                       if (len>=8 &&
+                           strncmp(cp, ">>>>>>>", 7)==0 &&
+                           (cp[7] == ' ' || cp[7] == '\n')
+                               ) {
+                               state = 0;
+                               skip_eol(&cp, end);
+                       } else {
+                               char *t = cp;
+                               copyline(&r1, &t, end);
+                               copyline(&r3, &cp, end);
+                       }
+                       break;
                }
        }
        *f1 = r1;