X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=show-diff.c;h=4557bd82f302eb951e02281a67a84c959122031b;hb=b8a55ce71d0d46204d64fe35787956e994d2a802;hp=4456230a568afd6ad090daf6ed2f77b4361434d7;hpb=4789576e0e5364dcd3916ef583b2ea61bef23f24;p=git.git diff --git a/show-diff.c b/show-diff.c index 4456230a..4557bd82 100644 --- a/show-diff.c +++ b/show-diff.c @@ -5,108 +5,13 @@ */ #include "cache.h" -static char *diff_cmd = "diff -L 'a/%s' -L 'b/%s' "; -static char *diff_opts = "-p -u"; -static char *diff_arg_forward = " - '%s'"; -static char *diff_arg_reverse = " '%s' -"; - -static void prepare_diff_cmd(void) -{ - /* - * Default values above are meant to match the - * Linux kernel development style. Examples of - * alternative styles you can specify via environment - * variables are: - * - * GIT_DIFF_CMD="diff -L '%s' -L '%s'" - * GIT_DIFF_OPTS="-c"; - */ - diff_cmd = getenv("GIT_DIFF_CMD") ? : diff_cmd; - diff_opts = getenv("GIT_DIFF_OPTS") ? : diff_opts; -} - -/* Help to copy the thing properly quoted for the shell safety. - * any single quote is replaced with '\'', and the caller is - * expected to enclose the result within a single quote pair. - * - * E.g. - * original sq_expand result - * name ==> name ==> 'name' - * a b ==> a b ==> 'a b' - * a'b ==> a'\''b ==> 'a'\''b' - * - * NOTE! The returned memory belongs to this function so - * do not free it. - */ -static char *sq_expand(char *src) -{ - static char *buf = NULL; - int cnt, c; - char *cp; - - /* count bytes needed to store the quoted string. */ - for (cnt = 1, cp = src; *cp; cnt++, cp++) - if (*cp == '\'') - cnt += 3; - - if (! (buf = malloc(cnt))) - return buf; - cp = buf; - while ((c = *src++)) { - if (c != '\'') - *cp++ = c; - else { - cp = strcpy(cp, "'\\''"); - cp += 4; - } - } - *cp = 0; - return buf; -} - -static void show_differences(char *name, char *label, void *old_contents, - unsigned long long old_size, int reverse) -{ - FILE *f; - char *name_sq = sq_expand(name); - char *label_sq = (name != label) ? sq_expand(label) : name_sq; - char *diff_arg = reverse ? diff_arg_reverse : diff_arg_forward; - int cmd_size = strlen(name_sq) + strlen(label_sq) * 2 + - strlen(diff_cmd) + strlen(diff_opts) + strlen(diff_arg); - char *cmd = malloc(cmd_size); - int next_at; - - fflush(stdout); - next_at = snprintf(cmd, cmd_size, diff_cmd, label_sq, label_sq); - next_at += snprintf(cmd+next_at, cmd_size-next_at, "%s", diff_opts); - next_at += snprintf(cmd+next_at, cmd_size-next_at, diff_arg, name_sq); - f = popen(cmd, "w"); - if (old_size) - fwrite(old_contents, old_size, 1, f); - pclose(f); - if (label_sq != name_sq) - free(label_sq); - free(name_sq); - free(cmd); -} - -static void show_diff_empty(struct cache_entry *ce, int reverse) -{ - char *old; - unsigned long int size; - unsigned char type[20]; - - old = read_sha1_file(ce->sha1, type, &size); - if (! old) { - error("unable to read blob object for %s (%s)", ce->name, - sha1_to_hex(ce->sha1)); - return; - } - show_differences("/dev/null", ce->name, old, size, reverse); -} - static const char *show_diff_usage = "show-diff [-q] [-s] [-z] [paths...]"; +static int recursive = 0; +static int line_termination = '\n'; +static int silent = 0; +static int silent_on_nonexisting_files = 0; + static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt) { int i; @@ -122,24 +27,27 @@ static int matches_pathspec(struct cache_entry *ce, char **spec, int cnt) return 0; } +static void show_file(const char *prefix, struct cache_entry *ce) +{ + printf("%s%o\t%s\t%s\t%s%c", prefix, ntohl(ce->ce_mode), "blob", + sha1_to_hex(ce->sha1), ce->name, line_termination); +} + int main(int argc, char **argv) { - int silent = 0; - int silent_on_nonexisting_files = 0; - int machine_readable = 0; - int reverse = 0; + static const char null_sha1_hex[] = "0000000000000000000000000000000000000000"; int entries = read_cache(); int i; while (1 < argc && argv[1][0] == '-') { - if (!strcmp(argv[1], "-R")) - reverse = 1; - else if (!strcmp(argv[1], "-s")) + if (!strcmp(argv[1], "-s")) silent_on_nonexisting_files = silent = 1; else if (!strcmp(argv[1], "-q")) silent_on_nonexisting_files = 1; else if (!strcmp(argv[1], "-z")) - machine_readable = 1; + line_termination = 0; + else if (!strcmp(argv[1], "-r")) + recursive = 1; /* No-op */ else usage(show_diff_usage); argv++; argc--; @@ -152,25 +60,20 @@ int main(int argc, char **argv) perror("read_cache"); exit(1); } - prepare_diff_cmd(); + for (i = 0; i < entries; i++) { struct stat st; + unsigned int oldmode, mode; struct cache_entry *ce = active_cache[i]; int changed; - unsigned long size; - char type[20]; - void *old; if (1 < argc && ! matches_pathspec(ce, argv+1, argc-1)) continue; if (ce_stage(ce)) { - if (machine_readable) - printf("U %s%c", ce->name, 0); - else - printf("%s: Unmerged\n", - ce->name); + printf("U %s%c", ce->name, line_termination); + while (i < entries && !strcmp(ce->name, active_cache[i]->name)) i++; @@ -179,37 +82,26 @@ int main(int argc, char **argv) } if (stat(ce->name, &st) < 0) { - if (errno == ENOENT && silent_on_nonexisting_files) + if (errno != ENOENT) { + perror(ce->name); continue; - if (machine_readable) - printf("X %s%c", ce->name, 0); - else { - printf("%s: %s\n", ce->name, strerror(errno)); - if (errno == ENOENT) - show_diff_empty(ce, reverse); - } + } + if (silent_on_nonexisting_files) + continue; + show_file("-", ce); continue; } changed = cache_match_stat(ce, &st); if (!changed) continue; - if (!machine_readable) - printf("%s: %s\n", ce->name, sha1_to_hex(ce->sha1)); - else { - printf("%s %s%c", sha1_to_hex(ce->sha1), ce->name, 0); - continue; - } - if (silent) - continue; - old = read_sha1_file(ce->sha1, type, &size); - if (! old) - error("unable to read blob object for %s (%s)", - ce->name, sha1_to_hex(ce->sha1)); - else - show_differences(ce->name, ce->name, old, size, - reverse); - free(old); + oldmode = ntohl(ce->ce_mode); + mode = S_IFREG | ce_permissions(st.st_mode); + + printf("*%o->%o\t%s\t%s->%s\t%s%c", + oldmode, mode, "blob", + sha1_to_hex(ce->sha1), null_sha1_hex, + ce->name, line_termination); } return 0; }