#include "diffcore.h"
#include "commit.h"
#include "pretty.h"
+#include "userdiff.h"
struct patch_util {
/* For the search for an exact match */
argv_array_pushl(&cp.args, "log", "--no-color", "-p", "--no-merges",
"--reverse", "--date-order", "--decorate=no",
+ /*
+ * Choose indicators that are not used anywhere
+ * else in diffs, but still look reasonable
+ * (e.g. will not be confusing when debugging)
+ */
+ "--output-indicator-new=>",
+ "--output-indicator-old=<",
+ "--output-indicator-context=#",
"--no-abbrev-commit", range,
NULL);
cp.out = -1;
strbuf_addch(&buf, '\n');
if (!util->diff_offset)
util->diff_offset = buf.len;
+ strbuf_addch(&buf, ' ');
strbuf_addbuf(&buf, &line);
} else if (in_header) {
if (starts_with(line.buf, "Author: ")) {
* we are not interested.
*/
continue;
- else
+ else if (line.buf[0] == '>') {
+ strbuf_addch(&buf, '+');
+ strbuf_add(&buf, line.buf + 1, line.len - 1);
+ } else if (line.buf[0] == '<') {
+ strbuf_addch(&buf, '-');
+ strbuf_add(&buf, line.buf + 1, line.len - 1);
+ } else if (line.buf[0] == '#') {
+ strbuf_addch(&buf, ' ');
+ strbuf_add(&buf, line.buf + 1, line.len - 1);
+ } else {
+ strbuf_addch(&buf, ' ');
strbuf_addbuf(&buf, &line);
+ }
strbuf_addch(&buf, '\n');
util->diffsize++;
free(b2a);
}
-static void output_pair_header(struct strbuf *buf,
+static void output_pair_header(struct diff_options *diffopt,
+ int patch_no_width,
+ struct strbuf *buf,
struct strbuf *dashes,
struct patch_util *a_util,
struct patch_util *b_util)
{
struct object_id *oid = a_util ? &a_util->oid : &b_util->oid;
struct commit *commit;
+ char status;
+ const char *color_reset = diff_get_color_opt(diffopt, DIFF_RESET);
+ const char *color_old = diff_get_color_opt(diffopt, DIFF_FILE_OLD);
+ const char *color_new = diff_get_color_opt(diffopt, DIFF_FILE_NEW);
+ const char *color_commit = diff_get_color_opt(diffopt, DIFF_COMMIT);
+ const char *color;
if (!dashes->len)
strbuf_addchars(dashes, '-',
strlen(find_unique_abbrev(oid,
DEFAULT_ABBREV)));
+ if (!b_util) {
+ color = color_old;
+ status = '<';
+ } else if (!a_util) {
+ color = color_new;
+ status = '>';
+ } else if (strcmp(a_util->patch, b_util->patch)) {
+ color = color_commit;
+ status = '!';
+ } else {
+ color = color_commit;
+ status = '=';
+ }
+
strbuf_reset(buf);
+ strbuf_addstr(buf, status == '!' ? color_old : color);
if (!a_util)
- strbuf_addf(buf, "-: %s ", dashes->buf);
+ strbuf_addf(buf, "%*s: %s ", patch_no_width, "-", dashes->buf);
else
- strbuf_addf(buf, "%d: %s ", a_util->i + 1,
+ strbuf_addf(buf, "%*d: %s ", patch_no_width, a_util->i + 1,
find_unique_abbrev(&a_util->oid, DEFAULT_ABBREV));
- if (!a_util)
- strbuf_addch(buf, '>');
- else if (!b_util)
- strbuf_addch(buf, '<');
- else if (strcmp(a_util->patch, b_util->patch))
- strbuf_addch(buf, '!');
- else
- strbuf_addch(buf, '=');
+ if (status == '!')
+ strbuf_addf(buf, "%s%s", color_reset, color);
+ strbuf_addch(buf, status);
+ if (status == '!')
+ strbuf_addf(buf, "%s%s", color_reset, color_new);
if (!b_util)
- strbuf_addf(buf, " -: %s", dashes->buf);
+ strbuf_addf(buf, " %*s: %s", patch_no_width, "-", dashes->buf);
else
- strbuf_addf(buf, " %d: %s", b_util->i + 1,
+ strbuf_addf(buf, " %*d: %s", patch_no_width, b_util->i + 1,
find_unique_abbrev(&b_util->oid, DEFAULT_ABBREV));
commit = lookup_commit_reference(the_repository, oid);
if (commit) {
+ if (status == '!')
+ strbuf_addf(buf, "%s%s", color_reset, color);
+
strbuf_addch(buf, ' ');
pp_commit_easy(CMIT_FMT_ONELINE, commit, buf);
}
- strbuf_addch(buf, '\n');
+ strbuf_addf(buf, "%s\n", color_reset);
- fwrite(buf->buf, buf->len, 1, stdout);
+ fwrite(buf->buf, buf->len, 1, diffopt->file);
}
+static struct userdiff_driver no_func_name = {
+ .funcname = { "$^", 0 }
+};
+
static struct diff_filespec *get_filespec(const char *name, const char *p)
{
struct diff_filespec *spec = alloc_filespec(name);
spec->size = strlen(p);
spec->should_munmap = 0;
spec->is_stdin = 1;
+ spec->driver = &no_func_name;
return spec;
}
struct diff_options *diffopt)
{
struct strbuf buf = STRBUF_INIT, dashes = STRBUF_INIT;
+ int patch_no_width = decimal_width(1 + (a->nr > b->nr ? a->nr : b->nr));
int i = 0, j = 0;
/*
/* Show unmatched LHS commit whose predecessors were shown. */
if (i < a->nr && a_util->matching < 0) {
- output_pair_header(&buf, &dashes, a_util, NULL);
+ output_pair_header(diffopt, patch_no_width,
+ &buf, &dashes, a_util, NULL);
i++;
continue;
}
/* Show unmatched RHS commits. */
while (j < b->nr && b_util->matching < 0) {
- output_pair_header(&buf, &dashes, NULL, b_util);
+ output_pair_header(diffopt, patch_no_width,
+ &buf, &dashes, NULL, b_util);
b_util = ++j < b->nr ? b->items[j].util : NULL;
}
/* Show matching LHS/RHS pair. */
if (j < b->nr) {
a_util = a->items[b_util->matching].util;
- output_pair_header(&buf, &dashes, a_util, b_util);
+ output_pair_header(diffopt, patch_no_width,
+ &buf, &dashes, a_util, b_util);
if (!(diffopt->output_format & DIFF_FORMAT_NO_OUTPUT))
patch_diff(a->items[b_util->matching].string,
b->items[j].string, diffopt);
strbuf_release(&dashes);
}
+static struct strbuf *output_prefix_cb(struct diff_options *opt, void *data)
+{
+ return data;
+}
+
int show_range_diff(const char *range1, const char *range2,
- int creation_factor, struct diff_options *diffopt)
+ int creation_factor, int dual_color,
+ struct diff_options *diffopt)
{
int res = 0;
res = error(_("could not parse log for '%s'"), range2);
if (!res) {
+ struct diff_options opts;
+ struct strbuf indent = STRBUF_INIT;
+
+ memcpy(&opts, diffopt, sizeof(opts));
+ opts.output_format = DIFF_FORMAT_PATCH;
+ opts.flags.suppress_diff_headers = 1;
+ opts.flags.dual_color_diffed_diffs = dual_color;
+ opts.output_prefix = output_prefix_cb;
+ strbuf_addstr(&indent, " ");
+ opts.output_prefix_data = &indent;
+ diff_setup_done(&opts);
+
find_exact_matches(&branch1, &branch2);
get_correspondences(&branch1, &branch2, creation_factor);
- output(&branch1, &branch2, diffopt);
+ output(&branch1, &branch2, &opts);
+
+ strbuf_release(&indent);
}
string_list_clear(&branch1, 1);