return base;
}
-static char *grab_blob(const struct object_id *oid, unsigned int mode,
+static char *grab_blob(struct repository *r,
+ const struct object_id *oid, unsigned int mode,
unsigned long *size, struct userdiff_driver *textconv,
const char *path)
{
} else if (textconv) {
struct diff_filespec *df = alloc_filespec(path);
fill_filespec(df, oid, 1, mode);
- *size = fill_textconv(textconv, df, &blob);
+ *size = fill_textconv(r, textconv, df, &blob);
free_filespec(df);
} else {
blob = read_object_file(oid, &type, size);
struct sline *lost_bucket;
};
-static void consume_line(void *state_, char *line, unsigned long len)
+static void consume_hunk(void *state_,
+ long ob, long on,
+ long nb, long nn,
+ const char *funcline, long funclen)
{
struct combine_diff_state *state = state_;
- if (5 < len && !memcmp("@@ -", line, 4)) {
- if (parse_hunk_header(line, len,
- &state->ob, &state->on,
- &state->nb, &state->nn))
- return;
- state->lno = state->nb;
- if (state->nn == 0) {
- /* @@ -X,Y +N,0 @@ removed Y lines
- * that would have come *after* line N
- * in the result. Our lost buckets hang
- * to the line after the removed lines,
- *
- * Note that this is correct even when N == 0,
- * in which case the hunk removes the first
- * line in the file.
- */
- state->lost_bucket = &state->sline[state->nb];
- if (!state->nb)
- state->nb = 1;
- } else {
- state->lost_bucket = &state->sline[state->nb-1];
- }
- if (!state->sline[state->nb-1].p_lno)
- state->sline[state->nb-1].p_lno =
- xcalloc(state->num_parent,
- sizeof(unsigned long));
- state->sline[state->nb-1].p_lno[state->n] = state->ob;
- return;
+
+ state->ob = ob;
+ state->on = on;
+ state->nb = nb;
+ state->nn = nn;
+ state->lno = state->nb;
+ if (state->nn == 0) {
+ /* @@ -X,Y +N,0 @@ removed Y lines
+ * that would have come *after* line N
+ * in the result. Our lost buckets hang
+ * to the line after the removed lines,
+ *
+ * Note that this is correct even when N == 0,
+ * in which case the hunk removes the first
+ * line in the file.
+ */
+ state->lost_bucket = &state->sline[state->nb];
+ if (!state->nb)
+ state->nb = 1;
+ } else {
+ state->lost_bucket = &state->sline[state->nb-1];
}
+ if (!state->sline[state->nb-1].p_lno)
+ state->sline[state->nb-1].p_lno =
+ xcalloc(state->num_parent, sizeof(unsigned long));
+ state->sline[state->nb-1].p_lno[state->n] = state->ob;
+}
+
+static void consume_line(void *state_, char *line, unsigned long len)
+{
+ struct combine_diff_state *state = state_;
if (!state->lost_bucket)
return; /* not in any hunk yet */
switch (line[0]) {
}
}
-static void combine_diff(const struct object_id *parent, unsigned int mode,
+static void combine_diff(struct repository *r,
+ const struct object_id *parent, unsigned int mode,
mmfile_t *result_file,
struct sline *sline, unsigned int cnt, int n,
int num_parent, int result_deleted,
if (result_deleted)
return; /* result deleted */
- parent_file.ptr = grab_blob(parent, mode, &sz, textconv, path);
+ parent_file.ptr = grab_blob(r, parent, mode, &sz, textconv, path);
parent_file.size = sz;
memset(&xpp, 0, sizeof(xpp));
xpp.flags = flags;
state.num_parent = num_parent;
state.n = n;
- if (xdi_diff_outf(&parent_file, result_file, consume_line, &state,
- &xpp, &xecfg))
+ if (xdi_diff_outf(&parent_file, result_file, consume_hunk,
+ consume_line, &state, &xpp, &xecfg))
die("unable to generate combined diff for %s",
oid_to_hex(parent));
free(parent_file.ptr);
const char *line_prefix = diff_line_prefix(opt);
context = opt->context;
- userdiff = userdiff_find_by_path(elem->path);
+ userdiff = userdiff_find_by_path(opt->repo->index, elem->path);
if (!userdiff)
userdiff = userdiff_find_by_name("default");
if (opt->flags.allow_textconv)
- textconv = userdiff_get_textconv(userdiff);
+ textconv = userdiff_get_textconv(opt->repo, userdiff);
/* Read the result of merge first */
if (!working_tree_file)
- result = grab_blob(&elem->oid, elem->mode, &result_size,
+ result = grab_blob(opt->repo, &elem->oid, elem->mode, &result_size,
textconv, elem->path);
else {
/* Used by diff-tree to read from the working tree */
} else if (S_ISDIR(st.st_mode)) {
struct object_id oid;
if (resolve_gitlink_ref(elem->path, "HEAD", &oid) < 0)
- result = grab_blob(&elem->oid, elem->mode,
- &result_size, NULL, NULL);
+ result = grab_blob(opt->repo, &elem->oid,
+ elem->mode, &result_size,
+ NULL, NULL);
else
- result = grab_blob(&oid, elem->mode,
+ result = grab_blob(opt->repo, &oid, elem->mode,
&result_size, NULL, NULL);
} else if (textconv) {
struct diff_filespec *df = alloc_filespec(elem->path);
fill_filespec(df, &null_oid, 0, st.st_mode);
- result_size = fill_textconv(textconv, df, &result);
+ result_size = fill_textconv(opt->repo, textconv, df, &result);
free_filespec(df);
} else if (0 <= (fd = open(elem->path, O_RDONLY))) {
size_t len = xsize_t(st.st_size);
if (is_file) {
struct strbuf buf = STRBUF_INIT;
- if (convert_to_git(&the_index, elem->path, result, len, &buf, global_conv_flags_eol)) {
+ if (convert_to_git(rev->diffopt.repo->index,
+ elem->path, result, len, &buf, global_conv_flags_eol)) {
free(result);
result = strbuf_detach(&buf, &len);
result_size = len;
for (i = 0; !is_binary && i < num_parent; i++) {
char *buf;
unsigned long size;
- buf = grab_blob(&elem->parent[i].oid,
+ buf = grab_blob(opt->repo,
+ &elem->parent[i].oid,
elem->parent[i].mode,
&size, NULL, NULL);
if (buffer_is_binary(buf, size))
for (i = 0; i < num_parent; i++) {
int j;
for (j = 0; j < i; j++) {
- if (!oidcmp(&elem->parent[i].oid,
- &elem->parent[j].oid)) {
+ if (oideq(&elem->parent[i].oid,
+ &elem->parent[j].oid)) {
reuse_combine_diff(sline, cnt, i, j);
break;
}
}
if (i <= j)
- combine_diff(&elem->parent[i].oid,
+ combine_diff(opt->repo,
+ &elem->parent[i].oid,
elem->parent[i].mode,
&result_file, sline,
cnt, i, num_parent, result_deleted,
return path->path;
}
+/*
+ * Diff stat formats which we always compute solely against the first parent.
+ */
+#define STAT_FORMAT_MASK (DIFF_FORMAT_NUMSTAT \
+ | DIFF_FORMAT_SHORTSTAT \
+ | DIFF_FORMAT_SUMMARY \
+ | DIFF_FORMAT_DIRSTAT \
+ | DIFF_FORMAT_DIFFSTAT)
/* find set of paths that every parent touches */
static struct combine_diff_path *find_paths_generic(const struct object_id *oid,
* show stat against the first parent even when doing
* combined diff.
*/
- int stat_opt = (output_format &
- (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT));
+ int stat_opt = output_format & STAT_FORMAT_MASK;
if (i == 0 && stat_opt)
opt->output_format = stat_opt;
else
* show stat against the first parent even
* when doing combined diff.
*/
- stat_opt = (opt->output_format &
- (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT));
+ stat_opt = opt->output_format & STAT_FORMAT_MASK;
if (stat_opt) {
diffopts.output_format = stat_opt;
show_raw_diff(p, num_parent, rev);
needsep = 1;
}
- else if (opt->output_format &
- (DIFF_FORMAT_NUMSTAT|DIFF_FORMAT_DIFFSTAT))
+ else if (opt->output_format & STAT_FORMAT_MASK)
needsep = 1;
else if (opt->output_format & DIFF_FORMAT_CALLBACK)
handle_combined_callback(opt, paths, num_parent, num_paths);