diff-helper.con commit Cleanup the x-allocation functions (127cfd0)
   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 matches_pathspec(const char *name, const char **spec, int cnt)
  10{
  11        int i;
  12        int namelen = strlen(name);
  13        for (i = 0; i < cnt; i++) {
  14                int speclen = strlen(spec[i]);
  15                if (! strncmp(spec[i], name, speclen) &&
  16                    speclen <= namelen &&
  17                    (name[speclen] == 0 ||
  18                     name[speclen] == '/'))
  19                        return 1;
  20        }
  21        return 0;
  22}
  23
  24static int parse_oneside_change(const char *cp, struct diff_spec *one,
  25                                char *path)
  26{
  27        int ch;
  28
  29        one->file_valid = one->sha1_valid = 1;
  30        one->mode = 0;
  31        while ((ch = *cp) && '0' <= ch && ch <= '7') {
  32                one->mode = (one->mode << 3) | (ch - '0');
  33                cp++;
  34        }
  35
  36        if (strncmp(cp, "\tblob\t", 6))
  37                return -1;
  38        cp += 6;
  39        if (get_sha1_hex(cp, one->blob_sha1))
  40                return -1;
  41        cp += 40;
  42        if (*cp++ != '\t')
  43                return -1;
  44        strcpy(path, cp);
  45        return 0;
  46}
  47
  48static int parse_diff_raw_output(const char *buf,
  49                                 const char **spec, int cnt, int reverse)
  50{
  51        struct diff_spec old, new;
  52        char path[PATH_MAX];
  53        const char *cp = buf;
  54        int ch;
  55
  56        switch (*cp++) {
  57        case 'U':
  58                if (!cnt || matches_pathspec(cp + 1, spec, cnt))
  59                        diff_unmerge(cp + 1);
  60                return 0;
  61        case '+':
  62                old.file_valid = 0;
  63                parse_oneside_change(cp, &new, path);
  64                break;
  65        case '-':
  66                new.file_valid = 0;
  67                parse_oneside_change(cp, &old, path);
  68                break;
  69        case '*':
  70                old.file_valid = old.sha1_valid =
  71                        new.file_valid = new.sha1_valid = 1;
  72                old.mode = new.mode = 0;
  73                while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  74                        old.mode = (old.mode << 3) | (ch - '0');
  75                        cp++;
  76                }
  77                if (strncmp(cp, "->", 2))
  78                        return -1;
  79                cp += 2;
  80                while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  81                        new.mode = (new.mode << 3) | (ch - '0');
  82                        cp++;
  83                }
  84                if (strncmp(cp, "\tblob\t", 6))
  85                        return -1;
  86                cp += 6;
  87                if (get_sha1_hex(cp, old.blob_sha1))
  88                        return -1;
  89                cp += 40;
  90                if (strncmp(cp, "->", 2))
  91                        return -1;
  92                cp += 2;
  93                if (get_sha1_hex(cp, new.blob_sha1))
  94                        return -1;
  95                cp += 40;
  96                if (*cp++ != '\t')
  97                        return -1;
  98                strcpy(path, cp);
  99                break;
 100        default:
 101                return -1;
 102        }
 103        if (!cnt || matches_pathspec(path, spec, cnt)) {
 104                if (reverse)
 105                        run_external_diff(path, &new, &old);
 106                else
 107                        run_external_diff(path, &old, &new);
 108        }
 109        return 0;
 110}
 111
 112static const char *diff_helper_usage =
 113"git-diff-helper [-R] [-z] paths...";
 114
 115int main(int ac, const char **av) {
 116        struct strbuf sb;
 117        int reverse = 0;
 118        int line_termination = '\n';
 119
 120        strbuf_init(&sb);
 121
 122        while (1 < ac && av[1][0] == '-') {
 123                if (av[1][1] == 'R')
 124                        reverse = 1;
 125                else if (av[1][1] == 'z')
 126                        line_termination = 0;
 127                else
 128                        usage(diff_helper_usage);
 129                ac--; av++;
 130        }
 131        /* the remaining parameters are paths patterns */
 132
 133        while (1) {
 134                int status;
 135                read_line(&sb, stdin, line_termination);
 136                if (sb.eof)
 137                        break;
 138                status = parse_diff_raw_output(sb.buf, av+1, ac-1, reverse);
 139                if (status)
 140                        fprintf(stderr, "cannot parse %s\n", sb.buf);
 141        }
 142        return 0;
 143}