X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=show-diff.c;h=fdd7dd4b0cc8c92a18ddaf0bcf8c9675fcab303b;hb=3a663fd9842aaa9e232ab43a811d11f1d7f0b7bc;hp=e7aa60b4ab92ab2d0fe6afaeb5657757d0401225;hpb=8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68;p=git.git diff --git a/show-diff.c b/show-diff.c index e7aa60b4..fdd7dd4b 100644 --- a/show-diff.c +++ b/show-diff.c @@ -4,83 +4,132 @@ * Copyright (C) Linus Torvalds, 2005 */ #include "cache.h" +#include "diff.h" -#define MTIME_CHANGED 0x0001 -#define CTIME_CHANGED 0x0002 -#define OWNER_CHANGED 0x0004 -#define MODE_CHANGED 0x0008 -#define INODE_CHANGED 0x0010 -#define DATA_CHANGED 0x0020 +static const char *show_diff_usage = +"show-diff [-p] [-q] [-r] [-z] [paths...]"; -static int match_stat(struct cache_entry *ce, struct stat *st) +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) { - unsigned int changed = 0; + if (generate_patch) + diff_unmerge(path); + else + printf("U %s%c", path, line_termination); +} - if (ce->mtime.sec != (unsigned int)st->st_mtim.tv_sec || - ce->mtime.nsec != (unsigned int)st->st_mtim.tv_nsec) - changed |= MTIME_CHANGED; - if (ce->ctime.sec != (unsigned int)st->st_ctim.tv_sec || - ce->ctime.nsec != (unsigned int)st->st_ctim.tv_nsec) - changed |= CTIME_CHANGED; - if (ce->st_uid != (unsigned int)st->st_uid || - ce->st_gid != (unsigned int)st->st_gid) - changed |= OWNER_CHANGED; - if (ce->st_mode != (unsigned int)st->st_mode) - changed |= MODE_CHANGED; - if (ce->st_dev != (unsigned int)st->st_dev || - ce->st_ino != (unsigned int)st->st_ino) - changed |= INODE_CHANGED; - if (ce->st_size != (unsigned int)st->st_size) - changed |= DATA_CHANGED; - return changed; +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_differences(struct cache_entry *ce, struct stat *cur, - void *old_contents, unsigned long long old_size) +static void show_modified(int oldmode, int mode, + const char *old_sha1, const char *sha1, + char *path) { - static char cmd[1000]; - FILE *f; + char old_sha1_hex[41]; + strcpy(old_sha1_hex, sha1_to_hex(old_sha1)); - snprintf(cmd, sizeof(cmd), "diff -u - %s", ce->name); - f = popen(cmd, "w"); - fwrite(old_contents, old_size, 1, f); - pclose(f); + 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 n, changed; - unsigned int mode; - unsigned long size; - char type[20]; - void *new; + int changed; - if (stat(ce->name, &st) < 0) { - printf("%s: %s\n", ce->name, strerror(errno)); + 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; } - changed = match_stat(ce, &st); - if (!changed) { - printf("%s: ok\n", ce->name); + + if (stat(ce->name, &st) < 0) { + if (errno != ENOENT) { + perror(ce->name); + continue; + } + if (silent) + continue; + show_file('-', ce); continue; } - printf("%.*s: ", ce->namelen, ce->name); - for (n = 0; n < 20; n++) - printf("%02x", ce->sha1[n]); - printf("\n"); - new = read_sha1_file(ce->sha1, type, &size); - show_differences(ce, &st, new, size); - free(new); + 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; }