6
#define USE_THE_INDEX_COMPATIBILITY_MACROS
7
#include "cache.h"
8
#include "config.h"
9
+#include "ewah/ewok.h"
10
#include "lockfile.h"
11
#include "color.h"
12
#include "commit.h"
255
return run_diff_files(revs, options);
256
}
257
258
+struct symdiff {
259
+ struct bitmap *skip;
260
+ int warn;
261
+ const char *base, *left, *right;
262
+};
263
+
264
+/*
265
+ * Check for symmetric-difference arguments, and if present, arrange
266
+ * everything we need to know to handle them correctly. As a bonus,
267
+ * weed out all bogus range-based revision specifications, e.g.,
268
+ * "git diff A..B C..D" or "git diff A..B C" get rejected.
269
+ *
270
+ * For an actual symmetric diff, *symdiff is set this way:
271
+ *
272
+ * - its skip is non-NULL and marks *all* rev->pending.objects[i]
273
+ * indices that the caller should ignore (extra merge bases, of
274
+ * which there might be many, and A in A...B). Note that the
275
+ * chosen merge base and right side are NOT marked.
276
+ * - warn is set if there are multiple merge bases.
277
+ * - base, left, and right point to the names to use in a
278
+ * warning about multiple merge bases.
279
+ *
280
+ * If there is no symmetric diff argument, sym->skip is NULL and
281
+ * sym->warn is cleared. The remaining fields are not set.
282
+ */
283
+static void symdiff_prepare(struct rev_info *rev, struct symdiff *sym)
284
+{
285
+ int i, is_symdiff = 0, basecount = 0, othercount = 0;
286
+ int lpos = -1, rpos = -1, basepos = -1;
287
+ struct bitmap *map = NULL;
288
+
289
+ /*
290
+ * Use the whence fields to find merge bases and left and
291
+ * right parts of symmetric difference, so that we do not
292
+ * depend on the order that revisions are parsed. If there
293
+ * are any revs that aren't from these sources, we have a
294
+ * "git diff C A...B" or "git diff A...B C" case. Or we
295
+ * could even get "git diff A...B C...E", for instance.
296
+ *
297
+ * If we don't have just one merge base, we pick one
298
+ * at random.
299
+ *
300
+ * NB: REV_CMD_LEFT, REV_CMD_RIGHT are also used for A..B,
301
+ * so we must check for SYMMETRIC_LEFT too. The two arrays
302
+ * rev->pending.objects and rev->cmdline.rev are parallel.
303
+ */
304
+ for (i = 0; i < rev->cmdline.nr; i++) {
305
+ struct object *obj = rev->pending.objects[i].item;
306
+ switch (rev->cmdline.rev[i].whence) {
307
+ case REV_CMD_MERGE_BASE:
308
+ if (basepos < 0)
309
+ basepos = i;
310
+ basecount++;
311
+ break; /* do mark all bases */
312
+ case REV_CMD_LEFT:
313
+ if (lpos >= 0)
314
+ usage(builtin_diff_usage);
315
+ lpos = i;
316
+ if (obj->flags & SYMMETRIC_LEFT) {
317
+ is_symdiff = 1;
318
+ break; /* do mark A */
319
+ }
320
+ continue;
321
+ case REV_CMD_RIGHT:
322
+ if (rpos >= 0)
323
+ usage(builtin_diff_usage);
324
+ rpos = i;
325
+ continue; /* don't mark B */
326
+ case REV_CMD_PARENTS_ONLY:
327
+ case REV_CMD_REF:
328
+ case REV_CMD_REV:
329
+ othercount++;
330
+ continue;
331
+ }
332
+ if (map == NULL)
333
+ map = bitmap_new();
334
+ bitmap_set(map, i);
335
+ }
336
+
337
+ /*
338
+ * Forbid any additional revs for both A...B and A..B.
339
+ */
340
+ if (lpos >= 0 && othercount > 0)
341
+ usage(builtin_diff_usage);
342
+
343
+ if (!is_symdiff) {
344
+ bitmap_free(map);
345
+ sym->warn = 0;
346
+ sym->skip = NULL;
347
+ return;
348
+ }
349
+
350
+ sym->left = rev->pending.objects[lpos].name;
351
+ sym->right = rev->pending.objects[rpos].name;
352
+ sym->base = rev->pending.objects[basepos].name;
353
+ if (basecount == 0)
354
+ die(_("%s...%s: no merge base"), sym->left, sym->right);
355
+ bitmap_unset(map, basepos); /* unmark the base we want */
356
+ sym->warn = basecount > 1;
357
+ sym->skip = map;
358
+}
359
+
360
int cmd_diff(int argc, const char **argv, const char *prefix)
361
{
362
int i;
366
struct object_array_entry *blob[2];
367
int nongit = 0, no_index = 0;
368
int result = 0;
369
+ struct symdiff sdiff;
370
371
/*
372
* We could get N tree-ish in the rev.pending_objects list.
486
}
487
}
488
489
+ symdiff_prepare(&rev, &sdiff);
490
for (i = 0; i < rev.pending.nr; i++) {
491
struct object_array_entry *entry = &rev.pending.objects[i];
492
struct object *obj = entry->item;
501
obj = &get_commit_tree(((struct commit *)obj))->object;
502
503
if (obj->type == OBJ_TREE) {
504
+ if (sdiff.skip && bitmap_get(sdiff.skip, i))
505
+ continue;
506
obj->flags |= flags;
507
add_object_array(obj, name, &ent);
508
} else if (obj->type == OBJ_BLOB) {
544
usage(builtin_diff_usage);
545
else if (ent.nr == 1)
546
result = builtin_diff_index(&rev, argc, argv);
440
- else if (ent.nr == 2)
547
+ else if (ent.nr == 2) {
548
+ if (sdiff.warn)
549
+ warning(_("%s...%s: multiple merge bases, using %s"),
550
+ sdiff.left, sdiff.right, sdiff.base);
551
result = builtin_diff_tree(&rev, argc, argv,
552
&ent.objects[0], &ent.objects[1]);
443
- else if (ent.objects[0].item->flags & UNINTERESTING) {
444
- /*
445
- * diff A...B where there is at least one merge base
446
- * between A and B. We have ent.objects[0] ==
447
- * merge-base, ent.objects[ents-2] == A, and
448
- * ent.objects[ents-1] == B. Show diff between the
449
- * base and B. Note that we pick one merge base at
450
- * random if there are more than one.
451
- */
452
- result = builtin_diff_tree(&rev, argc, argv,
453
- &ent.objects[0],
454
- &ent.objects[ent.nr-1]);
553
} else
554
result = builtin_diff_combined(&rev, argc, argv,
555
ent.objects, ent.nr);