2580
return 1;
2581
}
2582
2583
+static void line_range_filter_init(struct line_range_filter *filter,
2584
+ const struct range_set *ranges,
2585
+ xdiff_emit_line_fn line_fn,
2586
+ void *cb_data)
2587
+{
2588
+ memset(filter, 0, sizeof(*filter));
2589
+ filter->orig_line_fn = line_fn;
2590
+ filter->orig_cb_data = cb_data;
2591
+ filter->ranges = ranges;
2592
+ strbuf_init(&filter->hunk.lines, 0);
2593
+}
2594
+
2595
/*
2596
* Begin a range hunk at the first in-range line. Its position fixes the
2597
* hunk's begins, taken from the two image cursors before they advance:
2756
return filter->ret;
2757
}
2758
2759
+/*
2760
+ * Run an xdiff pass through an initialized line-range filter, flush the
2761
+ * final range hunk, and release the filter. Inflates ctxlen to the largest
2762
+ * range span first, so that every change within a single range lands in one
2763
+ * xdiff hunk and the inter-change context is emitted; the filter then clips
2764
+ * back to range boundaries. The optimal ctxlen depends on where changes fall
2765
+ * within the range, which is only known after xdiff runs, so the max span is
2766
+ * the upper bound that guarantees correctness in a single pass. Every
2767
+ * consumer (patch, diffstat, check) relies on one xdiff hunk per range, so
2768
+ * this lives here rather than at each call site. Also clears
2769
+ * XDL_EMIT_NO_HUNK_HDR: the filter seeds its per-image position from the hunk
2770
+ * headers, so a consumer that otherwise suppresses them (diffstat) still gets
2771
+ * them here. Returns non-zero if xdiff or any forwarded callback failed.
2772
+ */
2773
+static int line_range_filter_diff(struct line_range_filter *filter,
2774
+ mmfile_t *mf1, mmfile_t *mf2,
2775
+ xpparam_t *xpp, xdemitconf_t *xecfg)
2776
+{
2777
+ const struct range_set *ranges = filter->ranges;
2778
+ long max_span = 0;
2779
+ unsigned int i;
2780
+ int ret;
2781
+
2782
+ for (i = 0; i < ranges->nr; i++) {
2783
+ long span = ranges->ranges[i].end - ranges->ranges[i].start;
2784
+ if (span > max_span)
2785
+ max_span = span;
2786
+ }
2787
+ if (max_span > xecfg->ctxlen)
2788
+ xecfg->ctxlen = max_span;
2789
+
2790
+ /* the filter seeds its per-image position from hunk headers */
2791
+ xecfg->flags &= ~XDL_EMIT_NO_HUNK_HDR;
2792
+
2793
+ ret = xdi_diff_outf(mf1, mf2, line_range_hunk_fn,
2794
+ line_range_line_fn, filter, xpp, xecfg);
2795
+ if (!ret) {
2796
+ flush_range_hunk(filter);
2797
+ ret = filter->ret;
2798
+ }
2799
+ strbuf_release(&filter->hunk.lines);
2800
+ return ret;
2801
+}
2802
+
2803
static void pprint_rename(struct strbuf *name, const char *a, const char *b)
2804
{
2805
const char *old_name = a;
4164
xdi_diff_outf(&mf1, &mf2, NULL, quick_consume,
4165
&ecbdata, &xpp, &xecfg);
4166
} else if (line_ranges) {
4111
- struct line_range_filter lr_state;
4112
- unsigned int i;
4113
- long max_span = 0;
4167
+ struct line_range_filter lr_filter;
4168
4115
- memset(&lr_state, 0, sizeof(lr_state));
4116
- lr_state.orig_line_fn = fn_out_consume;
4117
- lr_state.orig_cb_data = &ecbdata;
4118
- lr_state.ranges = line_ranges;
4119
- strbuf_init(&lr_state.hunk.lines, 0);
4120
-
4121
- /*
4122
- * Inflate ctxlen so that all changes within
4123
- * any single range are merged into one xdiff
4124
- * hunk and the inter-change context is emitted.
4125
- * The callback clips back to range boundaries.
4126
- *
4127
- * The optimal ctxlen depends on where changes
4128
- * fall within the range, which is only known
4129
- * after xdiff runs; the max range span is the
4130
- * upper bound that guarantees correctness in a
4131
- * single pass.
4132
- */
4133
- for (i = 0; i < line_ranges->nr; i++) {
4134
- long span = line_ranges->ranges[i].end -
4135
- line_ranges->ranges[i].start;
4136
- if (span > max_span)
4137
- max_span = span;
4138
- }
4139
- if (max_span > xecfg.ctxlen)
4140
- xecfg.ctxlen = max_span;
4141
-
4142
- if (xdi_diff_outf(&mf1, &mf2,
4143
- line_range_hunk_fn,
4144
- line_range_line_fn,
4145
- &lr_state, &xpp, &xecfg))
4146
- die("unable to generate diff for %s",
4147
- one->path);
4169
+ line_range_filter_init(&lr_filter, line_ranges,
4170
+ fn_out_consume, &ecbdata);
4171
4149
- flush_range_hunk(&lr_state);
4150
- if (lr_state.ret)
4172
+ if (line_range_filter_diff(&lr_filter, &mf1, &mf2,
4173
+ &xpp, &xecfg))
4174
die("unable to generate diff for %s",
4175
one->path);
4153
- strbuf_release(&lr_state.hunk.lines);
4176
} else if (xdi_diff_outf(&mf1, &mf2, NULL, fn_out_consume,
4177
&ecbdata, &xpp, &xecfg))
4178
die("unable to generate diff for %s", one->path);