6456405b53bc9ff419e1133aa4da816fe761d911
   1/*
   2 * Copyright (C) 2005 Junio C Hamano
   3 */
   4#include "cache.h"
   5#include "strbuf.h"
   6#include "diff.h"
   7
   8static const char *pickaxe = NULL;
   9static int pickaxe_opts = 0;
  10static int line_termination = '\n';
  11static int inter_name_termination = '\t';
  12
  13static const char *diff_helper_usage =
  14        "git-diff-helper [-z] [-S<string>] paths...";
  15
  16int main(int ac, const char **av) {
  17        struct strbuf sb;
  18
  19        strbuf_init(&sb);
  20
  21        while (1 < ac && av[1][0] == '-') {
  22                if (av[1][1] == 'z')
  23                        line_termination = inter_name_termination = 0;
  24                else if (av[1][1] == 'S') {
  25                        pickaxe = av[1] + 2;
  26                }
  27                else if (!strcmp(av[1], "--pickaxe-all"))
  28                        pickaxe_opts = DIFF_PICKAXE_ALL;
  29                else
  30                        usage(diff_helper_usage);
  31                ac--; av++;
  32        }
  33        /* the remaining parameters are paths patterns */
  34
  35        diff_setup(0);
  36        while (1) {
  37                unsigned old_mode, new_mode;
  38                unsigned char old_sha1[20], new_sha1[20];
  39                char old_path[PATH_MAX];
  40                int status, score, two_paths;
  41                char new_path[PATH_MAX];
  42
  43                int ch;
  44                char *cp, *ep;
  45
  46                read_line(&sb, stdin, line_termination);
  47                if (sb.eof)
  48                        break;
  49                switch (sb.buf[0]) {
  50                case ':':
  51                        /* parse the first part up to the status */
  52                        cp = sb.buf + 1;
  53                        old_mode = new_mode = 0;
  54                        while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  55                                old_mode = (old_mode << 3) | (ch - '0');
  56                                cp++;
  57                        }
  58                        if (*cp++ != ' ')
  59                                break;
  60                        while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  61                                new_mode = (new_mode << 3) | (ch - '0');
  62                                cp++;
  63                        }
  64                        if (*cp++ != ' ')
  65                                break;
  66                        if (get_sha1_hex(cp, old_sha1))
  67                                break;
  68                        cp += 40;
  69                        if (*cp++ != ' ')
  70                                break;
  71                        if (get_sha1_hex(cp, new_sha1))
  72                                break;
  73                        cp += 40;
  74                        if (*cp++ != ' ')
  75                                break;
  76                        status = *cp++;
  77                        if (!strchr("MCRNDU", status))
  78                                break;
  79                        two_paths = score = 0;
  80                        if (status == 'R' || status == 'C') {
  81                                two_paths = 1;
  82                                sscanf(cp, "%d", &score);
  83                                if (line_termination) {
  84                                        cp = strchr(cp,
  85                                                    inter_name_termination);
  86                                        if (!cp)
  87                                                break;
  88                                }
  89                        }
  90
  91                        if (*cp++ != inter_name_termination)
  92                                break;
  93
  94                        /* first pathname */
  95                        if (!line_termination) {
  96                                read_line(&sb, stdin, line_termination);
  97                                if (sb.eof)
  98                                        break;
  99                                strcpy(old_path, sb.buf);
 100                        }
 101                        else if (!two_paths)
 102                                strcpy(old_path, cp);
 103                        else {
 104                                ep = strchr(cp, inter_name_termination);
 105                                if (!ep)
 106                                        break;
 107                                strncpy(old_path, cp, ep-cp);
 108                                old_path[ep-cp] = 0;
 109                                cp = ep + 1;
 110                        }
 111
 112                        /* second pathname */
 113                        if (!two_paths)
 114                                strcpy(new_path, old_path);
 115                        else {
 116                                if (!line_termination) {
 117                                        read_line(&sb, stdin,
 118                                                  line_termination);
 119                                        if (sb.eof)
 120                                                break;
 121                                        strcpy(new_path, sb.buf);
 122                                }
 123                                else
 124                                        strcpy(new_path, cp);
 125                        }
 126                        diff_helper_input(old_mode, new_mode,
 127                                          old_sha1, new_sha1,
 128                                          old_path, status, score,
 129                                          new_path);
 130                        continue;
 131                }
 132                if (1 < ac)
 133                        diffcore_pathspec(av + 1);
 134                if (pickaxe)
 135                        diffcore_pickaxe(pickaxe, pickaxe_opts);
 136                diff_flush(DIFF_FORMAT_PATCH, 0);
 137                printf("%s\n", sb.buf);
 138        }
 139        if (1 < ac)
 140                diffcore_pathspec(av + 1);
 141        if (pickaxe)
 142                diffcore_pickaxe(pickaxe, pickaxe_opts);
 143        diff_flush(DIFF_FORMAT_PATCH, 0);
 144        return 0;
 145}