3e798be303ded2218c2d2a2c8ca79c3b4c0fba6f
   1/*
   2 * GIT - The information manager from hell
   3 *
   4 * Copyright (C) Linus Torvalds, 2005
   5 */
   6#include "cache.h"
   7#include "diff.h"
   8
   9static const char *show_diff_usage = "show-diff [-q] [-s] [-z] [paths...]";
  10
  11static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt)
  12{
  13        int i;
  14        int namelen = ce_namelen(ce);
  15        for (i = 0; i < cnt; i++) {
  16                int speclen = strlen(spec[i]);
  17                if (! strncmp(spec[i], ce->name, speclen) &&
  18                    speclen <= namelen &&
  19                    (ce->name[speclen] == 0 ||
  20                     ce->name[speclen] == '/'))
  21                        return 1;
  22        }
  23        return 0;
  24}
  25
  26int main(int argc, char **argv)
  27{
  28        int silent = 0;
  29        int silent_on_nonexisting_files = 0;
  30        int machine_readable = 0;
  31        int reverse = 0;
  32        int entries = read_cache();
  33        int i;
  34
  35        while (1 < argc && argv[1][0] == '-') {
  36                if  (!strcmp(argv[1], "-R"))
  37                        reverse = 1;
  38                else if (!strcmp(argv[1], "-s"))
  39                        silent_on_nonexisting_files = silent = 1;
  40                else if (!strcmp(argv[1], "-q"))
  41                        silent_on_nonexisting_files = 1;
  42                else if (!strcmp(argv[1], "-z"))
  43                        machine_readable = 1;
  44                else
  45                        usage(show_diff_usage);
  46                argv++; argc--;
  47        }
  48
  49        /* At this point, if argc == 1, then we are doing everything.
  50         * Otherwise argv[1] .. argv[argc-1] have the explicit paths.
  51         */
  52        if (entries < 0) {
  53                perror("read_cache");
  54                exit(1);
  55        }
  56        prepare_diff_cmd();
  57        for (i = 0; i < entries; i++) {
  58                struct stat st;
  59                struct cache_entry *ce = active_cache[i];
  60                int changed;
  61                unsigned long size;
  62                char type[20];
  63                void *old;
  64
  65                if (1 < argc &&
  66                    ! matches_pathspec(ce, argv+1, argc-1))
  67                        continue;
  68
  69                if (ce_stage(ce)) {
  70                        if (machine_readable)
  71                                printf("U %s%c", ce->name, 0);
  72                        else
  73                                printf("%s: Unmerged\n",
  74                                       ce->name);
  75                        while (i < entries &&
  76                               !strcmp(ce->name, active_cache[i]->name))
  77                                i++;
  78                        i--; /* compensate for loop control increments */
  79                        continue;
  80                }
  81 
  82                if (stat(ce->name, &st) < 0) {
  83                        if (errno == ENOENT && silent_on_nonexisting_files)
  84                                continue;
  85                        if (machine_readable)
  86                                printf("X %s%c", ce->name, 0);
  87                        else {
  88                                printf("%s: %s\n", ce->name, strerror(errno));
  89                                if (errno == ENOENT)
  90                                        show_diff_empty(ce->sha1, ce->name,
  91                                                        reverse);
  92                        }
  93                        continue;
  94                }
  95                changed = cache_match_stat(ce, &st);
  96                if (!changed)
  97                        continue;
  98                if (!machine_readable)
  99                        printf("%s: %s\n", ce->name, sha1_to_hex(ce->sha1));
 100                else {
 101                        printf("%s %s%c", sha1_to_hex(ce->sha1), ce->name, 0);
 102                        continue;
 103                }
 104                if (silent)
 105                        continue;
 106
 107                old = read_sha1_file(ce->sha1, type, &size);
 108                if (! old)
 109                        error("unable to read blob object for %s (%s)",
 110                              ce->name, sha1_to_hex(ce->sha1));
 111                else
 112                        show_differences(ce->name, ce->name, old, size,
 113                                         reverse);
 114                free(old);
 115        }
 116        return 0;
 117}