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