diff options
Diffstat (limited to 'diff-tree-helper.c')
-rw-r--r-- | diff-tree-helper.c | 242 |
1 files changed, 39 insertions, 203 deletions
diff --git a/diff-tree-helper.c b/diff-tree-helper.c index 293e00b702..bcf89a5789 100644 --- a/diff-tree-helper.c +++ b/diff-tree-helper.c @@ -1,3 +1,6 @@ +/* + * Copyright (C) 2005 Junio C Hamano + */ #include "cache.h" #include "strbuf.h" #include "diff.h" @@ -17,15 +20,22 @@ static int matches_pathspec(const char *name, char **spec, int cnt) return 0; } -static int parse_oneside_change(const char *cp, unsigned char *sha1, - char *path) { +static int parse_oneside_change(const char *cp, struct diff_spec *one, + char *path) +{ int ch; - while ((ch = *cp) && '0' <= ch && ch <= '7') - cp++; /* skip mode bits */ + + one->file_valid = one->sha1_valid = 1; + one->mode = 0; + while ((ch = *cp) && '0' <= ch && ch <= '7') { + one->mode = (one->mode << 3) | (ch - '0'); + cp++; + } + if (strncmp(cp, "\tblob\t", 6)) return -1; cp += 6; - if (get_sha1_hex(cp, sha1)) + if (get_sha1_hex(cp, one->u.sha1)) return -1; cp += 40; if (*cp++ != '\t') @@ -34,31 +44,20 @@ static int parse_oneside_change(const char *cp, unsigned char *sha1, return 0; } -#define STATUS_CACHED 0 /* cached and sha1 valid */ -#define STATUS_ABSENT 1 /* diff-tree says old removed or new added */ -#define STATUS_UNCACHED 2 /* diff-cache output: read from working tree */ - static int parse_diff_tree_output(const char *buf, - unsigned char *old_sha1, - int *old_status, - unsigned char *new_sha1, - int *new_status, + struct diff_spec *old, + struct diff_spec *new, char *path) { const char *cp = buf; int ch; - static unsigned char null_sha[20] = { 0, }; switch (*cp++) { case '+': - *old_status = STATUS_ABSENT; - *new_status = (memcmp(new_sha1, null_sha, sizeof(null_sha)) ? - STATUS_CACHED : STATUS_UNCACHED); - return parse_oneside_change(cp, new_sha1, path); + old->file_valid = 0; + return parse_oneside_change(cp, new, path); case '-': - *new_status = STATUS_ABSENT; - *old_status = (memcmp(old_sha1, null_sha, sizeof(null_sha)) ? - STATUS_CACHED : STATUS_UNCACHED); - return parse_oneside_change(cp, old_sha1, path); + new->file_valid = 0; + return parse_oneside_change(cp, old, path); case '*': break; default: @@ -66,191 +65,36 @@ static int parse_diff_tree_output(const char *buf, } /* This is for '*' entries */ - while ((ch = *cp) && ('0' <= ch && ch <= '7')) - cp++; /* skip mode bits */ + old->file_valid = old->sha1_valid = 1; + new->file_valid = new->sha1_valid = 1; + + old->mode = new->mode = 0; + while ((ch = *cp) && ('0' <= ch && ch <= '7')) { + old->mode = (old->mode << 3) | (ch - '0'); + cp++; + } if (strncmp(cp, "->", 2)) return -1; cp += 2; - while ((ch = *cp) && ('0' <= ch && ch <= '7')) - cp++; /* skip mode bits */ + while ((ch = *cp) && ('0' <= ch && ch <= '7')) { + new->mode = (new->mode << 3) | (ch - '0'); + cp++; + } if (strncmp(cp, "\tblob\t", 6)) return -1; cp += 6; - if (get_sha1_hex(cp, old_sha1)) + if (get_sha1_hex(cp, old->u.sha1)) return -1; cp += 40; if (strncmp(cp, "->", 2)) return -1; cp += 2; - if (get_sha1_hex(cp, new_sha1)) + if (get_sha1_hex(cp, new->u.sha1)) return -1; cp += 40; if (*cp++ != '\t') return -1; strcpy(path, cp); - *old_status = (memcmp(old_sha1, null_sha, sizeof(null_sha)) ? - STATUS_CACHED : STATUS_UNCACHED); - *new_status = (memcmp(new_sha1, null_sha, sizeof(null_sha)) ? - STATUS_CACHED : STATUS_UNCACHED); - return 0; -} - -static int sha1err(const char *path, const unsigned char *sha1) -{ - return error("diff-tree-helper: unable to read sha1 file of %s (%s)", - path, sha1_to_hex(sha1)); -} - -static int fserr(const char *path) -{ - return error("diff-tree-helper: unable to read file %s", path); -} - -static char *map_whole_file(const char *path, unsigned long *size) { - int fd; - struct stat st; - void *buf; - - if ((fd = open(path, O_RDONLY)) < 0) { - error("diff-tree-helper: unable to read file %s", path); - return 0; - } - if (fstat(fd, &st) < 0) { - close(fd); - error("diff-tree-helper: unable to stat file %s", path); - return 0; - } - *size = st.st_size; - buf = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - close(fd); - return buf; -} - -static int show_diff(const unsigned char *old_sha1, int old_status, - const unsigned char *new_sha1, int new_status, - const char *path, int reverse_diff) -{ - char other[PATH_MAX]; - unsigned long size; - char type[20]; - int fd; - int reverse; - void *blob = 0; - const char *fs = 0; - int need_unmap = 0; - int need_unlink = 0; - - - switch (old_status) { - case STATUS_CACHED: - blob = read_sha1_file(old_sha1, type, &size); - if (! blob) - return sha1err(path, old_sha1); - - switch (new_status) { - case STATUS_CACHED: - strcpy(other, ".diff_tree_helper_XXXXXX"); - fd = mkstemp(other); - if (fd < 0) - die("unable to create temp-file"); - if (write(fd, blob, size) != size) - die("unable to write temp-file"); - close(fd); - free(blob); - - blob = read_sha1_file(new_sha1, type, &size); - if (! blob) - return sha1err(path, new_sha1); - - need_unlink = 1; - /* new = blob, old = fs */ - reverse = !reverse_diff; - fs = other; - break; - - case STATUS_ABSENT: - case STATUS_UNCACHED: - fs = ((new_status == STATUS_ABSENT) ? - "/dev/null" : path); - reverse = reverse_diff; - break; - - default: - reverse = reverse_diff; - } - break; - - case STATUS_ABSENT: - switch (new_status) { - case STATUS_CACHED: - blob = read_sha1_file(new_sha1, type, &size); - if (! blob) - return sha1err(path, new_sha1); - /* old = fs, new = blob */ - fs = "/dev/null"; - reverse = !reverse_diff; - break; - - case STATUS_ABSENT: - return error("diff-tree-helper: absent from both old and new?"); - case STATUS_UNCACHED: - fs = path; - blob = strdup(""); - size = 0; - /* old = blob, new = fs */ - reverse = reverse_diff; - break; - default: - reverse = reverse_diff; - } - break; - - case STATUS_UNCACHED: - fs = path; /* old = fs, new = blob */ - reverse = !reverse_diff; - - switch (new_status) { - case STATUS_CACHED: - blob = read_sha1_file(new_sha1, type, &size); - if (! blob) - return sha1err(path, new_sha1); - break; - - case STATUS_ABSENT: - blob = strdup(""); - size = 0; - break; - - case STATUS_UNCACHED: - /* old = fs */ - blob = map_whole_file(path, &size); - if (! blob) - return fserr(path); - need_unmap = 1; - break; - default: - reverse = reverse_diff; - } - break; - - default: - reverse = reverse_diff; - } - - if (fs) - show_differences(fs, - path, /* label */ - blob, - size, - reverse /* 0: diff blob fs - 1: diff fs blob */); - - if (need_unlink) - unlink(other); - if (need_unmap && blob) - munmap(blob, size); - else - free(blob); return 0; } @@ -275,28 +119,20 @@ int main(int ac, char **av) { } /* the remaining parameters are paths patterns */ - prepare_diff_cmd(); - while (1) { - int old_status, new_status; - unsigned char old_sha1[20], new_sha1[20]; + struct diff_spec old, new; char path[PATH_MAX]; read_line(&sb, stdin, line_termination); if (sb.eof) break; - if (parse_diff_tree_output(sb.buf, - old_sha1, &old_status, - new_sha1, &new_status, - path)) { + if (parse_diff_tree_output(sb.buf, &old, &new, path)) { fprintf(stderr, "cannot parse %s\n", sb.buf); continue; } - if (1 < ac && ! matches_pathspec(path, av+1, ac-1)) + if (1 < ac && !matches_pathspec(path, av+1, ac-1)) continue; - show_diff(old_sha1, old_status, - new_sha1, new_status, - path, reverse_diff); + run_external_diff(path, &old, &new); } return 0; } |