revision.c 107 KB
Newer Older
1
#include "cache.h"
2
#include "object-store.h"
3 4 5 6
#include "tag.h"
#include "blob.h"
#include "tree.h"
#include "commit.h"
7
#include "diff.h"
8 9
#include "refs.h"
#include "revision.h"
10
#include "repository.h"
11
#include "graph.h"
12
#include "grep.h"
13
#include "reflog-walk.h"
14
#include "patch-ids.h"
15
#include "decorate.h"
16
#include "log-tree.h"
17
#include "string-list.h"
18
#include "line-log.h"
19
#include "mailmap.h"
20
#include "commit-slab.h"
21
#include "dir.h"
22
#include "cache-tree.h"
23
#include "bisect.h"
24
#include "packfile.h"
25
#include "worktree.h"
26
#include "argv-array.h"
27
#include "commit-reach.h"
28
#include "commit-graph.h"
29
#include "prio-queue.h"
30
#include "hashmap.h"
31

32 33
volatile show_early_output_fn_t show_early_output;

34 35 36
static const char *term_bad;
static const char *term_good;

37 38
implement_shared_commit_slab(revision_sources, char *);

39
void show_object_with_name(FILE *out, struct object *obj, const char *name)
40
{
41
	const char *p;
42

43
	fprintf(out, "%s ", oid_to_hex(&obj->oid));
44 45
	for (p = name; *p && *p != '\n'; p++)
		fputc(*p, out);
46
	fputc('\n', out);
47 48
}

49 50
static void mark_blob_uninteresting(struct blob *blob)
{
51 52
	if (!blob)
		return;
53 54 55 56 57
	if (blob->object.flags & UNINTERESTING)
		return;
	blob->object.flags |= UNINTERESTING;
}

58 59
static void mark_tree_contents_uninteresting(struct repository *r,
					     struct tree *tree)
60
{
61
	struct tree_desc desc;
62
	struct name_entry entry;
63

64
	if (parse_tree_gently(tree, 1) < 0)
65
		return;
66

67
	init_tree_desc(&desc, tree->buffer, tree->size);
68
	while (tree_entry(&desc, &entry)) {
69 70
		switch (object_type(entry.mode)) {
		case OBJ_TREE:
71
			mark_tree_uninteresting(r, lookup_tree(r, &entry.oid));
72 73
			break;
		case OBJ_BLOB:
74
			mark_blob_uninteresting(lookup_blob(r, &entry.oid));
75 76 77 78 79
			break;
		default:
			/* Subproject commit - not in this repository */
			break;
		}
80
	}
81 82 83 84 85

	/*
	 * We don't care about the tree any more
	 * after it has been marked uninteresting.
	 */
86
	free_tree_buffer(tree);
87 88
}

89
void mark_tree_uninteresting(struct repository *r, struct tree *tree)
90
{
91
	struct object *obj;
92 93 94

	if (!tree)
		return;
95 96

	obj = &tree->object;
97 98 99
	if (obj->flags & UNINTERESTING)
		return;
	obj->flags |= UNINTERESTING;
100
	mark_tree_contents_uninteresting(r, tree);
101 102
}

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
struct path_and_oids_entry {
	struct hashmap_entry ent;
	char *path;
	struct oidset trees;
};

static int path_and_oids_cmp(const void *hashmap_cmp_fn_data,
			     const struct path_and_oids_entry *e1,
			     const struct path_and_oids_entry *e2,
			     const void *keydata)
{
	return strcmp(e1->path, e2->path);
}

static void paths_and_oids_init(struct hashmap *map)
{
	hashmap_init(map, (hashmap_cmp_fn) path_and_oids_cmp, NULL, 0);
}

static void paths_and_oids_clear(struct hashmap *map)
{
	struct hashmap_iter iter;
	struct path_and_oids_entry *entry;
	hashmap_iter_init(map, &iter);

	while ((entry = (struct path_and_oids_entry *)hashmap_iter_next(&iter))) {
		oidset_clear(&entry->trees);
		free(entry->path);
	}

	hashmap_free(map, 1);
}

static void paths_and_oids_insert(struct hashmap *map,
				  const char *path,
				  const struct object_id *oid)
{
	int hash = strhash(path);
	struct path_and_oids_entry key;
	struct path_and_oids_entry *entry;

	hashmap_entry_init(&key, hash);

	/* use a shallow copy for the lookup */
	key.path = (char *)path;
	oidset_init(&key.trees, 0);

	if (!(entry = (struct path_and_oids_entry *)hashmap_get(map, &key, NULL))) {
		entry = xcalloc(1, sizeof(struct path_and_oids_entry));
		hashmap_entry_init(entry, hash);
		entry->path = xstrdup(key.path);
		oidset_init(&entry->trees, 16);
		hashmap_put(map, entry);
	}

	oidset_insert(&entry->trees, oid);
}

static void add_children_by_path(struct repository *r,
				 struct tree *tree,
				 struct hashmap *map)
{
	struct tree_desc desc;
	struct name_entry entry;

	if (!tree)
		return;

	if (parse_tree_gently(tree, 1) < 0)
		return;

	init_tree_desc(&desc, tree->buffer, tree->size);
	while (tree_entry(&desc, &entry)) {
		switch (object_type(entry.mode)) {
		case OBJ_TREE:
178
			paths_and_oids_insert(map, entry.path, &entry.oid);
179 180

			if (tree->object.flags & UNINTERESTING) {
181
				struct tree *child = lookup_tree(r, &entry.oid);
182 183 184 185 186 187
				if (child)
					child->object.flags |= UNINTERESTING;
			}
			break;
		case OBJ_BLOB:
			if (tree->object.flags & UNINTERESTING) {
188
				struct blob *child = lookup_blob(r, &entry.oid);
189 190 191 192 193 194 195 196 197 198 199 200 201
				if (child)
					child->object.flags |= UNINTERESTING;
			}
			break;
		default:
			/* Subproject commit - not in this repository */
			break;
		}
	}

	free_tree_buffer(tree);
}

202 203 204
void mark_trees_uninteresting_sparse(struct repository *r,
				     struct oidset *trees)
{
205 206 207 208
	unsigned has_interesting = 0, has_uninteresting = 0;
	struct hashmap map;
	struct hashmap_iter map_iter;
	struct path_and_oids_entry *entry;
209 210 211 212
	struct object_id *oid;
	struct oidset_iter iter;

	oidset_iter_init(trees, &iter);
213 214
	while ((!has_interesting || !has_uninteresting) &&
	       (oid = oidset_iter_next(&iter))) {
215 216 217 218 219
		struct tree *tree = lookup_tree(r, oid);

		if (!tree)
			continue;

220 221 222 223
		if (tree->object.flags & UNINTERESTING)
			has_uninteresting = 1;
		else
			has_interesting = 1;
224
	}
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

	/* Do not walk unless we have both types of trees. */
	if (!has_uninteresting || !has_interesting)
		return;

	paths_and_oids_init(&map);

	oidset_iter_init(trees, &iter);
	while ((oid = oidset_iter_next(&iter))) {
		struct tree *tree = lookup_tree(r, oid);
		add_children_by_path(r, tree, &map);
	}

	hashmap_iter_init(&map, &map_iter);
	while ((entry = hashmap_iter_next(&map_iter)))
		mark_trees_uninteresting_sparse(r, &entry->trees);

	paths_and_oids_clear(&map);
243 244
}

245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
struct commit_stack {
	struct commit **items;
	size_t nr, alloc;
};
#define COMMIT_STACK_INIT { NULL, 0, 0 }

static void commit_stack_push(struct commit_stack *stack, struct commit *commit)
{
	ALLOC_GROW(stack->items, stack->nr + 1, stack->alloc);
	stack->items[stack->nr++] = commit;
}

static struct commit *commit_stack_pop(struct commit_stack *stack)
{
	return stack->nr ? stack->items[--stack->nr] : NULL;
}

static void commit_stack_clear(struct commit_stack *stack)
{
	FREE_AND_NULL(stack->items);
	stack->nr = stack->alloc = 0;
}

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
static void mark_one_parent_uninteresting(struct commit *commit,
					  struct commit_stack *pending)
{
	struct commit_list *l;

	if (commit->object.flags & UNINTERESTING)
		return;
	commit->object.flags |= UNINTERESTING;

	/*
	 * Normally we haven't parsed the parent
	 * yet, so we won't have a parent of a parent
	 * here. However, it may turn out that we've
	 * reached this commit some other way (where it
	 * wasn't uninteresting), in which case we need
	 * to mark its parents recursively too..
	 */
	for (l = commit->parents; l; l = l->next)
		commit_stack_push(pending, l->item);
}

289 290
void mark_parents_uninteresting(struct commit *commit)
{
291 292
	struct commit_stack pending = COMMIT_STACK_INIT;
	struct commit_list *l;
293 294

	for (l = commit->parents; l; l = l->next)
295 296 297 298 299
		mark_one_parent_uninteresting(l->item, &pending);

	while (pending.nr > 0)
		mark_one_parent_uninteresting(commit_stack_pop(&pending),
					      &pending);
300 301

	commit_stack_clear(&pending);
302 303
}

304
static void add_pending_object_with_path(struct rev_info *revs,
305
					 struct object *obj,
306 307
					 const char *name, unsigned mode,
					 const char *path)
308
{
Junio C Hamano's avatar
Junio C Hamano committed
309 310
	if (!obj)
		return;
311
	if (revs->no_walk && (obj->flags & UNINTERESTING))
312
		revs->no_walk = 0;
313 314
	if (revs->reflog_info && obj->type == OBJ_COMMIT) {
		struct strbuf buf = STRBUF_INIT;
315
		int len = interpret_branch_name(name, 0, &buf, 0);
316 317 318

		if (0 < len && name[len] && buf.len)
			strbuf_addstr(&buf, name + len);
319 320 321
		add_reflog_for_walk(revs->reflog_info,
				    (struct commit *)obj,
				    buf.buf[0] ? buf.buf: name);
322
		strbuf_release(&buf);
323
		return; /* do not add the commit itself */
324
	}
325 326 327 328 329 330 331 332
	add_object_array_with_path(obj, name, &revs->pending, mode, path);
}

static void add_pending_object_with_mode(struct rev_info *revs,
					 struct object *obj,
					 const char *name, unsigned mode)
{
	add_pending_object_with_path(revs, obj, name, mode, NULL);
333 334
}

335 336
void add_pending_object(struct rev_info *revs,
			struct object *obj, const char *name)
Junio C Hamano's avatar
Junio C Hamano committed
337 338 339 340
{
	add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
}

341 342
void add_head_to_pending(struct rev_info *revs)
{
343
	struct object_id oid;
344
	struct object *obj;
345
	if (get_oid("HEAD", &oid))
346
		return;
347
	obj = parse_object(revs->repo, &oid);
348 349 350 351 352
	if (!obj)
		return;
	add_pending_object(revs, obj, "HEAD");
}

353
static struct object *get_reference(struct rev_info *revs, const char *name,
354
				    const struct object_id *oid,
355
				    unsigned int flags)
356 357 358
{
	struct object *object;

359 360 361 362 363 364 365 366 367 368 369 370 371 372
	/*
	 * If the repository has commit graphs, repo_parse_commit() avoids
	 * reading the object buffer, so use it whenever possible.
	 */
	if (oid_object_info(revs->repo, oid, NULL) == OBJ_COMMIT) {
		struct commit *c = lookup_commit(revs->repo, oid);
		if (!repo_parse_commit(revs->repo, c))
			object = (struct object *) c;
		else
			object = NULL;
	} else {
		object = parse_object(revs->repo, oid);
	}

Junio C Hamano's avatar
Junio C Hamano committed
373 374 375
	if (!object) {
		if (revs->ignore_missing)
			return object;
376 377
		if (revs->exclude_promisor_objects && is_promisor_object(oid))
			return NULL;
378
		die("bad object %s", name);
Junio C Hamano's avatar
Junio C Hamano committed
379
	}
380 381 382 383
	object->flags |= flags;
	return object;
}

384 385
void add_pending_oid(struct rev_info *revs, const char *name,
		      const struct object_id *oid, unsigned int flags)
386
{
387
	struct object *object = get_reference(revs, name, oid, flags);
388 389 390
	add_pending_object(revs, object, name);
}

391
static struct commit *handle_commit(struct rev_info *revs,
392
				    struct object_array_entry *entry)
393
{
394 395 396 397
	struct object *object = entry->item;
	const char *name = entry->name;
	const char *path = entry->path;
	unsigned int mode = entry->mode;
398
	unsigned long flags = object->flags;
399 400 401 402

	/*
	 * Tag object? Look what it points to..
	 */
403
	while (object->type == OBJ_TAG) {
404
		struct tag *tag = (struct tag *) object;
405
		if (revs->tag_objects && !(flags & UNINTERESTING))
406
			add_pending_object(revs, object, tag->tag);
407 408
		if (!tag->tagged)
			die("bad tag");
409
		object = parse_object(revs->repo, &tag->tagged->oid);
410
		if (!object) {
411
			if (revs->ignore_missing_links || (flags & UNINTERESTING))
412
				return NULL;
413 414 415
			if (revs->exclude_promisor_objects &&
			    is_promisor_object(&tag->tagged->oid))
				return NULL;
416
			die("bad object %s", oid_to_hex(&tag->tagged->oid));
417
		}
418
		object->flags |= flags;
419 420 421
		/*
		 * We'll handle the tagged object by looping or dropping
		 * through to the non-tag handlers below. Do not
422
		 * propagate path data from the tag's pending entry.
423 424 425
		 */
		path = NULL;
		mode = 0;
426 427 428 429 430 431
	}

	/*
	 * Commit object? Just return it, we'll do all the complex
	 * reachability crud.
	 */
432
	if (object->type == OBJ_COMMIT) {
433
		struct commit *commit = (struct commit *)object;
434

435 436
		if (parse_commit(commit) < 0)
			die("unable to parse commit %s", name);
437
		if (flags & UNINTERESTING) {
438
			mark_parents_uninteresting(commit);
439 440
			revs->limited = 1;
		}
441 442 443 444 445 446
		if (revs->sources) {
			char **slot = revision_sources_at(revs->sources, commit);

			if (!*slot)
				*slot = xstrdup(name);
		}
447 448 449 450
		return commit;
	}

	/*
451
	 * Tree object? Either mark it uninteresting, or add it
452 453
	 * to the list of objects to look at later..
	 */
454
	if (object->type == OBJ_TREE) {
455 456 457 458
		struct tree *tree = (struct tree *)object;
		if (!revs->tree_objects)
			return NULL;
		if (flags & UNINTERESTING) {
459
			mark_tree_contents_uninteresting(revs->repo, tree);
460 461
			return NULL;
		}
462
		add_pending_object_with_path(revs, object, name, mode, path);
463 464 465 466 467 468
		return NULL;
	}

	/*
	 * Blob object? You know the drill by now..
	 */
469
	if (object->type == OBJ_BLOB) {
470 471
		if (!revs->blob_objects)
			return NULL;
472
		if (flags & UNINTERESTING)
473
			return NULL;
474
		add_pending_object_with_path(revs, object, name, mode, path);
475 476 477 478 479
		return NULL;
	}
	die("%s is unknown object", name);
}

480 481
static int everybody_uninteresting(struct commit_list *orig,
				   struct commit **interesting_cache)
482 483
{
	struct commit_list *list = orig;
484 485 486 487 488 489 490

	if (*interesting_cache) {
		struct commit *commit = *interesting_cache;
		if (!(commit->object.flags & UNINTERESTING))
			return 0;
	}

491 492 493 494 495
	while (list) {
		struct commit *commit = list->item;
		list = list->next;
		if (commit->object.flags & UNINTERESTING)
			continue;
496 497

		*interesting_cache = commit;
498 499 500 501 502
		return 0;
	}
	return 1;
}

503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
/*
 * A definition of "relevant" commit that we can use to simplify limited graphs
 * by eliminating side branches.
 *
 * A "relevant" commit is one that is !UNINTERESTING (ie we are including it
 * in our list), or that is a specified BOTTOM commit. Then after computing
 * a limited list, during processing we can generally ignore boundary merges
 * coming from outside the graph, (ie from irrelevant parents), and treat
 * those merges as if they were single-parent. TREESAME is defined to consider
 * only relevant parents, if any. If we are TREESAME to our on-graph parents,
 * we don't care if we were !TREESAME to non-graph parents.
 *
 * Treating bottom commits as relevant ensures that a limited graph's
 * connection to the actual bottom commit is not viewed as a side branch, but
 * treated as part of the graph. For example:
 *
 *   ....Z...A---X---o---o---B
 *        .     /
 *         W---Y
 *
 * When computing "A..B", the A-X connection is at least as important as
 * Y-X, despite A being flagged UNINTERESTING.
 *
 * And when computing --ancestry-path "A..B", the A-X connection is more
 * important than Y-X, despite both A and Y being flagged UNINTERESTING.
 */
static inline int relevant_commit(struct commit *commit)
{
	return (commit->object.flags & (UNINTERESTING | BOTTOM)) != UNINTERESTING;
}

/*
 * Return a single relevant commit from a parent list. If we are a TREESAME
 * commit, and this selects one of our parents, then we can safely simplify to
 * that parent.
 */
static struct commit *one_relevant_parent(const struct rev_info *revs,
					  struct commit_list *orig)
{
	struct commit_list *list = orig;
	struct commit *relevant = NULL;

	if (!orig)
		return NULL;

	/*
	 * For 1-parent commits, or if first-parent-only, then return that
	 * first parent (even if not "relevant" by the above definition).
	 * TREESAME will have been set purely on that parent.
	 */
	if (revs->first_parent_only || !orig->next)
		return orig->item;

	/*
	 * For multi-parent commits, identify a sole relevant parent, if any.
	 * If we have only one relevant parent, then TREESAME will be set purely
	 * with regard to that parent, and we can simplify accordingly.
	 *
	 * If we have more than one relevant parent, or no relevant parents
	 * (and multiple irrelevant ones), then we can't select a parent here
	 * and return NULL.
	 */
	while (list) {
		struct commit *commit = list->item;
		list = list->next;
		if (relevant_commit(commit)) {
			if (relevant)
				return NULL;
			relevant = commit;
		}
	}
	return relevant;
}

577 578
/*
 * The goal is to get REV_TREE_NEW as the result only if the
579 580 581 582
 * diff consists of all '+' (and no other changes), REV_TREE_OLD
 * if the whole diff is removal of old data, and otherwise
 * REV_TREE_DIFFERENT (of course if the trees are the same we
 * want REV_TREE_SAME).
583 584 585 586 587 588 589 590 591 592
 *
 * The only time we care about the distinction is when
 * remove_empty_trees is in effect, in which case we care only about
 * whether the whole change is REV_TREE_NEW, or if there's another type
 * of change. Which means we can stop the diff early in either of these
 * cases:
 *
 *   1. We're not using remove_empty_trees at all.
 *
 *   2. We saw anything except REV_TREE_NEW.
593
 */
594
static int tree_difference = REV_TREE_SAME;
595 596 597

static void file_add_remove(struct diff_options *options,
		    int addremove, unsigned mode,
598 599
		    const struct object_id *oid,
		    int oid_valid,
600
		    const char *fullpath, unsigned dirty_submodule)
601
{
602
	int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD;
603
	struct rev_info *revs = options->change_fn_data;
604

605
	tree_difference |= diff;
606
	if (!revs->remove_empty_trees || tree_difference != REV_TREE_NEW)
607
		options->flags.has_changes = 1;
608 609 610 611
}

static void file_change(struct diff_options *options,
		 unsigned old_mode, unsigned new_mode,
612 613 614
		 const struct object_id *old_oid,
		 const struct object_id *new_oid,
		 int old_oid_valid, int new_oid_valid,
615 616
		 const char *fullpath,
		 unsigned old_dirty_submodule, unsigned new_dirty_submodule)
617
{
618
	tree_difference = REV_TREE_DIFFERENT;
619
	options->flags.has_changes = 1;
620 621
}

622 623
static int rev_compare_tree(struct rev_info *revs,
			    struct commit *parent, struct commit *commit)
624
{
625 626
	struct tree *t1 = get_commit_tree(parent);
	struct tree *t2 = get_commit_tree(commit);
627

628
	if (!t1)
629
		return REV_TREE_NEW;
630 631
	if (!t2)
		return REV_TREE_OLD;
632 633 634 635 636 637

	if (revs->simplify_by_decoration) {
		/*
		 * If we are simplifying by decoration, then the commit
		 * is worth showing if it has a tag pointing at it.
		 */
638
		if (get_name_decoration(&commit->object))
639 640 641 642 643 644 645 646
			return REV_TREE_DIFFERENT;
		/*
		 * A commit that is not pointed by a tag is uninteresting
		 * if we are not limited by path.  This means that you will
		 * see the usual "commits that touch the paths" plus any
		 * tagged commit by specifying both --simplify-by-decoration
		 * and pathspec.
		 */
647
		if (!revs->prune_data.nr)
648 649
			return REV_TREE_SAME;
	}
650

651
	tree_difference = REV_TREE_SAME;
652
	revs->pruning.flags.has_changes = 0;
653
	if (diff_tree_oid(&t1->object.oid, &t2->object.oid, "",
654
			   &revs->pruning) < 0)
655
		return REV_TREE_DIFFERENT;
656 657 658
	return tree_difference;
}

659
static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit)
660 661
{
	int retval;
662
	struct tree *t1 = get_commit_tree(commit);
663 664 665 666

	if (!t1)
		return 0;

667
	tree_difference = REV_TREE_SAME;
668
	revs->pruning.flags.has_changes = 0;
669
	retval = diff_tree_oid(NULL, &t1->object.oid, "", &revs->pruning);
670

671
	return retval >= 0 && (tree_difference == REV_TREE_SAME);
672 673
}

674 675 676 677 678 679 680 681
struct treesame_state {
	unsigned int nparents;
	unsigned char treesame[FLEX_ARRAY];
};

static struct treesame_state *initialise_treesame(struct rev_info *revs, struct commit *commit)
{
	unsigned n = commit_list_count(commit->parents);
682
	struct treesame_state *st = xcalloc(1, st_add(sizeof(*st), n));
683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
	st->nparents = n;
	add_decoration(&revs->treesame, &commit->object, st);
	return st;
}

/*
 * Must be called immediately after removing the nth_parent from a commit's
 * parent list, if we are maintaining the per-parent treesame[] decoration.
 * This does not recalculate the master TREESAME flag - update_treesame()
 * should be called to update it after a sequence of treesame[] modifications
 * that may have affected it.
 */
static int compact_treesame(struct rev_info *revs, struct commit *commit, unsigned nth_parent)
{
	struct treesame_state *st;
	int old_same;

	if (!commit->parents) {
		/*
		 * Have just removed the only parent from a non-merge.
		 * Different handling, as we lack decoration.
		 */
		if (nth_parent != 0)
			die("compact_treesame %u", nth_parent);
		old_same = !!(commit->object.flags & TREESAME);
		if (rev_same_tree_as_empty(revs, commit))
			commit->object.flags |= TREESAME;
		else
			commit->object.flags &= ~TREESAME;
		return old_same;
	}

	st = lookup_decoration(&revs->treesame, &commit->object);
	if (!st || nth_parent >= st->nparents)
		die("compact_treesame %u", nth_parent);

	old_same = st->treesame[nth_parent];
	memmove(st->treesame + nth_parent,
		st->treesame + nth_parent + 1,
		st->nparents - nth_parent - 1);

	/*
	 * If we've just become a non-merge commit, update TREESAME
	 * immediately, and remove the no-longer-needed decoration.
	 * If still a merge, defer update until update_treesame().
	 */
	if (--st->nparents == 1) {
		if (commit->parents->next)
			die("compact_treesame parents mismatch");
		if (st->treesame[0] && revs->dense)
			commit->object.flags |= TREESAME;
		else
			commit->object.flags &= ~TREESAME;
		free(add_decoration(&revs->treesame, &commit->object, NULL));
	}

	return old_same;
}

static unsigned update_treesame(struct rev_info *revs, struct commit *commit)
{
	if (commit->parents && commit->parents->next) {
		unsigned n;
		struct treesame_state *st;
747 748 749
		struct commit_list *p;
		unsigned relevant_parents;
		unsigned relevant_change, irrelevant_change;
750 751 752

		st = lookup_decoration(&revs->treesame, &commit->object);
		if (!st)
753
			die("update_treesame %s", oid_to_hex(&commit->object.oid));
754 755 756 757 758 759 760 761
		relevant_parents = 0;
		relevant_change = irrelevant_change = 0;
		for (p = commit->parents, n = 0; p; n++, p = p->next) {
			if (relevant_commit(p->item)) {
				relevant_change |= !st->treesame[n];
				relevant_parents++;
			} else
				irrelevant_change |= !st->treesame[n];
762
		}
763 764 765 766
		if (relevant_parents ? relevant_change : irrelevant_change)
			commit->object.flags &= ~TREESAME;
		else
			commit->object.flags |= TREESAME;
767 768 769 770 771
	}

	return commit->object.flags & TREESAME;
}

772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
static inline int limiting_can_increase_treesame(const struct rev_info *revs)
{
	/*
	 * TREESAME is irrelevant unless prune && dense;
	 * if simplify_history is set, we can't have a mixture of TREESAME and
	 *    !TREESAME INTERESTING parents (and we don't have treesame[]
	 *    decoration anyway);
	 * if first_parent_only is set, then the TREESAME flag is locked
	 *    against the first parent (and again we lack treesame[] decoration).
	 */
	return revs->prune && revs->dense &&
	       !revs->simplify_history &&
	       !revs->first_parent_only;
}

787 788 789
static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
{
	struct commit_list **pp, *parent;
790
	struct treesame_state *ts = NULL;
791 792
	int relevant_change = 0, irrelevant_change = 0;
	int relevant_parents, nth_parent;
793

794 795 796
	/*
	 * If we don't do pruning, everything is interesting
	 */
797
	if (!revs->prune)
798 799
		return;

800
	if (!get_commit_tree(commit))
801 802 803
		return;

	if (!commit->parents) {
804
		if (rev_same_tree_as_empty(revs, commit))
805
			commit->object.flags |= TREESAME;
806 807 808
		return;
	}

809 810 811 812
	/*
	 * Normal non-merge commit? If we don't want to make the
	 * history dense, we consider it always to be a change..
	 */
813
	if (!revs->dense && !commit->parents->next)
814 815
		return;

816
	for (pp = &commit->parents, nth_parent = 0, relevant_parents = 0;
817 818
	     (parent = *pp) != NULL;
	     pp = &parent->next, nth_parent++) {
819
		struct commit *p = parent->item;
820 821
		if (relevant_commit(p))
			relevant_parents++;
822

823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844
		if (nth_parent == 1) {
			/*
			 * This our second loop iteration - so we now know
			 * we're dealing with a merge.
			 *
			 * Do not compare with later parents when we care only about
			 * the first parent chain, in order to avoid derailing the
			 * traversal to follow a side branch that brought everything
			 * in the path we are limited to by the pathspec.
			 */
			if (revs->first_parent_only)
				break;
			/*
			 * If this will remain a potentially-simplifiable
			 * merge, remember per-parent treesame if needed.
			 * Initialise the array with the comparison from our
			 * first iteration.
			 */
			if (revs->treesame.name &&
			    !revs->simplify_history &&
			    !(commit->object.flags & UNINTERESTING)) {
				ts = initialise_treesame(revs, commit);
845
				if (!(irrelevant_change || relevant_change))
846 847 848
					ts->treesame[0] = 1;
			}
		}
849 850
		if (parse_commit(p) < 0)
			die("cannot simplify commit %s (because of %s)",
851 852
			    oid_to_hex(&commit->object.oid),
			    oid_to_hex(&p->object.oid));
853
		switch (rev_compare_tree(revs, p, commit)) {
854
		case REV_TREE_SAME:
855
			if (!revs->simplify_history || !relevant_commit(p)) {
856 857 858 859 860 861
				/* Even if a merge with an uninteresting
				 * side branch brought the entire change
				 * we are interested in, we do not want
				 * to lose the other branches of this
				 * merge, so we just keep going.
				 */
862 863
				if (ts)
					ts->treesame[nth_parent] = 1;
864 865
				continue;
			}
866 867
			parent->next = NULL;
			commit->parents = parent;
868
			commit->object.flags |= TREESAME;
869 870
			return;

871 872
		case REV_TREE_NEW:
			if (revs->remove_empty_trees &&
873
			    rev_same_tree_as_empty(revs, p)) {
874 875 876 877 878 879 880
				/* We are adding all the specified
				 * paths from this parent, so the
				 * history beyond this parent is not
				 * interesting.  Remove its parents
				 * (they are grandparents for us).
				 * IOW, we pretend this parent is a
				 * "root" commit.
881
				 */
882 883
				if (parse_commit(p) < 0)
					die("cannot simplify commit %s (invalid %s)",
884 885
					    oid_to_hex(&commit->object.oid),
					    oid_to_hex(&p->object.oid));
886
				p->parents = NULL;
887 888
			}
		/* fallthrough */
889
		case REV_TREE_OLD:
890
		case REV_TREE_DIFFERENT:
891 892 893 894
			if (relevant_commit(p))
				relevant_change = 1;
			else
				irrelevant_change = 1;
895 896
			continue;
		}
897
		die("bad tree compare for commit %s", oid_to_hex(&commit->object.oid));
898
	}
899 900 901 902 903 904 905 906 907 908 909 910 911

	/*
	 * TREESAME is straightforward for single-parent commits. For merge
	 * commits, it is most useful to define it so that "irrelevant"
	 * parents cannot make us !TREESAME - if we have any relevant
	 * parents, then we only consider TREESAMEness with respect to them,
	 * allowing irrelevant merges from uninteresting branches to be
	 * simplified away. Only if we have only irrelevant parents do we
	 * base TREESAME on them. Note that this logic is replicated in
	 * update_treesame, which should be kept in sync.
	 */
	if (relevant_parents ? !relevant_change : !irrelevant_change)
		commit->object.flags |= TREESAME;
912 913
}

914
static int process_parents(struct rev_info *revs, struct commit *commit,
915
			   struct commit_list **list, struct prio_queue *queue)
916 917
{
	struct commit_list *parent = commit->parents;
Junio C Hamano's avatar
Junio C Hamano committed
918
	unsigned left_flag;
919

920
	if (commit->object.flags & ADDED)
921
		return 0;
922 923
	commit->object.flags |= ADDED;

924 925 926 927
	if (revs->include_check &&
	    !revs->include_check(commit, revs->include_check_data))
		return 0;

928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943
	/*
	 * If the commit is uninteresting, don't try to
	 * prune parents - we want the maximal uninteresting
	 * set.
	 *
	 * Normally we haven't parsed the parent
	 * yet, so we won't have a parent of a parent
	 * here. However, it may turn out that we've
	 * reached this commit some other way (where it
	 * wasn't uninteresting), in which case we need
	 * to mark its parents recursively too..
	 */
	if (commit->object.flags & UNINTERESTING) {
		while (parent) {
			struct commit *p = parent->item;
			parent = parent->next;
944 945
			if (p)
				p->object.flags |= UNINTERESTING;
946
			if (parse_commit_gently(p, 1) < 0)
947
				continue;
948 949 950 951 952
			if (p->parents)
				mark_parents_uninteresting(p);
			if (p->object.flags & SEEN)
				continue;
			p->object.flags |= SEEN;
953
			if (list)
954 955 956
				commit_list_insert_by_date(p, list);
			if (queue)
				prio_queue_put(queue, p);
957
		}
958
		return 0;
959 960 961 962 963 964 965
	}

	/*
	 * Ok, the commit wasn't uninteresting. Try to
	 * simplify the commit history and find the parent
	 * that has no differences in the path set if one exists.
	 */
966
	try_to_simplify_commit(revs, commit);
967

968
	if (revs->no_walk)
969
		return 0;
970

Junio C Hamano's avatar
Junio C Hamano committed
971
	left_flag = (commit->object.flags & SYMMETRIC_LEFT);
972

973
	for (parent = commit->parents; parent; parent = parent->next) {
974
		struct commit *p = parent->item;
975 976 977 978 979 980 981 982 983
		int gently = revs->ignore_missing_links ||
			     revs->exclude_promisor_objects;
		if (parse_commit_gently(p, gently) < 0) {
			if (revs->exclude_promisor_objects &&
			    is_promisor_object(&p->object.oid)) {
				if (revs->first_parent_only)
					break;
				continue;
			}
984
			return -1;
985
		}
986 987 988 989 990 991
		if (revs->sources) {
			char **slot = revision_sources_at(revs->sources, p);

			if (!*slot)
				*slot = *revision_sources_at(revs->sources, commit);
		}
Junio C Hamano's avatar
Junio C Hamano committed
992
		p->object.flags |= left_flag;
993 994
		if (!(p->object.flags & SEEN)) {
			p->object.flags |= SEEN;
995
			if (list)
996 997 998
				commit_list_insert_by_date(p, list);
			if (queue)
				prio_queue_put(queue, p);
999
		}
1000
		if (revs->first_parent_only)
1001
			break;
1002
	}
1003
	return 0;
1004 1005
}

1006
static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
1007 1008 1009 1010 1011
{
	struct commit_list *p;
	int left_count = 0, right_count = 0;
	int left_first;
	struct patch_ids ids;
1012
	unsigned cherry_flag;
1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025

	/* First count the commits on the left and on the right */
	for (p = list; p; p = p->next) {
		struct commit *commit = p->item;
		unsigned flags = commit->object.flags;
		if (flags & BOUNDARY)
			;
		else if (flags & SYMMETRIC_LEFT)
			left_count++;
		else
			right_count++;
	}

1026 1027 1028
	if (!left_count || !right_count)
		return;

1029
	left_first = left_count < right_count;
1030
	init_patch_ids(revs->repo, &ids);
1031
	ids.diffopts.pathspec = revs->diffopt.pathspec;
1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046

	/* Compute patch-ids for one side */
	for (p = list; p; p = p->next) {
		struct commit *commit = p->item;
		unsigned flags = commit->object.flags;

		if (flags & BOUNDARY)
			continue;
		/*
		 * If we have fewer left, left_first is set and we omit
		 * commits on the right branch in this loop.  If we have
		 * fewer right, we skip the left ones.
		 */
		if (left_first != !!(flags & SYMMETRIC_LEFT))
			continue;
1047
		add_commit_patch_id(commit, &ids);
1048 1049
	}

1050 1051 1052
	/* either cherry_mark or cherry_pick are true */
	cherry_flag = revs->cherry_mark ? PATCHSAME : SHOWN;

1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
	/* Check the other side */
	for (p = list; p; p = p->next) {
		struct commit *commit = p->item;
		struct patch_id *id;
		unsigned flags = commit->object.flags;

		if (flags & BOUNDARY)
			continue;
		/*
		 * If we have fewer left, left_first is set and we omit
		 * commits on the left branch in this loop.
		 */
		if (left_first == !!(flags & SYMMETRIC_LEFT))
			continue;

		/*
		 * Have we seen the same patch id?
		 */
		id = has_commit_patch_id(commit, &ids);
		if (!id)
			continue;

1075 1076
		commit->object.flags |= cherry_flag;
		id->commit->object.flags |= cherry_flag;
1077 1078 1079 1080 1081
	}

	free_patch_ids(&ids);
}

1082 1083 1084
/* How many extra uninteresting commits we want to see.. */
#define SLOP 5

1085
static int still_interesting(struct commit_list *src, timestamp_t date, int slop,
1086
			     struct commit **interesting_cache)
1087
{
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
	/*
	 * No source list at all? We're definitely done..
	 */
	if (!src)
		return 0;

	/*
	 * Does the destination list contain entries with a date
	 * before the source list? Definitely _not_ done.
	 */
1098
	if (date <= src->item->date)
1099 1100 1101 1102 1103 1104
		return SLOP;

	/*
	 * Does the source list still have interesting commits in
	 * it? Definitely not done..
	 */
1105
	if (!everybody_uninteresting(src, interesting_cache))
1106 1107 1108 1109
		return SLOP;

	/* Ok, we're closing in.. */
	return slop-1;
1110 1111
}

1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189
/*
 * "rev-list --ancestry-path A..B" computes commits that are ancestors
 * of B but not ancestors of A but further limits the result to those
 * that are descendants of A.  This takes the list of bottom commits and
 * the result of "A..B" without --ancestry-path, and limits the latter
 * further to the ones that can reach one of the commits in "bottom".
 */
static void limit_to_ancestry(struct commit_list *bottom, struct commit_list *list)
{
	struct commit_list *p;
	struct commit_list *rlist = NULL;
	int made_progress;

	/*
	 * Reverse the list so that it will be likely that we would
	 * process parents before children.
	 */
	for (p = list; p; p = p->next)
		commit_list_insert(p->item, &rlist);

	for (p = bottom; p; p = p->next)
		p->item->object.flags |= TMP_MARK;

	/*
	 * Mark the ones that can reach bottom commits in "list",
	 * in a bottom-up fashion.
	 */
	do {
		made_progress = 0;
		for (p = rlist; p; p = p->next) {
			struct commit *c = p->item;
			struct commit_list *parents;
			if (c->object.flags & (TMP_MARK | UNINTERESTING))
				continue;
			for (parents = c->parents;
			     parents;
			     parents = parents->next) {
				if (!(parents->item->object.flags & TMP_MARK))
					continue;
				c->object.flags |= TMP_MARK;
				made_progress = 1;
				break;
			}
		}
	} while (made_progress);

	/*
	 * NEEDSWORK: decide if we want to remove parents that are
	 * not marked with TMP_MARK from commit->parents for commits
	 * in the resulting list.  We may not want to do that, though.
	 */

	/*
	 * The ones that are not marked with TMP_MARK are uninteresting
	 */
	for (p = list; p; p = p->next) {
		struct commit *c = p->item;
		if (c->object.flags & TMP_MARK)
			continue;
		c->object.flags |= UNINTERESTING;
	}

	/* We are done with the TMP_MARK */
	for (p = list; p; p = p->next)
		p->item->object.flags &= ~TMP_MARK;
	for (p = bottom; p; p = p->next)
		p->item->object.flags &= ~TMP_MARK;
	free_commit_list(rlist);
}

/*
 * Before walking the history, keep the set of "negative" refs the
 * caller has asked to exclude.
 *
 * This is used to compute "rev-list --ancestry-path A..B", as we need
 * to filter the result of "A..B" further to the ones that can actually
 * reach A.
 */
1190
static struct commit_list *collect_bottom_commits(struct commit_list *list)
1191
{
1192 1193 1194 1195
	struct commit_list *elem, *bottom = NULL;
	for (elem = list; elem; elem = elem->next)
		if (elem->item->object.flags & BOTTOM)
			commit_list_insert(elem->item, &bottom);
1196 1197 1198
	return bottom;
}

1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
/* Assumes either left_only or right_only is set */
static void limit_left_right(struct commit_list *list, struct rev_info *revs)
{
	struct commit_list *p;

	for (p = list; p; p = p->next) {
		struct commit *commit = p->item;

		if (revs->right_only) {
			if (commit->object.flags & SYMMETRIC_LEFT)
				commit->object.flags |= SHOWN;
		} else	/* revs->left_only is set */
			if (!(commit->object.flags & SYMMETRIC_LEFT))
				commit->object.flags |= SHOWN;
	}
}

1216
static int limit_list(struct rev_info *revs)
1217
{
1218
	int slop = SLOP;
1219
	timestamp_t date = TIME_MAX;
1220 1221 1222
	struct commit_list *list = revs->commits;
	struct commit_list *newlist = NULL;
	struct commit_list **p = &newlist;
1223
	struct commit_list *bottom = NULL;
1224
	struct commit *interesting_cache = NULL;
1225 1226

	if (revs->ancestry_path) {
1227
		bottom = collect_bottom_commits(list);
1228
		if (!bottom)
1229
			die("--ancestry-path given but there are no bottom commits");
1230
	}
1231 1232

	while (list) {
1233
		struct commit *commit = pop_commit(&list);
1234
		struct object *obj = &commit->object;
1235
		show_early_output_fn_t show;
1236

1237 1238 1239
		if (commit == interesting_cache)
			interesting_cache = NULL;

1240 1241
		if (revs->max_age != -1 && (commit->date < revs->max_age))
			obj->flags |= UNINTERESTING;
1242
		if (process_parents(revs, commit, &list, NULL) < 0)
1243
			return -1;
1244 1245
		if (obj->flags & UNINTERESTING) {
			mark_parents_uninteresting(commit);
1246
			slop = still_interesting(list, date, slop, &interesting_cache);
1247
			if (slop)
1248
				continue;
1249
			break;
1250 1251 1252
		}
		if (revs->min_age != -1 && (commit->date > revs->min_age))
			continue;
1253
		date = commit->date;
1254
		p = &commit_list_insert(commit, p)->next;
1255 1256 1257 1258 1259 1260 1261

		show = show_early_output;
		if (!show)
			continue;

		show(revs, newlist);
		show_early_output = NULL;
1262
	}
1263
	if (revs->cherry_pick || revs->cherry_mark)
1264
		cherry_pick_list(newlist, revs);
1265

1266 1267 1268
	if (revs->left_only || revs->right_only)
		limit_left_right(newlist, revs);

1269 1270 1271 1272 1273
	if (bottom) {
		limit_to_ancestry(bottom, newlist);
		free_commit_list(bottom);
	}

1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285
	/*
	 * Check if any commits have become TREESAME by some of their parents
	 * becoming UNINTERESTING.
	 */
	if (limiting_can_increase_treesame(revs))
		for (list = newlist; list; list = list->next) {
			struct commit *c = list->item;
			if (c->object.flags & (UNINTERESTING | TREESAME))
				continue;
			update_treesame(revs, c);
		}

1286
	revs->commits = newlist;
1287
	return 0;
1288 1289
}

1290 1291 1292 1293
/*
 * Add an entry to refs->cmdline with the specified information.
 * *name is copied.
 */
1294 1295 1296 1297 1298 1299 1300
static void add_rev_cmdline(struct rev_info *revs,
			    struct object *item,
			    const char *name,
			    int whence,
			    unsigned flags)
{
	struct rev_cmdline_info *info = &revs->cmdline;
1301
	unsigned int nr = info->nr;
1302 1303 1304

	ALLOC_GROW(info->rev, nr + 1, info->alloc);
	info->rev[nr].item = item;
1305
	info->rev[nr].name = xstrdup(name);
1306 1307 1308 1309 1310
	info->rev[nr].whence = whence;
	info->rev[nr].flags = flags;
	info->nr++;
}

1311 1312 1313 1314 1315 1316 1317
static void add_rev_cmdline_list(struct rev_info *revs,
				 struct commit_list *commit_list,
				 int whence,
				 unsigned flags)
{
	while (commit_list) {
		struct object *object = &commit_list->item->object;
1318
		add_rev_cmdline(revs, object, oid_to_hex(&object->oid),
1319 1320 1321 1322 1323
				whence, flags);
		commit_list = commit_list->next;
	}
}

1324 1325
struct all_refs_cb {
	int all_flags;
1326
	int warned_bad_reflog;
1327 1328
	struct rev_info *all_revs;
	const char *name_for_errormsg;
1329
	struct worktree *wt;
1330
};
1331

1332
int ref_excluded(struct string_list *ref_excludes, const char *path)
1333 1334 1335
{
	struct string_list_item *item;

1336
	if (!ref_excludes)
1337
		return 0;
1338
	for_each_string_list_item(item, ref_excludes) {
1339
		if (!wildmatch(item->string, path, 0))
1340 1341 1342 1343 1344
			return 1;
	}
	return 0;
}

1345 1346
static int handle_one_ref(const char *path, const struct object_id *oid,
			  int flag, void *cb_data)
1347
{
1348
	struct all_refs_cb *cb = cb_data;
1349 1350
	struct object *object;

1351
	if (ref_excluded(cb->all_revs->ref_excludes, path))
1352 1353
	    return 0;

1354
	object = get_reference(cb->all_revs, path, oid, cb->all_flags);
1355
	add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags);
1356
	add_pending_oid(cb->all_revs, path, oid, cb->all_flags);
1357 1358 1359
	return 0;
}

Ilari Liusvaara's avatar
Ilari Liusvaara committed
1360 1361 1362 1363 1364
static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs,
	unsigned flags)
{
	cb->all_revs = revs;
	cb->all_flags = flags;
1365
	revs->rev_input_given = 1;
1366
	cb->wt = NULL;
Ilari Liusvaara's avatar
Ilari Liusvaara committed
1367 1368
}

1369
void clear_ref_exclusion(struct string_list **ref_excludes_p)
1370
{
1371 1372 1373
	if (*ref_excludes_p) {
		string_list_clear(*ref_excludes_p, 0);
		free(*ref_excludes_p);
1374
	}
1375
	*ref_excludes_p = NULL;
1376 1377
}

1378
void add_ref_exclusion(struct string_list **ref_excludes_p, const char *exclude)
1379
{
1380 1381 1382
	if (!*ref_excludes_p) {
		*ref_excludes_p = xcalloc(1, sizeof(**ref_excludes_p));
		(*ref_excludes_p)->strdup_strings = 1;
1383
	}
1384
	string_list_append(*ref_excludes_p, exclude);
1385 1386
}

1387 1388 1389
static void handle_refs(struct ref_store *refs,
			struct rev_info *revs, unsigned flags,
			int (*for_each)(struct ref_store *, each_ref_fn, void *))
1390
{
1391
	struct all_refs_cb cb;
1392 1393 1394 1395 1396 1397

	if (!refs) {
		/* this could happen with uninitialized submodules */
		return;
	}

Ilari Liusvaara's avatar
Ilari Liusvaara committed
1398
	init_all_refs_cb(&cb, revs, flags);
1399
	for_each(refs, handle_one_ref, &cb);
1400 1401
}

1402
static void handle_one_reflog_commit(struct object_id *oid, void *cb_data)
1403 1404
{
	struct all_refs_cb *cb = cb_data;
1405
	if (!is_null_oid(oid)) {
1406
		struct object *o = parse_object(cb->all_revs->repo, oid);
1407 1408
		if (o) {
			o->flags |= cb->all_flags;
1409
			/* ??? CMDLINEFLAGS ??? */
1410 1411 1412
			add_pending_object(cb->all_revs, o, "");
		}
		else if (!cb->warned_bad_reflog) {
1413
			warning("reflog of '%s' references pruned commits",
1414 1415 1416
				cb->name_for_errormsg);
			cb->warned_bad_reflog = 1;
		}
1417
	}
1418 1419
}

1420
static int handle_one_reflog_ent(struct object_id *ooid, struct object_id *noid,
1421
		const char *email, timestamp_t timestamp, int tz,
1422
		const char *message, void *cb_data)
1423
{
1424 1425
	handle_one_reflog_commit(ooid, cb_data);
	handle_one_reflog_commit(noid, cb_data);
1426 1427 1428
	return 0;
}