/* * GIT - The information manager from hell * * Copyright (C) Linus Torvalds, 2005 */ #include "cache.h" #include "diff.h" static const char *show_diff_usage = "show-diff [-p] [-q] [-r] [-z] [paths...]"; static int generate_patch = 0; static int line_termination = '\n'; static int silent = 0; static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt) { int i; int namelen = ce_namelen(ce); for (i = 0; i < cnt; i++) { int speclen = strlen(spec[i]); if (! strncmp(spec[i], ce->name, speclen) && speclen <= namelen && (ce->name[speclen] == 0 || ce->name[speclen] == '/')) return 1; } return 0; } static void show_unmerge(const char *path) { if (generate_patch) diff_unmerge(path); else printf("U %s%c", path, line_termination); } static void show_file(int pfx, struct cache_entry *ce) { if (generate_patch) diff_addremove(pfx, ntohl(ce->ce_mode), ce->sha1, ce->name, NULL); else printf("%c%06o\t%s\t%s\t%s%c", pfx, ntohl(ce->ce_mode), "blob", sha1_to_hex(ce->sha1), ce->name, line_termination); } static void show_modified(int oldmode, int mode, const char *old_sha1, const char *sha1, char *path) { char old_sha1_hex[41]; strcpy(old_sha1_hex, sha1_to_hex(old_sha1)); if (generate_patch) diff_change(oldmode, mode, old_sha1, sha1, path, NULL); else printf("*%06o->%06o\tblob\t%s->%s\t%s%c", oldmode, mode, old_sha1_hex, sha1_to_hex(sha1), path, line_termination); } int main(int argc, char **argv) { static const char null_sha1[20] = { 0, }; int entries = read_cache(); int i; while (1 < argc && argv[1][0] == '-') { if (!strcmp(argv[1], "-p")) generate_patch = 1; else if (!strcmp(argv[1], "-q")) silent = 1; else if (!strcmp(argv[1], "-r")) ; /* no-op */ else if (!strcmp(argv[1], "-s")) ; /* no-op */ else if (!strcmp(argv[1], "-z")) line_termination = 0; else usage(show_diff_usage); argv++; argc--; } /* At this point, if argc == 1, then we are doing everything. * Otherwise argv[1] .. argv[argc-1] have the explicit paths. */ if (entries < 0) { perror("read_cache"); exit(1); } for (i = 0; i < entries; i++) { struct stat st; unsigned int oldmode, mode; struct cache_entry *ce = active_cache[i]; int changed; if (1 < argc && ! matches_pathspec(ce, argv+1, argc-1)) continue; if (ce_stage(ce)) { show_unmerge(ce->name); while (i < entries && !strcmp(ce->name, active_cache[i]->name)) i++; i--; /* compensate for loop control increments */ continue; } if (stat(ce->name, &st) < 0) { if (errno != ENOENT) { perror(ce->name); continue; } if (silent) continue; show_file('-', ce); continue; } changed = cache_match_stat(ce, &st); if (!changed) continue; oldmode = ntohl(ce->ce_mode); mode = S_IFREG | ce_permissions(st.st_mode); show_modified(oldmode, mode, ce->sha1, null_sha1, ce->name); } return 0; }