Skip to content

Commit f2f880f

Browse files
author
Junio C Hamano
committed
blame: use built-in xdiff
This removes the last use of external diff from core git suite. Also addresses the use of index() -- elsewhere we tend to use strchr(). Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent c1e335a commit f2f880f

File tree

1 file changed

+67
-93
lines changed

1 file changed

+67
-93
lines changed

blame.c

Lines changed: 67 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "diff.h"
1717
#include "diffcore.h"
1818
#include "revision.h"
19+
#include "xdiff-interface.h"
1920

2021
#define DEBUG 0
2122

@@ -57,116 +58,89 @@ static int num_get_patch = 0;
5758
static int num_commits = 0;
5859
static int patch_time = 0;
5960

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;
6363
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+
};
7965

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;
8170

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;
8573

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+
}
8989

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++;
9394

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--;
9799

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+
}
102103

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;
106114

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;
109118

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;
146122

147-
if (chunk->len1 == 0)
148-
chunk->off1++;
149-
if (chunk->len2 == 0)
150-
chunk->off2++;
123+
gettimeofday(&tv_start, NULL);
151124

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;
156135

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);
163137

164138
gettimeofday(&tv_end, NULL);
165139
patch_time += 1000000 * (tv_end.tv_sec - tv_start.tv_sec) +
166140
tv_end.tv_usec - tv_start.tv_usec;
167141

168142
num_get_patch++;
169-
return ret;
143+
return state.ret;
170144
}
171145

172146
static void free_patch(struct patch *p)
@@ -674,7 +648,7 @@ static void get_commit_info(struct commit* commit, struct commit_info* ret)
674648
static char author_buf[1024];
675649

676650
tmp = strstr(commit->buffer, "\nauthor ") + 8;
677-
len = index(tmp, '\n') - tmp;
651+
len = strchr(tmp, '\n') - tmp;
678652
ret->author = author_buf;
679653
memcpy(ret->author, tmp, len);
680654

@@ -875,7 +849,7 @@ int main(int argc, const char **argv)
875849
if(blame_contents[blame_len-1] != '\n')
876850
putc('\n', stdout);
877851
} else {
878-
char* next_buf = index(buf, '\n') + 1;
852+
char* next_buf = strchr(buf, '\n') + 1;
879853
fwrite(buf, next_buf - buf, 1, stdout);
880854
buf = next_buf;
881855
}

0 commit comments

Comments
 (0)