Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 42 additions & 12 deletions builtin/diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "setup.h"
#include "oid-array.h"
#include "tree.h"
#include "hex.h"

#define DIFF_NO_INDEX_EXPLICIT 1
#define DIFF_NO_INDEX_IMPLICIT 2
Expand Down Expand Up @@ -170,14 +171,23 @@ static void builtin_diff_index(struct rev_info *revs,
run_diff_index(revs, option);
}

struct symdiff {
struct bitmap *skip;
int warn;
const char *base, *left, *right;
struct object_array_entry *ent0, *ent1;
};

static void builtin_diff_tree(struct rev_info *revs,
int argc, const char **argv,
struct object_array_entry *ent0,
struct object_array_entry *ent1)
struct object_array_entry *ent0, // I would rather encapsulate this with original object
struct object_array_entry *ent1,
struct symdiff *sdiff)
{
const struct object_id *(oid[2]);
struct object_id mb_oid;
int merge_base = 0;
const struct object_id *(r[2]); // oid closest to rev_info - tag/commit if known - corresponding to oid[]

while (1 < argc) {
const char *arg = argv[1];
Expand All @@ -192,20 +202,44 @@ static void builtin_diff_tree(struct rev_info *revs,
diff_get_merge_base(revs, &mb_oid);
oid[0] = &mb_oid;
oid[1] = &revs->pending.objects[1].item->oid;
r[0] = oid[0];
r[1] = oid[1];
} else {
int swap = 0;

/*
* We saw two trees, ent0 and ent1. If ent1 is uninteresting,
* swap them.
*/
if (ent1->item->flags & UNINTERESTING)
if (ent1->item->flags & UNINTERESTING) {
warning("SWAP");
swap = 1;
}
oid[swap] = &ent0->item->oid;
oid[1 - swap] = &ent1->item->oid;

if (sdiff->skip) { // XXX symmetric diff will have 3+ revs; it's simplest to reuse the symdiff result
r[swap] = &sdiff->ent0->item->oid;
r[1 - swap] = &sdiff->ent1->item->oid;
} else {
// XXX assuming 2 revs, reach back up to commits
if (revs->pending.nr != 2)
BUG("unexpected revs->pending.nr: %d", revs->pending.nr);
r[swap] = &revs->pending.objects[0].item->oid;
r[1 - swap] = &revs->pending.objects[1].item->oid;
}
}
diff_tree_oid(oid[0], oid[1], "", &revs->diffopt);
log_tree_diff_flush(revs);

revs->diffopt.why.mode = "diff_tree";
revs->diffopt.why.oid[0] = r[0];
revs->diffopt.why.oid[1] = r[1];

diff_tree_oid(oid[0], oid[1], "", &revs->diffopt); // XXX the merge-base option implies that either TREE or COMMIT could reach here
log_tree_diff_flush(revs); // TODO Smuggle the answers via revs->diffopt down to run_diff

revs->diffopt.why.mode = NULL;
revs->diffopt.why.oid[0] = NULL;
revs->diffopt.why.oid[1] = NULL;
}

static void builtin_diff_combined(struct rev_info *revs,
Expand Down Expand Up @@ -289,12 +323,6 @@ static void builtin_diff_files(struct rev_info *revs, int argc, const char **arg
run_diff_files(revs, options);
}

struct symdiff {
struct bitmap *skip;
int warn;
const char *base, *left, *right;
};

/*
* Check for symmetric-difference arguments, and if present, arrange
* everything we need to know to handle them correctly. As a bonus,
Expand Down Expand Up @@ -389,6 +417,8 @@ static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym)
bitmap_unset(map, basepos); /* unmark the base we want */
sym->warn = basecount > 1;
sym->skip = map;
sym->ent0 = &rev->pending.objects[basepos];
sym->ent1 = &rev->pending.objects[rpos];
}

static void symdiff_release(struct symdiff *sdiff)
Expand Down Expand Up @@ -621,7 +651,7 @@ int cmd_diff(int argc,
warning(_("%s...%s: multiple merge bases, using %s"),
sdiff.left, sdiff.right, sdiff.base);
builtin_diff_tree(&rev, argc, argv,
&ent.objects[0], &ent.objects[1]);
&ent.objects[0], &ent.objects[1], &sdiff);
} else
builtin_diff_combined(&rev, argc, argv,
ent.objects, ent.nr,
Expand Down
14 changes: 13 additions & 1 deletion diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#include "setup.h"
#include "strmap.h"
#include "ws.h"
#include "hash.h"

#ifdef NO_FAST_WORKING_DIRECTORY
#define FAST_WORKING_DIRECTORY 0
Expand Down Expand Up @@ -4427,14 +4428,25 @@ static void run_external_diff(const struct external_diff *pgm,
if (other) {
strvec_push(&cmd.args, other);
if (xfrm_msg)
strvec_push(&cmd.args, xfrm_msg);
strvec_push(&cmd.args, xfrm_msg); // XXX does this provide useful metadata?
}
}

strvec_pushf(&cmd.env, "GIT_DIFF_PATH_COUNTER=%d",
++o->diff_path_counter);
strvec_pushf(&cmd.env, "GIT_DIFF_PATH_TOTAL=%d", q->nr);

if (o->why.oid[0] && o->why.oid[1]) {
strvec_pushf(&cmd.env, "GIT_DIFF_MODE=%s", o->why.mode);

strvec_pushf(&cmd.env, "GIT_DIFF_REV_ONE=%s", oid_to_hex(o->why.oid[0]));
strvec_pushf(&cmd.env, "GIT_DIFF_REV_TWO=%s", oid_to_hex(o->why.oid[1]));

strvec_pushf(&cmd.env, "GIT_DIFF_FILESPEC_PATH_ONE=%s", one->path);
strvec_pushf(&cmd.env, "GIT_DIFF_FILESPEC_PATH_TWO=%s", two->path);
}


diff_free_filespec_data(one);
diff_free_filespec_data(two);
cmd.use_shell = 1;
Expand Down
6 changes: 6 additions & 0 deletions diff.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,12 @@ struct diff_options {
struct strmap *additional_path_headers;

int no_free;

struct why {
const char * mode;
const struct object_id * oid[2];
} why;

};

unsigned diff_filter_bit(char status);
Expand Down
Loading