diff-tree-helper.con commit fsck-cache: sort entries by inode number (7e8c174)
   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,
  48                                  const char **spec, int cnt, int reverse)
  49{
  50        struct diff_spec old, new;
  51        char path[PATH_MAX];
  52        const char *cp = buf;
  53        int ch;
  54
  55        switch (*cp++) {
  56        case 'U':
  57                if (!cnt || matches_pathspec(cp + 1, spec, cnt))
  58                        diff_unmerge(cp + 1);
  59                return 0;
  60        case '+':
  61                old.file_valid = 0;
  62                parse_oneside_change(cp, &new, path);
  63                break;
  64        case '-':
  65                new.file_valid = 0;
  66                parse_oneside_change(cp, &old, path);
  67                break;
  68        case '*':
  69                old.file_valid = old.sha1_valid =
  70                        new.file_valid = new.sha1_valid = 1;
  71                old.mode = new.mode = 0;
  72                while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  73                        old.mode = (old.mode << 3) | (ch - '0');
  74                        cp++;
  75                }
  76                if (strncmp(cp, "->", 2))
  77                        return -1;
  78                cp += 2;
  79                while ((ch = *cp) && ('0' <= ch && ch <= '7')) {
  80                        new.mode = (new.mode << 3) | (ch - '0');
  81                        cp++;
  82                }
  83                if (strncmp(cp, "\tblob\t", 6))
  84                        return -1;
  85                cp += 6;
  86                if (get_sha1_hex(cp, old.u.sha1))
  87                        return -1;
  88                cp += 40;
  89                if (strncmp(cp, "->", 2))
  90                        return -1;
  91                cp += 2;
  92                if (get_sha1_hex(cp, new.u.sha1))
  93                        return -1;
  94                cp += 40;
  95                if (*cp++ != '\t')
  96                        return -1;
  97                strcpy(path, cp);
  98                break;
  99        default:
 100                return -1;
 101        }
 102        if (!cnt || matches_pathspec(path, spec, cnt)) {
 103                if (reverse)
 104                        run_external_diff(path, &new, &old);
 105                else
 106                        run_external_diff(path, &old, &new);
 107        }
 108        return 0;
 109}
 110
 111static const char *diff_tree_helper_usage =
 112"diff-tree-helper [-R] [-z] paths...";
 113
 114int main(int ac, const char **av) {
 115        struct strbuf sb;
 116        int reverse = 0;
 117        int line_termination = '\n';
 118
 119        strbuf_init(&sb);
 120
 121        while (1 < ac && av[1][0] == '-') {
 122                if (av[1][1] == 'R')
 123                        reverse = 1;
 124                else if (av[1][1] == 'z')
 125                        line_termination = 0;
 126                else
 127                        usage(diff_tree_helper_usage);
 128                ac--; av++;
 129        }
 130        /* the remaining parameters are paths patterns */
 131
 132        while (1) {
 133                int status;
 134                read_line(&sb, stdin, line_termination);
 135                if (sb.eof)
 136                        break;
 137                status = parse_diff_tree_output(sb.buf, av+1, ac-1, reverse);
 138                if (status)
 139                        fprintf(stderr, "cannot parse %s\n", sb.buf);
 140        }
 141        return 0;
 142}