diff-files.con commit [PATCH] Implement git-checkout-cache -u to update stat information in the cache. (415e96c)
   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 *diff_files_usage =
  10"diff-files [-p] [-q] [-r] [-z] [-M] [paths...]";
  11
  12static int generate_patch = 0;
  13static int line_termination = '\n';
  14static int detect_rename = 0;
  15static int silent = 0;
  16
  17static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt)
  18{
  19        int i;
  20        int namelen = ce_namelen(ce);
  21        for (i = 0; i < cnt; i++) {
  22                int speclen = strlen(spec[i]);
  23                if (! strncmp(spec[i], ce->name, speclen) &&
  24                    speclen <= namelen &&
  25                    (ce->name[speclen] == 0 ||
  26                     ce->name[speclen] == '/'))
  27                        return 1;
  28        }
  29        return 0;
  30}
  31
  32static void show_unmerge(const char *path)
  33{
  34        if (generate_patch)
  35                diff_unmerge(path);
  36        else
  37                printf("U %s%c", path, line_termination);
  38}
  39
  40static void show_file(int pfx, struct cache_entry *ce)
  41{
  42        if (generate_patch)
  43                diff_addremove(pfx, ntohl(ce->ce_mode), ce->sha1,
  44                               ce->name, NULL);
  45        else
  46                printf("%c%06o\t%s\t%s\t%s%c",
  47                       pfx, ntohl(ce->ce_mode), "blob",
  48                       sha1_to_hex(ce->sha1), ce->name, line_termination);
  49}
  50
  51static void show_modified(int oldmode, int mode,
  52                          const unsigned char *old_sha1, const unsigned char *sha1,
  53                          char *path)
  54{
  55        char old_sha1_hex[41];
  56        strcpy(old_sha1_hex, sha1_to_hex(old_sha1));
  57
  58        if (generate_patch)
  59                diff_change(oldmode, mode, old_sha1, sha1, path, NULL);
  60        else
  61                printf("*%06o->%06o\tblob\t%s->%s\t%s%c",
  62                       oldmode, mode, old_sha1_hex, sha1_to_hex(sha1), path,
  63                       line_termination);
  64}
  65
  66int main(int argc, char **argv)
  67{
  68        static const unsigned char null_sha1[20] = { 0, };
  69        int entries = read_cache();
  70        int i;
  71
  72        while (1 < argc && argv[1][0] == '-') {
  73                if (!strcmp(argv[1], "-p"))
  74                        generate_patch = 1;
  75                else if (!strcmp(argv[1], "-q"))
  76                        silent = 1;
  77                else if (!strcmp(argv[1], "-r"))
  78                        ; /* no-op */
  79                else if (!strcmp(argv[1], "-s"))
  80                        ; /* no-op */
  81                else if (!strcmp(argv[1], "-z"))
  82                        line_termination = 0;
  83                else if (!strcmp(argv[1], "-M")) {
  84                        detect_rename = generate_patch = 1;
  85                }
  86                else
  87                        usage(diff_files_usage);
  88                argv++; argc--;
  89        }
  90
  91        /* At this point, if argc == 1, then we are doing everything.
  92         * Otherwise argv[1] .. argv[argc-1] have the explicit paths.
  93         */
  94        if (entries < 0) {
  95                perror("read_cache");
  96                exit(1);
  97        }
  98
  99        if (generate_patch)
 100                diff_setup(detect_rename, 0, 0, 0, 0);          
 101
 102        for (i = 0; i < entries; i++) {
 103                struct stat st;
 104                unsigned int oldmode, mode;
 105                struct cache_entry *ce = active_cache[i];
 106                int changed;
 107
 108                if (1 < argc &&
 109                    ! matches_pathspec(ce, argv+1, argc-1))
 110                        continue;
 111
 112                if (ce_stage(ce)) {
 113                        show_unmerge(ce->name);
 114                        while (i < entries &&
 115                               !strcmp(ce->name, active_cache[i]->name))
 116                                i++;
 117                        i--; /* compensate for loop control increments */
 118                        continue;
 119                }
 120 
 121                if (lstat(ce->name, &st) < 0) {
 122                        if (errno != ENOENT) {
 123                                perror(ce->name);
 124                                continue;
 125                        }       
 126                        if (silent)
 127                                continue;
 128                        show_file('-', ce);
 129                        continue;
 130                }
 131                changed = ce_match_stat(ce, &st);
 132                if (!changed)
 133                        continue;
 134
 135                oldmode = ntohl(ce->ce_mode);
 136                mode = (S_ISLNK(st.st_mode) ? S_IFLNK :
 137                        S_IFREG | ce_permissions(st.st_mode));
 138
 139                show_modified(oldmode, mode, ce->sha1, null_sha1,
 140                              ce->name);
 141        }
 142        if (generate_patch)
 143                diff_flush();
 144        return 0;
 145}