|
16 | 16 | #include "diff.h" |
17 | 17 | #include "diffcore.h" |
18 | 18 | #include "revision.h" |
| 19 | +#include "xdiff-interface.h" |
19 | 20 |
|
20 | 21 | #define DEBUG 0 |
21 | 22 |
|
@@ -57,116 +58,89 @@ static int num_get_patch = 0; |
57 | 58 | static int num_commits = 0; |
58 | 59 | static int patch_time = 0; |
59 | 60 |
|
60 | | -#define TEMPFILE_PATH_LEN 60 |
61 | | -static struct patch *get_patch(struct commit *commit, struct commit *other) |
62 | | -{ |
| 61 | +struct blame_diff_state { |
| 62 | + struct xdiff_emit_state xm; |
63 | 63 | struct patch *ret; |
64 | | - struct util_info *info_c = (struct util_info *)commit->object.util; |
65 | | - struct util_info *info_o = (struct util_info *)other->object.util; |
66 | | - char tmp_path1[TEMPFILE_PATH_LEN], tmp_path2[TEMPFILE_PATH_LEN]; |
67 | | - char diff_cmd[TEMPFILE_PATH_LEN*2 + 20]; |
68 | | - struct timeval tv_start, tv_end; |
69 | | - int fd; |
70 | | - FILE *fin; |
71 | | - char buf[1024]; |
72 | | - |
73 | | - ret = xmalloc(sizeof(struct patch)); |
74 | | - ret->chunks = NULL; |
75 | | - ret->num = 0; |
76 | | - |
77 | | - get_blob(commit); |
78 | | - get_blob(other); |
| 64 | +}; |
79 | 65 |
|
80 | | - gettimeofday(&tv_start, NULL); |
| 66 | +static void process_u0_diff(void *state_, char *line, unsigned long len) |
| 67 | +{ |
| 68 | + struct blame_diff_state *state = state_; |
| 69 | + struct chunk *chunk; |
81 | 70 |
|
82 | | - fd = git_mkstemp(tmp_path1, TEMPFILE_PATH_LEN, "git-blame-XXXXXX"); |
83 | | - if (fd < 0) |
84 | | - die("unable to create temp-file: %s", strerror(errno)); |
| 71 | + if (len < 4 || line[0] != '@' || line[1] != '@') |
| 72 | + return; |
85 | 73 |
|
86 | | - if (xwrite(fd, info_c->buf, info_c->size) != info_c->size) |
87 | | - die("write failed: %s", strerror(errno)); |
88 | | - close(fd); |
| 74 | + if (DEBUG) |
| 75 | + printf("chunk line: %.*s", (int)len, line); |
| 76 | + state->ret->num++; |
| 77 | + state->ret->chunks = xrealloc(state->ret->chunks, |
| 78 | + sizeof(struct chunk) * state->ret->num); |
| 79 | + chunk = &state->ret->chunks[state->ret->num - 1]; |
| 80 | + |
| 81 | + assert(!strncmp(line, "@@ -", 4)); |
| 82 | + |
| 83 | + if (parse_hunk_header(line, len, |
| 84 | + &chunk->off1, &chunk->len1, |
| 85 | + &chunk->off2, &chunk->len2)) { |
| 86 | + state->ret->num--; |
| 87 | + return; |
| 88 | + } |
89 | 89 |
|
90 | | - fd = git_mkstemp(tmp_path2, TEMPFILE_PATH_LEN, "git-blame-XXXXXX"); |
91 | | - if (fd < 0) |
92 | | - die("unable to create temp-file: %s", strerror(errno)); |
| 90 | + if (chunk->len1 == 0) |
| 91 | + chunk->off1++; |
| 92 | + if (chunk->len2 == 0) |
| 93 | + chunk->off2++; |
93 | 94 |
|
94 | | - if (xwrite(fd, info_o->buf, info_o->size) != info_o->size) |
95 | | - die("write failed: %s", strerror(errno)); |
96 | | - close(fd); |
| 95 | + if (chunk->off1 > 0) |
| 96 | + chunk->off1--; |
| 97 | + if (chunk->off2 > 0) |
| 98 | + chunk->off2--; |
97 | 99 |
|
98 | | - sprintf(diff_cmd, "diff -U 0 %s %s", tmp_path1, tmp_path2); |
99 | | - fin = popen(diff_cmd, "r"); |
100 | | - if (!fin) |
101 | | - die("popen failed: %s", strerror(errno)); |
| 100 | + assert(chunk->off1 >= 0); |
| 101 | + assert(chunk->off2 >= 0); |
| 102 | +} |
102 | 103 |
|
103 | | - while (fgets(buf, sizeof(buf), fin)) { |
104 | | - struct chunk *chunk; |
105 | | - char *start, *sp; |
| 104 | +static struct patch *get_patch(struct commit *commit, struct commit *other) |
| 105 | +{ |
| 106 | + struct blame_diff_state state; |
| 107 | + xpparam_t xpp; |
| 108 | + xdemitconf_t xecfg; |
| 109 | + mmfile_t file_c, file_o; |
| 110 | + xdemitcb_t ecb; |
| 111 | + struct util_info *info_c = (struct util_info *)commit->object.util; |
| 112 | + struct util_info *info_o = (struct util_info *)other->object.util; |
| 113 | + struct timeval tv_start, tv_end; |
106 | 114 |
|
107 | | - if (buf[0] != '@' || buf[1] != '@') |
108 | | - continue; |
| 115 | + get_blob(commit); |
| 116 | + file_c.ptr = info_c->buf; |
| 117 | + file_c.size = info_c->size; |
109 | 118 |
|
110 | | - if (DEBUG) |
111 | | - printf("chunk line: %s", buf); |
112 | | - ret->num++; |
113 | | - ret->chunks = xrealloc(ret->chunks, |
114 | | - sizeof(struct chunk) * ret->num); |
115 | | - chunk = &ret->chunks[ret->num - 1]; |
116 | | - |
117 | | - assert(!strncmp(buf, "@@ -", 4)); |
118 | | - |
119 | | - start = buf + 4; |
120 | | - sp = index(start, ' '); |
121 | | - *sp = '\0'; |
122 | | - if (index(start, ',')) { |
123 | | - int ret = |
124 | | - sscanf(start, "%d,%d", &chunk->off1, &chunk->len1); |
125 | | - assert(ret == 2); |
126 | | - } else { |
127 | | - int ret = sscanf(start, "%d", &chunk->off1); |
128 | | - assert(ret == 1); |
129 | | - chunk->len1 = 1; |
130 | | - } |
131 | | - *sp = ' '; |
132 | | - |
133 | | - start = sp + 1; |
134 | | - sp = index(start, ' '); |
135 | | - *sp = '\0'; |
136 | | - if (index(start, ',')) { |
137 | | - int ret = |
138 | | - sscanf(start, "%d,%d", &chunk->off2, &chunk->len2); |
139 | | - assert(ret == 2); |
140 | | - } else { |
141 | | - int ret = sscanf(start, "%d", &chunk->off2); |
142 | | - assert(ret == 1); |
143 | | - chunk->len2 = 1; |
144 | | - } |
145 | | - *sp = ' '; |
| 119 | + get_blob(other); |
| 120 | + file_o.ptr = info_o->buf; |
| 121 | + file_o.size = info_o->size; |
146 | 122 |
|
147 | | - if (chunk->len1 == 0) |
148 | | - chunk->off1++; |
149 | | - if (chunk->len2 == 0) |
150 | | - chunk->off2++; |
| 123 | + gettimeofday(&tv_start, NULL); |
151 | 124 |
|
152 | | - if (chunk->off1 > 0) |
153 | | - chunk->off1--; |
154 | | - if (chunk->off2 > 0) |
155 | | - chunk->off2--; |
| 125 | + xpp.flags = XDF_NEED_MINIMAL; |
| 126 | + xecfg.ctxlen = 0; |
| 127 | + xecfg.flags = 0; |
| 128 | + ecb.outf = xdiff_outf; |
| 129 | + ecb.priv = &state; |
| 130 | + memset(&state, 0, sizeof(state)); |
| 131 | + state.xm.consume = process_u0_diff; |
| 132 | + state.ret = xmalloc(sizeof(struct patch)); |
| 133 | + state.ret->chunks = NULL; |
| 134 | + state.ret->num = 0; |
156 | 135 |
|
157 | | - assert(chunk->off1 >= 0); |
158 | | - assert(chunk->off2 >= 0); |
159 | | - } |
160 | | - pclose(fin); |
161 | | - unlink(tmp_path1); |
162 | | - unlink(tmp_path2); |
| 136 | + xdl_diff(&file_c, &file_o, &xpp, &xecfg, &ecb); |
163 | 137 |
|
164 | 138 | gettimeofday(&tv_end, NULL); |
165 | 139 | patch_time += 1000000 * (tv_end.tv_sec - tv_start.tv_sec) + |
166 | 140 | tv_end.tv_usec - tv_start.tv_usec; |
167 | 141 |
|
168 | 142 | num_get_patch++; |
169 | | - return ret; |
| 143 | + return state.ret; |
170 | 144 | } |
171 | 145 |
|
172 | 146 | static void free_patch(struct patch *p) |
@@ -674,7 +648,7 @@ static void get_commit_info(struct commit* commit, struct commit_info* ret) |
674 | 648 | static char author_buf[1024]; |
675 | 649 |
|
676 | 650 | tmp = strstr(commit->buffer, "\nauthor ") + 8; |
677 | | - len = index(tmp, '\n') - tmp; |
| 651 | + len = strchr(tmp, '\n') - tmp; |
678 | 652 | ret->author = author_buf; |
679 | 653 | memcpy(ret->author, tmp, len); |
680 | 654 |
|
@@ -875,7 +849,7 @@ int main(int argc, const char **argv) |
875 | 849 | if(blame_contents[blame_len-1] != '\n') |
876 | 850 | putc('\n', stdout); |
877 | 851 | } else { |
878 | | - char* next_buf = index(buf, '\n') + 1; |
| 852 | + char* next_buf = strchr(buf, '\n') + 1; |
879 | 853 | fwrite(buf, next_buf - buf, 1, stdout); |
880 | 854 | buf = next_buf; |
881 | 855 | } |
|
0 commit comments