From: Junio C Hamano Date: Sat, 8 Apr 2006 00:57:46 +0000 (-0700) Subject: Merge branch 'jc/blame' X-Git-Tag: v1.3.0-rc3~6 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/45fa7608bd1abd4dca12b0b90a852e7a71377381?ds=inline;hp=-c Merge branch 'jc/blame' * jc/blame: blame -S Match ofs/cnt types in diff interface. blame: use built-in xdiff combine-diff: move the code to parse hunk-header into common library. combine-diff: refactor built-in xdiff interface. combine-diff: use built-in xdiff. --- 45fa7608bd1abd4dca12b0b90a852e7a71377381 diff --combined Makefile index 3367b8c13d,7030370c6f..fe40b652e6 --- a/Makefile +++ b/Makefile @@@ -114,7 -114,7 +114,7 @@@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__pow SCRIPT_SH = \ git-add.sh git-bisect.sh git-branch.sh git-checkout.sh \ - git-cherry.sh git-clone.sh git-commit.sh \ + git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \ git-count-objects.sh git-diff.sh git-fetch.sh \ git-format-patch.sh git-log.sh git-ls-remote.sh \ git-merge-one-file.sh git-parse-remote.sh \ @@@ -208,7 -208,7 +208,7 @@@ LIB_OBJS = quote.o read-cache.o refs.o run-command.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ - fetch-clone.o revision.o pager.o tree-walk.o \ + fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \ $(DIFF_OBJS) GITLIBS = $(LIB_FILE) $(XDIFF_LIB) diff --combined blame.c index 9bb34e63ec,75cffd8a3f..6730b10b11 --- a/blame.c +++ b/blame.c @@@ -16,6 -16,7 +16,7 @@@ #include "diff.h" #include "diffcore.h" #include "revision.h" + #include "xdiff-interface.h" #define DEBUG 0 @@@ -57,116 -58,89 +58,89 @@@ static int num_get_patch = 0 static int num_commits = 0; static int patch_time = 0; - #define TEMPFILE_PATH_LEN 60 - static struct patch *get_patch(struct commit *commit, struct commit *other) - { + struct blame_diff_state { + struct xdiff_emit_state xm; struct patch *ret; - struct util_info *info_c = (struct util_info *)commit->object.util; - struct util_info *info_o = (struct util_info *)other->object.util; - char tmp_path1[TEMPFILE_PATH_LEN], tmp_path2[TEMPFILE_PATH_LEN]; - char diff_cmd[TEMPFILE_PATH_LEN*2 + 20]; - struct timeval tv_start, tv_end; - int fd; - FILE *fin; - char buf[1024]; - - ret = xmalloc(sizeof(struct patch)); - ret->chunks = NULL; - ret->num = 0; - - get_blob(commit); - get_blob(other); + }; - gettimeofday(&tv_start, NULL); + static void process_u0_diff(void *state_, char *line, unsigned long len) + { + struct blame_diff_state *state = state_; + struct chunk *chunk; - fd = git_mkstemp(tmp_path1, TEMPFILE_PATH_LEN, "git-blame-XXXXXX"); - if (fd < 0) - die("unable to create temp-file: %s", strerror(errno)); + if (len < 4 || line[0] != '@' || line[1] != '@') + return; - if (xwrite(fd, info_c->buf, info_c->size) != info_c->size) - die("write failed: %s", strerror(errno)); - close(fd); + if (DEBUG) + printf("chunk line: %.*s", (int)len, line); + state->ret->num++; + state->ret->chunks = xrealloc(state->ret->chunks, + sizeof(struct chunk) * state->ret->num); + chunk = &state->ret->chunks[state->ret->num - 1]; + + assert(!strncmp(line, "@@ -", 4)); + + if (parse_hunk_header(line, len, + &chunk->off1, &chunk->len1, + &chunk->off2, &chunk->len2)) { + state->ret->num--; + return; + } - fd = git_mkstemp(tmp_path2, TEMPFILE_PATH_LEN, "git-blame-XXXXXX"); - if (fd < 0) - die("unable to create temp-file: %s", strerror(errno)); + if (chunk->len1 == 0) + chunk->off1++; + if (chunk->len2 == 0) + chunk->off2++; - if (xwrite(fd, info_o->buf, info_o->size) != info_o->size) - die("write failed: %s", strerror(errno)); - close(fd); + if (chunk->off1 > 0) + chunk->off1--; + if (chunk->off2 > 0) + chunk->off2--; - sprintf(diff_cmd, "diff -U 0 %s %s", tmp_path1, tmp_path2); - fin = popen(diff_cmd, "r"); - if (!fin) - die("popen failed: %s", strerror(errno)); + assert(chunk->off1 >= 0); + assert(chunk->off2 >= 0); + } - while (fgets(buf, sizeof(buf), fin)) { - struct chunk *chunk; - char *start, *sp; + static struct patch *get_patch(struct commit *commit, struct commit *other) + { + struct blame_diff_state state; + xpparam_t xpp; + xdemitconf_t xecfg; + mmfile_t file_c, file_o; + xdemitcb_t ecb; + struct util_info *info_c = (struct util_info *)commit->object.util; + struct util_info *info_o = (struct util_info *)other->object.util; + struct timeval tv_start, tv_end; - if (buf[0] != '@' || buf[1] != '@') - continue; + get_blob(commit); + file_c.ptr = info_c->buf; + file_c.size = info_c->size; - if (DEBUG) - printf("chunk line: %s", buf); - ret->num++; - ret->chunks = xrealloc(ret->chunks, - sizeof(struct chunk) * ret->num); - chunk = &ret->chunks[ret->num - 1]; - - assert(!strncmp(buf, "@@ -", 4)); - - start = buf + 4; - sp = index(start, ' '); - *sp = '\0'; - if (index(start, ',')) { - int ret = - sscanf(start, "%d,%d", &chunk->off1, &chunk->len1); - assert(ret == 2); - } else { - int ret = sscanf(start, "%d", &chunk->off1); - assert(ret == 1); - chunk->len1 = 1; - } - *sp = ' '; - - start = sp + 1; - sp = index(start, ' '); - *sp = '\0'; - if (index(start, ',')) { - int ret = - sscanf(start, "%d,%d", &chunk->off2, &chunk->len2); - assert(ret == 2); - } else { - int ret = sscanf(start, "%d", &chunk->off2); - assert(ret == 1); - chunk->len2 = 1; - } - *sp = ' '; + get_blob(other); + file_o.ptr = info_o->buf; + file_o.size = info_o->size; - if (chunk->len1 == 0) - chunk->off1++; - if (chunk->len2 == 0) - chunk->off2++; + gettimeofday(&tv_start, NULL); - if (chunk->off1 > 0) - chunk->off1--; - if (chunk->off2 > 0) - chunk->off2--; + xpp.flags = XDF_NEED_MINIMAL; + xecfg.ctxlen = 0; + xecfg.flags = 0; + ecb.outf = xdiff_outf; + ecb.priv = &state; + memset(&state, 0, sizeof(state)); + state.xm.consume = process_u0_diff; + state.ret = xmalloc(sizeof(struct patch)); + state.ret->chunks = NULL; + state.ret->num = 0; - assert(chunk->off1 >= 0); - assert(chunk->off2 >= 0); - } - pclose(fin); - unlink(tmp_path1); - unlink(tmp_path2); + xdl_diff(&file_c, &file_o, &xpp, &xecfg, &ecb); gettimeofday(&tv_end, NULL); patch_time += 1000000 * (tv_end.tv_sec - tv_start.tv_sec) + tv_end.tv_usec - tv_start.tv_usec; num_get_patch++; - return ret; + return state.ret; } static void free_patch(struct patch *p) @@@ -674,7 -648,7 +648,7 @@@ static void get_commit_info(struct comm static char author_buf[1024]; tmp = strstr(commit->buffer, "\nauthor ") + 8; - len = index(tmp, '\n') - tmp; + len = strchr(tmp, '\n') - tmp; ret->author = author_buf; memcpy(ret->author, tmp, len); @@@ -729,11 -703,30 +703,30 @@@ static void* topo_getter(struct commit return util->topo_data; } + static int read_ancestry(const char *graft_file, + unsigned char **start_sha1) + { + FILE *fp = fopen(graft_file, "r"); + char buf[1024]; + if (!fp) + return -1; + while (fgets(buf, sizeof(buf), fp)) { + /* The format is just "Commit Parent1 Parent2 ...\n" */ + int len = strlen(buf); + struct commit_graft *graft = read_graft_line(buf, len); + register_commit_graft(graft, 0); + if (!*start_sha1) + *start_sha1 = graft->sha1; + } + fclose(fp); + return 0; + } + int main(int argc, const char **argv) { int i; struct commit *initial = NULL; - unsigned char sha1[20]; + unsigned char sha1[20], *sha1_p = NULL; const char *filename = NULL, *commit = NULL; char filename_buf[256]; @@@ -767,6 -760,14 +760,14 @@@ !strcmp(argv[i], "--compability")) { compability = 1; continue; + } else if(!strcmp(argv[i], "-S")) { + if (i + 1 < argc && + !read_ancestry(argv[i + 1], &sha1_p)) { + compability = 1; + i++; + continue; + } + usage(blame_usage); } else if(!strcmp(argv[i], "--")) { options = 0; continue; @@@ -788,7 -789,9 +789,9 @@@ if(!filename) usage(blame_usage); - if(!commit) + if (commit && sha1_p) + usage(blame_usage); + else if(!commit) commit = "HEAD"; if(prefix) @@@ -797,9 -800,12 +800,12 @@@ strcpy(filename_buf, filename); filename = filename_buf; - if (get_sha1(commit, sha1)) - die("get_sha1 failed, commit '%s' not found", commit); - start_commit = lookup_commit_reference(sha1); + if (!sha1_p) { + if (get_sha1(commit, sha1)) + die("get_sha1 failed, commit '%s' not found", commit); + sha1_p = sha1; + } + start_commit = lookup_commit_reference(sha1_p); get_util(start_commit)->pathname = filename; if (fill_util_info(start_commit)) { printf("%s not found in %s\n", filename, commit); @@@ -813,7 -819,6 +819,7 @@@ rev.prune_fn = simplify_commit; rev.topo_setter = topo_setter; rev.topo_getter = topo_getter; + rev.parents = 1; rev.limited = 1; commit_list_insert(start_commit, &rev.commits); @@@ -876,7 -881,7 +882,7 @@@ if(blame_contents[blame_len-1] != '\n') putc('\n', stdout); } else { - char* next_buf = index(buf, '\n') + 1; + char* next_buf = strchr(buf, '\n') + 1; fwrite(buf, next_buf - buf, 1, stdout); buf = next_buf; }