Merge with http://members.cox.net/junkio/git-jc.git
[git.git] / diff-tree-helper.c
index bcf89a5..51bb658 100644 (file)
@@ -1,11 +1,12 @@
 /*
  * Copyright (C) 2005 Junio C Hamano
  */
+#include <limits.h>
 #include "cache.h"
 #include "strbuf.h"
 #include "diff.h"
 
-static int matches_pathspec(const char *name, char **spec, int cnt)
+static int matches_pathspec(const char *name, const char **spec, int cnt)
 {
        int i;
        int namelen = strlen(name);
@@ -35,7 +36,7 @@ static int parse_oneside_change(const char *cp, struct diff_spec *one,
        if (strncmp(cp, "\tblob\t", 6))
                return -1;
        cp += 6;
-       if (get_sha1_hex(cp, one->u.sha1))
+       if (get_sha1_hex(cp, one->blob_sha1))
                return -1;
        cp += 40;
        if (*cp++ != '\t')
@@ -45,72 +46,82 @@ static int parse_oneside_change(const char *cp, struct diff_spec *one,
 }
 
 static int parse_diff_tree_output(const char *buf,
-                                 struct diff_spec *old,
-                                 struct diff_spec *new,
-                                 char *path) {
+                                 const char **spec, int cnt, int reverse)
+{
+       struct diff_spec old, new;
+       char path[PATH_MAX];
        const char *cp = buf;
        int ch;
 
        switch (*cp++) {
+       case 'U':
+               if (!cnt || matches_pathspec(cp + 1, spec, cnt))
+                       diff_unmerge(cp + 1);
+               return 0;
        case '+':
-               old->file_valid = 0;
-               return parse_oneside_change(cp, new, path);
+               old.file_valid = 0;
+               parse_oneside_change(cp, &new, path);
+               break;
        case '-':
-               new->file_valid = 0;
-               return parse_oneside_change(cp, old, path);
+               new.file_valid = 0;
+               parse_oneside_change(cp, &old, path);
+               break;
        case '*':
+               old.file_valid = old.sha1_valid =
+                       new.file_valid = new.sha1_valid = 1;
+               old.mode = new.mode = 0;
+               while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
+                       old.mode = (old.mode << 3) | (ch - '0');
+                       cp++;
+               }
+               if (strncmp(cp, "->", 2))
+                       return -1;
+               cp += 2;
+               while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
+                       new.mode = (new.mode << 3) | (ch - '0');
+                       cp++;
+               }
+               if (strncmp(cp, "\tblob\t", 6))
+                       return -1;
+               cp += 6;
+               if (get_sha1_hex(cp, old.blob_sha1))
+                       return -1;
+               cp += 40;
+               if (strncmp(cp, "->", 2))
+                       return -1;
+               cp += 2;
+               if (get_sha1_hex(cp, new.blob_sha1))
+                       return -1;
+               cp += 40;
+               if (*cp++ != '\t')
+                       return -1;
+               strcpy(path, cp);
                break;
        default:
                return -1;
        }
-       
-       /* This is for '*' entries */
-       old->file_valid = old->sha1_valid = 1;
-       new->file_valid = new->sha1_valid = 1;
-
-       old->mode = new->mode = 0;
-       while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
-               old->mode = (old->mode << 3) | (ch - '0');
-               cp++;
-       }
-       if (strncmp(cp, "->", 2))
-               return -1;
-       cp += 2;
-       while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
-               new->mode = (new->mode << 3) | (ch - '0');
-               cp++;
+       if (!cnt || matches_pathspec(path, spec, cnt)) {
+               if (reverse)
+                       run_external_diff(path, &new, &old);
+               else
+                       run_external_diff(path, &old, &new);
        }
-       if (strncmp(cp, "\tblob\t", 6))
-               return -1;
-       cp += 6;
-       if (get_sha1_hex(cp, old->u.sha1))
-               return -1;
-       cp += 40;
-       if (strncmp(cp, "->", 2))
-               return -1;
-       cp += 2;
-       if (get_sha1_hex(cp, new->u.sha1))
-               return -1;
-       cp += 40;
-       if (*cp++ != '\t')
-               return -1;
-       strcpy(path, cp);
        return 0;
 }
 
 static const char *diff_tree_helper_usage =
 "diff-tree-helper [-R] [-z] paths...";
 
-int main(int ac, char **av) {
+int main(int ac, const char **av) {
        struct strbuf sb;
-       int reverse_diff = 0;
+       int reverse = 0;
        int line_termination = '\n';
 
        strbuf_init(&sb);
 
        while (1 < ac && av[1][0] == '-') {
                if (av[1][1] == 'R')
-                       reverse_diff = 1;
+                       reverse = 1;
                else if (av[1][1] == 'z')
                        line_termination = 0;
                else
@@ -120,19 +131,13 @@ int main(int ac, char **av) {
        /* the remaining parameters are paths patterns */
 
        while (1) {
-               struct diff_spec old, new;
-               char path[PATH_MAX];
+               int status;
                read_line(&sb, stdin, line_termination);
                if (sb.eof)
                        break;
-               if (parse_diff_tree_output(sb.buf, &old, &new, path)) { 
+               status = parse_diff_tree_output(sb.buf, av+1, ac-1, reverse);
+               if (status)
                        fprintf(stderr, "cannot parse %s\n", sb.buf);
-                       continue;
-               }
-               if (1 < ac && !matches_pathspec(path, av+1, ac-1))
-                       continue;
-
-               run_external_diff(path, &old, &new);
        }
        return 0;
 }