diff-helper.con commit [PATCH] diff overhaul (57fe64a)
   1/*
   2 * Copyright (C) 2005 Junio C Hamano
   3 */
   4#include <limits.h>
   5#include "cache.h"
   6#include "strbuf.h"
   7#include "diff.h"
   8
   9static int detect_rename = 0;
  10static int diff_score_opt = 0;
  11
  12static int parse_oneside_change(const char *cp, int *mode,
  13                                unsigned char *sha1, char *path)
  14{
  15        int ch, m;
  16
  17        m = 0;
  18        while ((ch = *cp) && '0' <= ch && ch <= '7') {
  19                m = (m << 3) | (ch - '0');
  20                cp++;
  21        }
  22        *mode = m;
  23        if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6))
  24                return -1;
  25        cp += 6;
  26        if (get_sha1_hex(cp, sha1))
  27                return -1;
  28        cp += 40;
  29        if ((*cp != '\t') && *cp != ' ')
  30                return -1;
  31        strcpy(path, ++cp);
  32        return 0;
  33}
  34
  35static int parse_diff_raw_output(const char *buf)
  36{
  37        char path[PATH_MAX];
  38        unsigned char old_sha1[20], new_sha1[20];
  39        const char *cp = buf;
  40        int ch, old_mode, new_mode;
  41
  42        switch (*cp++) {
  43        case 'U':
  44                diff_unmerge(cp + 1);
  45                break;
  46        case '+':
  47                parse_oneside_change(cp, &new_mode, new_sha1, path);
  48                diff_addremove('+', new_mode, new_sha1, path, NULL);
  49                break;
  50        case '-':
  51                parse_oneside_change(cp, &old_mode, old_sha1, path);
  52                diff_addremove('-', old_mode, old_sha1, path, NULL);
  53                break;
  54        case '*':
  55                old_mode = new_mode = 0;
  56                while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  57                        old_mode = (old_mode << 3) | (ch - '0');
  58                        cp++;
  59                }
  60                if (strncmp(cp, "->", 2))
  61                        return -1;
  62                cp += 2;
  63                while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  64                        new_mode = (new_mode << 3) | (ch - '0');
  65                        cp++;
  66                }
  67                if (strncmp(cp, "\tblob\t", 6) && strncmp(cp, " blob ", 6))
  68                        return -1;
  69                cp += 6;
  70                if (get_sha1_hex(cp, old_sha1))
  71                        return -1;
  72                cp += 40;
  73                if (strncmp(cp, "->", 2))
  74                        return -1;
  75                cp += 2;
  76                if (get_sha1_hex(cp, new_sha1))
  77                        return -1;
  78                cp += 40;
  79                if ((*cp != '\t') && *cp != ' ')
  80                        return -1;
  81                strcpy(path, ++cp);
  82                diff_change(old_mode, new_mode, old_sha1, new_sha1, path, 0);
  83                break;
  84        default:
  85                return -1;
  86        }
  87        return 0;
  88}
  89
  90static const char *diff_helper_usage =
  91        "git-diff-helper [-z] [-R] [-M] paths...";
  92
  93int main(int ac, const char **av) {
  94        struct strbuf sb;
  95        int reverse = 0;
  96        int line_termination = '\n';
  97
  98        strbuf_init(&sb);
  99
 100        while (1 < ac && av[1][0] == '-') {
 101                if (av[1][1] == 'R')
 102                        reverse = 1;
 103                else if (av[1][1] == 'z')
 104                        line_termination = 0;
 105                else if (av[1][1] == 'M') {
 106                        detect_rename = 1;
 107                        diff_score_opt = diff_scoreopt_parse(av[1]);
 108                }
 109                else
 110                        usage(diff_helper_usage);
 111                ac--; av++;
 112        }
 113        /* the remaining parameters are paths patterns */
 114
 115        diff_setup(detect_rename, diff_score_opt, reverse, -1, av+1, ac-1);
 116
 117        while (1) {
 118                int status;
 119                read_line(&sb, stdin, line_termination);
 120                if (sb.eof)
 121                        break;
 122                status = parse_diff_raw_output(sb.buf);
 123                if (status) {
 124                        diff_flush();
 125                        printf("%s%c", sb.buf, line_termination);
 126                }
 127        }
 128
 129        diff_flush();
 130        return 0;
 131}