revision.c 37.2 KB
Newer Older
1 2 3 4 5
#include "cache.h"
#include "tag.h"
#include "blob.h"
#include "tree.h"
#include "commit.h"
6
#include "diff.h"
7 8
#include "refs.h"
#include "revision.h"
9
#include "grep.h"
10
#include "reflog-walk.h"
J
Junio C Hamano 已提交
11
#include "patch-ids.h"
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36

static char *path_name(struct name_path *path, const char *name)
{
	struct name_path *p;
	char *n, *m;
	int nlen = strlen(name);
	int len = nlen + 1;

	for (p = path; p; p = p->up) {
		if (p->elem_len)
			len += p->elem_len + 1;
	}
	n = xmalloc(len);
	m = n + len - (nlen + 1);
	strcpy(m, name);
	for (p = path; p; p = p->up) {
		if (p->elem_len) {
			m -= p->elem_len + 1;
			memcpy(m, p->elem, p->elem_len);
			m[p->elem_len] = '/';
		}
	}
	return n;
}

37 38 39 40
void add_object(struct object *obj,
		struct object_array *p,
		struct name_path *path,
		const char *name)
41
{
42
	add_object_array(obj, path_name(path, name), p);
43 44 45 46 47 48 49 50 51 52 53
}

static void mark_blob_uninteresting(struct blob *blob)
{
	if (blob->object.flags & UNINTERESTING)
		return;
	blob->object.flags |= UNINTERESTING;
}

void mark_tree_uninteresting(struct tree *tree)
{
54
	struct tree_desc desc;
55
	struct name_entry entry;
56 57 58 59 60 61 62 63 64
	struct object *obj = &tree->object;

	if (obj->flags & UNINTERESTING)
		return;
	obj->flags |= UNINTERESTING;
	if (!has_sha1_file(obj->sha1))
		return;
	if (parse_tree(tree) < 0)
		die("bad tree %s", sha1_to_hex(obj->sha1));
65

66
	init_tree_desc(&desc, tree->buffer, tree->size);
67 68 69
	while (tree_entry(&desc, &entry)) {
		if (S_ISDIR(entry.mode))
			mark_tree_uninteresting(lookup_tree(entry.sha1));
70
		else
71
			mark_blob_uninteresting(lookup_blob(entry.sha1));
72
	}
73 74 75 76 77 78 79

	/*
	 * We don't care about the tree any more
	 * after it has been marked uninteresting.
	 */
	free(tree->buffer);
	tree->buffer = NULL;
80 81 82 83 84 85 86 87
}

void mark_parents_uninteresting(struct commit *commit)
{
	struct commit_list *parents = commit->parents;

	while (parents) {
		struct commit *commit = parents->item;
88 89
		if (!(commit->object.flags & UNINTERESTING)) {
			commit->object.flags |= UNINTERESTING;
90

91 92 93 94 95 96 97 98 99 100 101
			/*
			 * 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->parents)
				mark_parents_uninteresting(commit);
		}
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

		/*
		 * A missing commit is ok iff its parent is marked
		 * uninteresting.
		 *
		 * We just mark such a thing parsed, so that when
		 * it is popped next time around, we won't be trying
		 * to parse it and get an error.
		 */
		if (!has_sha1_file(commit->object.sha1))
			commit->object.parsed = 1;
		parents = parents->next;
	}
}

J
Junio C Hamano 已提交
117
static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, const char *name, unsigned mode)
118
{
L
Linus Torvalds 已提交
119 120
	if (revs->no_walk && (obj->flags & UNINTERESTING))
		die("object ranges do not make sense when not walking revisions");
121
	add_object_array_with_mode(obj, name, &revs->pending, mode);
122 123 124
	if (revs->reflog_info && obj->type == OBJ_COMMIT)
		add_reflog_for_walk(revs->reflog_info,
				(struct commit *)obj, name);
125 126
}

J
Junio C Hamano 已提交
127 128 129 130 131
void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
{
	add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
}

132
static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
133 134 135 136 137 138
{
	struct object *object;

	object = parse_object(sha1);
	if (!object)
		die("bad object %s", name);
139 140 141 142 143 144 145
	object->flags |= flags;
	return object;
}

static struct commit *handle_commit(struct rev_info *revs, struct object *object, const char *name)
{
	unsigned long flags = object->flags;
146 147 148 149

	/*
	 * Tag object? Look what it points to..
	 */
150
	while (object->type == OBJ_TAG) {
151
		struct tag *tag = (struct tag *) object;
152
		if (revs->tag_objects && !(flags & UNINTERESTING))
153 154 155 156 157 158 159 160 161 162
			add_pending_object(revs, object, tag->tag);
		object = parse_object(tag->tagged->sha1);
		if (!object)
			die("bad object %s", sha1_to_hex(tag->tagged->sha1));
	}

	/*
	 * Commit object? Just return it, we'll do all the complex
	 * reachability crud.
	 */
163
	if (object->type == OBJ_COMMIT) {
164 165 166
		struct commit *commit = (struct commit *)object;
		if (parse_commit(commit) < 0)
			die("unable to parse commit %s", name);
167
		if (flags & UNINTERESTING) {
168
			commit->object.flags |= UNINTERESTING;
169
			mark_parents_uninteresting(commit);
170 171
			revs->limited = 1;
		}
172 173 174 175 176 177 178
		return commit;
	}

	/*
	 * Tree object? Either mark it uniniteresting, or add it
	 * to the list of objects to look at later..
	 */
179
	if (object->type == OBJ_TREE) {
180 181 182 183 184 185 186 187 188 189 190 191 192 193
		struct tree *tree = (struct tree *)object;
		if (!revs->tree_objects)
			return NULL;
		if (flags & UNINTERESTING) {
			mark_tree_uninteresting(tree);
			return NULL;
		}
		add_pending_object(revs, object, "");
		return NULL;
	}

	/*
	 * Blob object? You know the drill by now..
	 */
194
	if (object->type == OBJ_BLOB) {
195 196 197 198 199 200 201 202 203 204 205 206 207
		struct blob *blob = (struct blob *)object;
		if (!revs->blob_objects)
			return NULL;
		if (flags & UNINTERESTING) {
			mark_blob_uninteresting(blob);
			return NULL;
		}
		add_pending_object(revs, object, "");
		return NULL;
	}
	die("%s is unknown object", name);
}

208 209 210 211 212 213 214 215 216 217 218 219 220
static int everybody_uninteresting(struct commit_list *orig)
{
	struct commit_list *list = orig;
	while (list) {
		struct commit *commit = list->item;
		list = list->next;
		if (commit->object.flags & UNINTERESTING)
			continue;
		return 0;
	}
	return 1;
}

221 222 223 224 225 226 227
/*
 * The goal is to get REV_TREE_NEW as the result only if the
 * diff consists of all '+' (and no other changes), and
 * REV_TREE_DIFFERENT otherwise (of course if the trees are
 * the same we want REV_TREE_SAME).  That means that once we
 * get to REV_TREE_DIFFERENT, we do not have to look any further.
 */
228
static int tree_difference = REV_TREE_SAME;
229 230 231 232 233 234

static void file_add_remove(struct diff_options *options,
		    int addremove, unsigned mode,
		    const unsigned char *sha1,
		    const char *base, const char *path)
{
235
	int diff = REV_TREE_DIFFERENT;
236 237

	/*
238 239 240 241 242
	 * Is it an add of a new file? It means that the old tree
	 * didn't have it at all, so we will turn "REV_TREE_SAME" ->
	 * "REV_TREE_NEW", but leave any "REV_TREE_DIFFERENT" alone
	 * (and if it already was "REV_TREE_NEW", we'll keep it
	 * "REV_TREE_NEW" of course).
243 244 245
	 */
	if (addremove == '+') {
		diff = tree_difference;
246
		if (diff != REV_TREE_SAME)
247
			return;
248
		diff = REV_TREE_NEW;
249 250
	}
	tree_difference = diff;
251 252
	if (tree_difference == REV_TREE_DIFFERENT)
		options->has_changes = 1;
253 254 255 256 257 258 259 260
}

static void file_change(struct diff_options *options,
		 unsigned old_mode, unsigned new_mode,
		 const unsigned char *old_sha1,
		 const unsigned char *new_sha1,
		 const char *base, const char *path)
{
261
	tree_difference = REV_TREE_DIFFERENT;
262
	options->has_changes = 1;
263 264
}

J
Junio C Hamano 已提交
265
static int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
266 267
{
	if (!t1)
268
		return REV_TREE_NEW;
269
	if (!t2)
270 271
		return REV_TREE_DIFFERENT;
	tree_difference = REV_TREE_SAME;
272
	revs->pruning.has_changes = 0;
273
	if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
274
			   &revs->pruning) < 0)
275
		return REV_TREE_DIFFERENT;
276 277 278
	return tree_difference;
}

J
Junio C Hamano 已提交
279
static int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
280 281 282
{
	int retval;
	void *tree;
283
	unsigned long size;
284 285 286 287 288
	struct tree_desc empty, real;

	if (!t1)
		return 0;

289
	tree = read_object_with_reference(t1->object.sha1, tree_type, &size, NULL);
290 291
	if (!tree)
		return 0;
292 293
	init_tree_desc(&real, tree, size);
	init_tree_desc(&empty, "", 0);
294

295
	tree_difference = REV_TREE_SAME;
296
	revs->pruning.has_changes = 0;
297
	retval = diff_tree(&empty, &real, "", &revs->pruning);
298 299
	free(tree);

300
	return retval >= 0 && (tree_difference == REV_TREE_SAME);
301 302 303 304 305
}

static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
{
	struct commit_list **pp, *parent;
L
Linus Torvalds 已提交
306
	int tree_changed = 0, tree_same = 0;
307 308 309 310 311

	if (!commit->tree)
		return;

	if (!commit->parents) {
312
		if (!rev_same_tree_as_empty(revs, commit->tree))
313 314 315 316 317 318 319 320
			commit->object.flags |= TREECHANGE;
		return;
	}

	pp = &commit->parents;
	while ((parent = *pp) != NULL) {
		struct commit *p = parent->item;

321 322 323 324
		if (parse_commit(p) < 0)
			die("cannot simplify commit %s (because of %s)",
			    sha1_to_hex(commit->object.sha1),
			    sha1_to_hex(p->object.sha1));
325
		switch (rev_compare_tree(revs, p->tree, commit->tree)) {
326
		case REV_TREE_SAME:
L
Linus Torvalds 已提交
327
			tree_same = 1;
L
Linus Torvalds 已提交
328
			if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {
329 330 331 332 333 334 335 336 337
				/* 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.
				 */
				pp = &parent->next;
				continue;
			}
338 339 340 341
			parent->next = NULL;
			commit->parents = parent;
			return;

342 343
		case REV_TREE_NEW:
			if (revs->remove_empty_trees &&
344
			    rev_same_tree_as_empty(revs, p->tree)) {
345 346 347 348 349 350 351
				/* 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.
352
				 */
353 354 355 356
				if (parse_commit(p) < 0)
					die("cannot simplify commit %s (invalid %s)",
					    sha1_to_hex(commit->object.sha1),
					    sha1_to_hex(p->object.sha1));
357
				p->parents = NULL;
358 359
			}
		/* fallthrough */
360
		case REV_TREE_DIFFERENT:
361
			tree_changed = 1;
362 363 364 365 366
			pp = &parent->next;
			continue;
		}
		die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
	}
L
Linus Torvalds 已提交
367
	if (tree_changed && !tree_same)
368
		commit->object.flags |= TREECHANGE;
369 370
}

371
static int add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
372 373
{
	struct commit_list *parent = commit->parents;
J
Junio C Hamano 已提交
374
	unsigned left_flag;
375
	int add, rest;
376

377
	if (commit->object.flags & ADDED)
378
		return 0;
379 380
	commit->object.flags |= ADDED;

381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396
	/*
	 * 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;
397 398
			if (parse_commit(p) < 0)
				return -1;
399 400 401 402 403 404 405 406
			p->object.flags |= UNINTERESTING;
			if (p->parents)
				mark_parents_uninteresting(p);
			if (p->object.flags & SEEN)
				continue;
			p->object.flags |= SEEN;
			insert_by_date(p, list);
		}
407
		return 0;
408 409 410 411 412 413 414
	}

	/*
	 * 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.
	 */
415 416
	if (revs->prune_fn)
		revs->prune_fn(revs, commit);
417

L
Linus Torvalds 已提交
418
	if (revs->no_walk)
419
		return 0;
L
Linus Torvalds 已提交
420

J
Junio C Hamano 已提交
421
	left_flag = (commit->object.flags & SYMMETRIC_LEFT);
422 423 424

	rest = !revs->first_parent_only;
	for (parent = commit->parents, add = 1; parent; add = rest) {
425 426 427
		struct commit *p = parent->item;

		parent = parent->next;
428 429
		if (parse_commit(p) < 0)
			return -1;
J
Junio C Hamano 已提交
430
		p->object.flags |= left_flag;
431 432 433
		if (p->object.flags & SEEN)
			continue;
		p->object.flags |= SEEN;
434 435
		if (add)
			insert_by_date(p, list);
436
	}
437
	return 0;
438 439
}

440
static void cherry_pick_list(struct commit_list *list, struct rev_info *revs)
J
Junio C Hamano 已提交
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
{
	struct commit_list *p;
	int left_count = 0, right_count = 0;
	int left_first;
	struct patch_ids ids;

	/* 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++;
	}

	left_first = left_count < right_count;
	init_patch_ids(&ids);
461 462 463 464 465
	if (revs->diffopt.nr_paths) {
		ids.diffopts.nr_paths = revs->diffopt.nr_paths;
		ids.diffopts.paths = revs->diffopt.paths;
		ids.diffopts.pathlens = revs->diffopt.pathlens;
	}
J
Junio C Hamano 已提交
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524

	/* 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;
		commit->util = add_commit_patch_id(commit, &ids);
	}

	/* 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;
		id->seen = 1;
		commit->object.flags |= SHOWN;
	}

	/* Now check the original side for seen ones */
	for (p = list; p; p = p->next) {
		struct commit *commit = p->item;
		struct patch_id *ent;

		ent = commit->util;
		if (!ent)
			continue;
		if (ent->seen)
			commit->object.flags |= SHOWN;
		commit->util = NULL;
	}

	free_patch_ids(&ids);
}

525
static int limit_list(struct rev_info *revs)
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540
{
	struct commit_list *list = revs->commits;
	struct commit_list *newlist = NULL;
	struct commit_list **p = &newlist;

	while (list) {
		struct commit_list *entry = list;
		struct commit *commit = list->item;
		struct object *obj = &commit->object;

		list = list->next;
		free(entry);

		if (revs->max_age != -1 && (commit->date < revs->max_age))
			obj->flags |= UNINTERESTING;
541 542
		if (add_parents_to_list(revs, commit, &list) < 0)
			return -1;
543 544 545 546 547 548 549 550 551 552
		if (obj->flags & UNINTERESTING) {
			mark_parents_uninteresting(commit);
			if (everybody_uninteresting(list))
				break;
			continue;
		}
		if (revs->min_age != -1 && (commit->date > revs->min_age))
			continue;
		p = &commit_list_insert(commit, p)->next;
	}
J
Junio C Hamano 已提交
553
	if (revs->cherry_pick)
554
		cherry_pick_list(newlist, revs);
J
Junio C Hamano 已提交
555

556
	revs->commits = newlist;
557
	return 0;
558 559
}

560 561
struct all_refs_cb {
	int all_flags;
562
	int warned_bad_reflog;
563 564 565
	struct rev_info *all_revs;
	const char *name_for_errormsg;
};
566

567
static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
568
{
569 570 571
	struct all_refs_cb *cb = cb_data;
	struct object *object = get_reference(cb->all_revs, path, sha1,
					      cb->all_flags);
572
	add_pending_object(cb->all_revs, object, path);
573 574 575 576 577
	return 0;
}

static void handle_all(struct rev_info *revs, unsigned flags)
{
578 579 580 581 582 583
	struct all_refs_cb cb;
	cb.all_revs = revs;
	cb.all_flags = flags;
	for_each_ref(handle_one_ref, &cb);
}

584
static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data)
585 586
{
	struct all_refs_cb *cb = cb_data;
587 588 589 590 591 592 593
	if (!is_null_sha1(sha1)) {
		struct object *o = parse_object(sha1);
		if (o) {
			o->flags |= cb->all_flags;
			add_pending_object(cb->all_revs, o, "");
		}
		else if (!cb->warned_bad_reflog) {
594
			warning("reflog of '%s' references pruned commits",
595 596 597
				cb->name_for_errormsg);
			cb->warned_bad_reflog = 1;
		}
598
	}
599 600
}

601 602 603
static int handle_one_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
		const char *email, unsigned long timestamp, int tz,
		const char *message, void *cb_data)
604 605 606
{
	handle_one_reflog_commit(osha1, cb_data);
	handle_one_reflog_commit(nsha1, cb_data);
607 608 609 610 611 612
	return 0;
}

static int handle_one_reflog(const char *path, const unsigned char *sha1, int flag, void *cb_data)
{
	struct all_refs_cb *cb = cb_data;
613
	cb->warned_bad_reflog = 0;
614 615 616 617 618 619 620 621 622 623
	cb->name_for_errormsg = path;
	for_each_reflog_ent(path, handle_one_reflog_ent, cb_data);
	return 0;
}

static void handle_reflog(struct rev_info *revs, unsigned flags)
{
	struct all_refs_cb cb;
	cb.all_revs = revs;
	cb.all_flags = flags;
624
	for_each_reflog(handle_one_reflog, &cb);
625 626
}

627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
{
	unsigned char sha1[20];
	struct object *it;
	struct commit *commit;
	struct commit_list *parents;

	if (*arg == '^') {
		flags ^= UNINTERESTING;
		arg++;
	}
	if (get_sha1(arg, sha1))
		return 0;
	while (1) {
		it = get_reference(revs, arg, sha1, 0);
642
		if (it->type != OBJ_TAG)
643
			break;
644
		hashcpy(sha1, ((struct tag*)it)->tagged->sha1);
645
	}
646
	if (it->type != OBJ_COMMIT)
647 648 649 650 651 652 653 654 655 656
		return 0;
	commit = (struct commit *)it;
	for (parents = commit->parents; parents; parents = parents->next) {
		it = &parents->item->object;
		it->flags |= flags;
		add_pending_object(revs, it, arg);
	}
	return 1;
}

657
void init_revisions(struct rev_info *revs, const char *prefix)
658 659
{
	memset(revs, 0, sizeof(*revs));
660

661
	revs->abbrev = DEFAULT_ABBREV;
662
	revs->ignore_merges = 1;
L
Linus Torvalds 已提交
663
	revs->simplify_history = 1;
664
	revs->pruning.recursive = 1;
665
	revs->pruning.quiet = 1;
666 667
	revs->pruning.add_remove = file_add_remove;
	revs->pruning.change = file_change;
668 669
	revs->lifo = 1;
	revs->dense = 1;
670
	revs->prefix = prefix;
671 672
	revs->max_age = -1;
	revs->min_age = -1;
J
Junio C Hamano 已提交
673
	revs->skip_count = -1;
674 675 676 677 678 679 680
	revs->max_count = -1;

	revs->prune_fn = NULL;
	revs->prune_data = NULL;

	revs->topo_setter = topo_sort_default_setter;
	revs->topo_getter = topo_sort_default_getter;
681 682 683 684

	revs->commit_format = CMIT_FMT_DEFAULT;

	diff_setup(&revs->diffopt);
685 686
}

R
Rene Scharfe 已提交
687 688 689 690 691 692 693 694 695 696 697 698
static void add_pending_commit_list(struct rev_info *revs,
                                    struct commit_list *commit_list,
                                    unsigned int flags)
{
	while (commit_list) {
		struct object *object = &commit_list->item->object;
		object->flags |= flags;
		add_pending_object(revs, object, sha1_to_hex(object->sha1));
		commit_list = commit_list->next;
	}
}

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
static void prepare_show_merge(struct rev_info *revs)
{
	struct commit_list *bases;
	struct commit *head, *other;
	unsigned char sha1[20];
	const char **prune = NULL;
	int i, prune_num = 1; /* counting terminating NULL */

	if (get_sha1("HEAD", sha1) || !(head = lookup_commit(sha1)))
		die("--merge without HEAD?");
	if (get_sha1("MERGE_HEAD", sha1) || !(other = lookup_commit(sha1)))
		die("--merge without MERGE_HEAD?");
	add_pending_object(revs, &head->object, "HEAD");
	add_pending_object(revs, &other->object, "MERGE_HEAD");
	bases = get_merge_bases(head, other, 1);
	while (bases) {
		struct commit *it = bases->item;
		struct commit_list *n = bases->next;
		free(bases);
		bases = n;
		it->object.flags |= UNINTERESTING;
		add_pending_object(revs, &it->object, "(merge-base)");
	}

	if (!active_nr)
		read_cache();
	for (i = 0; i < active_nr; i++) {
		struct cache_entry *ce = active_cache[i];
		if (!ce_stage(ce))
			continue;
		if (ce_path_match(ce, revs->prune_data)) {
			prune_num++;
			prune = xrealloc(prune, sizeof(*prune) * prune_num);
			prune[prune_num-2] = ce->name;
			prune[prune_num-1] = NULL;
		}
		while ((i+1 < active_nr) &&
		       ce_same_name(ce, active_cache[i+1]))
			i++;
	}
	revs->prune_data = prune;
}

742 743 744 745
int handle_revision_arg(const char *arg, struct rev_info *revs,
			int flags,
			int cant_be_filename)
{
746
	unsigned mode;
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
	char *dotdot;
	struct object *object;
	unsigned char sha1[20];
	int local_flags;

	dotdot = strstr(arg, "..");
	if (dotdot) {
		unsigned char from_sha1[20];
		const char *next = dotdot + 2;
		const char *this = arg;
		int symmetric = *next == '.';
		unsigned int flags_exclude = flags ^ UNINTERESTING;

		*dotdot = 0;
		next += symmetric;

		if (!*next)
			next = "HEAD";
		if (dotdot == arg)
			this = "HEAD";
		if (!get_sha1(this, from_sha1) &&
		    !get_sha1(next, sha1)) {
			struct commit *a, *b;
			struct commit_list *exclude;

			a = lookup_commit_reference(from_sha1);
			b = lookup_commit_reference(sha1);
			if (!a || !b) {
				die(symmetric ?
				    "Invalid symmetric difference expression %s...%s" :
				    "Invalid revision range %s..%s",
				    arg, next);
			}

			if (!cant_be_filename) {
				*dotdot = '.';
				verify_non_filename(revs->prefix, arg);
			}

			if (symmetric) {
				exclude = get_merge_bases(a, b, 1);
				add_pending_commit_list(revs, exclude,
							flags_exclude);
				free_commit_list(exclude);
J
Junio C Hamano 已提交
791
				a->object.flags |= flags | SYMMETRIC_LEFT;
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
			} else
				a->object.flags |= flags_exclude;
			b->object.flags |= flags;
			add_pending_object(revs, &a->object, this);
			add_pending_object(revs, &b->object, next);
			return 0;
		}
		*dotdot = '.';
	}
	dotdot = strstr(arg, "^@");
	if (dotdot && !dotdot[2]) {
		*dotdot = 0;
		if (add_parents_only(revs, arg, flags))
			return 0;
		*dotdot = '^';
	}
808 809 810 811 812 813 814
	dotdot = strstr(arg, "^!");
	if (dotdot && !dotdot[2]) {
		*dotdot = 0;
		if (!add_parents_only(revs, arg, flags ^ UNINTERESTING))
			*dotdot = '^';
	}

815 816 817 818 819
	local_flags = 0;
	if (*arg == '^') {
		local_flags = UNINTERESTING;
		arg++;
	}
820
	if (get_sha1_with_mode(arg, sha1, &mode))
821 822 823 824
		return -1;
	if (!cant_be_filename)
		verify_non_filename(revs->prefix, arg);
	object = get_reference(revs, arg, sha1, flags ^ local_flags);
825
	add_pending_object_with_mode(revs, object, arg, mode);
826 827 828
	return 0;
}

829
static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
830
{
831
	if (!revs->grep_filter) {
832 833 834 835
		struct grep_opt *opt = xcalloc(1, sizeof(*opt));
		opt->status_only = 1;
		opt->pattern_tail = &(opt->pattern_list);
		opt->regflags = REG_NEWLINE;
836
		revs->grep_filter = opt;
837
	}
838 839 840 841 842 843 844 845 846
	append_grep_pattern(revs->grep_filter, ptn,
			    "command line", 0, what);
}

static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern)
{
	char *pat;
	const char *prefix;
	int patlen, fldlen;
847 848 849

	fldlen = strlen(field);
	patlen = strlen(pattern);
850 851 852 853 854 855 856
	pat = xmalloc(patlen + fldlen + 10);
	prefix = ".*";
	if (*pattern == '^') {
		prefix = "";
		pattern++;
	}
	sprintf(pat, "^%s %s%s", field, prefix, pattern);
857
	add_grep(revs, pat, GREP_PATTERN_HEAD);
858 859 860 861
}

static void add_message_grep(struct rev_info *revs, const char *pattern)
{
862
	add_grep(revs, pattern, GREP_PATTERN_BODY);
863 864
}

865 866 867 868 869 870 871 872 873 874
static void add_ignore_packed(struct rev_info *revs, const char *name)
{
	int num = ++revs->num_ignore_packed;

	revs->ignore_packed = xrealloc(revs->ignore_packed,
				       sizeof(const char **) * (num + 1));
	revs->ignore_packed[num-1] = name;
	revs->ignore_packed[num] = NULL;
}

875 876 877 878
/*
 * Parse revision information, filling in the "rev_info" structure,
 * and removing the used arguments from the argument list.
 *
879 880
 * Returns the number of arguments left that weren't recognized
 * (which are also moved to the head of the argument list)
881
 */
882
int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def)
883
{
884
	int i, flags, seen_dashdash, show_merge;
885
	const char **unrecognized = argv + 1;
886
	int left = 1;
887
	int all_match = 0;
888
	int regflags = 0;
889 890 891 892 893 894 895 896 897

	/* First, search for "--" */
	seen_dashdash = 0;
	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];
		if (strcmp(arg, "--"))
			continue;
		argv[i] = NULL;
		argc = i;
898
		revs->prune_data = get_pathspec(revs->prefix, argv + i + 1);
899 900 901 902
		seen_dashdash = 1;
		break;
	}

903
	flags = show_merge = 0;
904 905 906
	for (i = 1; i < argc; i++) {
		const char *arg = argv[i];
		if (*arg == '-') {
907
			int opts;
908
			if (!prefixcmp(arg, "--max-count=")) {
909 910 911
				revs->max_count = atoi(arg + 12);
				continue;
			}
912
			if (!prefixcmp(arg, "--skip=")) {
J
Junio C Hamano 已提交
913 914 915
				revs->skip_count = atoi(arg + 7);
				continue;
			}
916
			/* accept -<digit>, like traditional "head" */
917 918 919 920 921 922 923 924 925 926
			if ((*arg == '-') && isdigit(arg[1])) {
				revs->max_count = atoi(arg + 1);
				continue;
			}
			if (!strcmp(arg, "-n")) {
				if (argc <= i + 1)
					die("-n requires an argument");
				revs->max_count = atoi(argv[++i]);
				continue;
			}
927
			if (!prefixcmp(arg, "-n")) {
928 929 930
				revs->max_count = atoi(arg + 2);
				continue;
			}
931
			if (!prefixcmp(arg, "--max-age=")) {
932 933 934
				revs->max_age = atoi(arg + 10);
				continue;
			}
935
			if (!prefixcmp(arg, "--since=")) {
936 937 938
				revs->max_age = approxidate(arg + 8);
				continue;
			}
939
			if (!prefixcmp(arg, "--after=")) {
940
				revs->max_age = approxidate(arg + 8);
941 942
				continue;
			}
943
			if (!prefixcmp(arg, "--min-age=")) {
944
				revs->min_age = atoi(arg + 10);
945 946
				continue;
			}
947
			if (!prefixcmp(arg, "--before=")) {
948 949 950
				revs->min_age = approxidate(arg + 9);
				continue;
			}
951
			if (!prefixcmp(arg, "--until=")) {
952 953 954
				revs->min_age = approxidate(arg + 8);
				continue;
			}
955 956 957 958
			if (!strcmp(arg, "--all")) {
				handle_all(revs, flags);
				continue;
			}
959 960 961 962
			if (!strcmp(arg, "--first-parent")) {
				revs->first_parent_only = 1;
				continue;
			}
963 964 965 966
			if (!strcmp(arg, "--reflog")) {
				handle_reflog(revs, flags);
				continue;
			}
967 968
			if (!strcmp(arg, "-g") ||
					!strcmp(arg, "--walk-reflogs")) {
969 970 971
				init_reflog_walk(&revs->reflog_info);
				continue;
			}
972 973 974 975 976 977 978 979 980 981
			if (!strcmp(arg, "--not")) {
				flags ^= UNINTERESTING;
				continue;
			}
			if (!strcmp(arg, "--default")) {
				if (++i >= argc)
					die("bad --default argument");
				def = argv[i];
				continue;
			}
982 983 984 985
			if (!strcmp(arg, "--merge")) {
				show_merge = 1;
				continue;
			}
986 987 988 989 990 991 992 993 994
			if (!strcmp(arg, "--topo-order")) {
				revs->topo_order = 1;
				continue;
			}
			if (!strcmp(arg, "--date-order")) {
				revs->lifo = 0;
				revs->topo_order = 1;
				continue;
			}
995 996 997 998
			if (!strcmp(arg, "--parents")) {
				revs->parents = 1;
				continue;
			}
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
			if (!strcmp(arg, "--dense")) {
				revs->dense = 1;
				continue;
			}
			if (!strcmp(arg, "--sparse")) {
				revs->dense = 0;
				continue;
			}
			if (!strcmp(arg, "--remove-empty")) {
				revs->remove_empty_trees = 1;
				continue;
			}
1011
			if (!strcmp(arg, "--no-merges")) {
1012 1013 1014
				revs->no_merges = 1;
				continue;
			}
J
Junio C Hamano 已提交
1015 1016 1017 1018
			if (!strcmp(arg, "--boundary")) {
				revs->boundary = 1;
				continue;
			}
1019 1020
			if (!strcmp(arg, "--left-right")) {
				revs->left_right = 1;
1021 1022
				continue;
			}
J
Junio C Hamano 已提交
1023 1024 1025 1026
			if (!strcmp(arg, "--cherry-pick")) {
				revs->cherry_pick = 1;
				continue;
			}
1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
			if (!strcmp(arg, "--objects")) {
				revs->tag_objects = 1;
				revs->tree_objects = 1;
				revs->blob_objects = 1;
				continue;
			}
			if (!strcmp(arg, "--objects-edge")) {
				revs->tag_objects = 1;
				revs->tree_objects = 1;
				revs->blob_objects = 1;
				revs->edge_hint = 1;
				continue;
			}
1040 1041
			if (!strcmp(arg, "--unpacked")) {
				revs->unpacked = 1;
1042 1043 1044 1045 1046
				free(revs->ignore_packed);
				revs->ignore_packed = NULL;
				revs->num_ignore_packed = 0;
				continue;
			}
1047
			if (!prefixcmp(arg, "--unpacked=")) {
1048 1049
				revs->unpacked = 1;
				add_ignore_packed(revs, arg+11);
1050 1051
				continue;
			}
1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068
			if (!strcmp(arg, "-r")) {
				revs->diff = 1;
				revs->diffopt.recursive = 1;
				continue;
			}
			if (!strcmp(arg, "-t")) {
				revs->diff = 1;
				revs->diffopt.recursive = 1;
				revs->diffopt.tree_in_recursive = 1;
				continue;
			}
			if (!strcmp(arg, "-m")) {
				revs->ignore_merges = 0;
				continue;
			}
			if (!strcmp(arg, "-c")) {
				revs->diff = 1;
1069
				revs->dense_combined_merges = 0;
1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
				revs->combine_merges = 1;
				continue;
			}
			if (!strcmp(arg, "--cc")) {
				revs->diff = 1;
				revs->dense_combined_merges = 1;
				revs->combine_merges = 1;
				continue;
			}
			if (!strcmp(arg, "-v")) {
				revs->verbose_header = 1;
				continue;
			}
1083
			if (!prefixcmp(arg, "--pretty")) {
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
				revs->verbose_header = 1;
				revs->commit_format = get_commit_format(arg+8);
				continue;
			}
			if (!strcmp(arg, "--root")) {
				revs->show_root_diff = 1;
				continue;
			}
			if (!strcmp(arg, "--no-commit-id")) {
				revs->no_commit_id = 1;
				continue;
			}
			if (!strcmp(arg, "--always")) {
				revs->always_show_header = 1;
				continue;
			}
			if (!strcmp(arg, "--no-abbrev")) {
				revs->abbrev = 0;
				continue;
			}
			if (!strcmp(arg, "--abbrev")) {
				revs->abbrev = DEFAULT_ABBREV;
				continue;
			}
1108
			if (!prefixcmp(arg, "--abbrev=")) {
1109 1110 1111 1112 1113 1114 1115
				revs->abbrev = strtoul(arg + 9, NULL, 10);
				if (revs->abbrev < MINIMUM_ABBREV)
					revs->abbrev = MINIMUM_ABBREV;
				else if (revs->abbrev > 40)
					revs->abbrev = 40;
				continue;
			}
1116 1117 1118 1119 1120 1121 1122 1123 1124
			if (!strcmp(arg, "--abbrev-commit")) {
				revs->abbrev_commit = 1;
				continue;
			}
			if (!strcmp(arg, "--full-diff")) {
				revs->diff = 1;
				revs->full_diff = 1;
				continue;
			}
L
Linus Torvalds 已提交
1125 1126 1127 1128
			if (!strcmp(arg, "--full-history")) {
				revs->simplify_history = 0;
				continue;
			}
1129
			if (!strcmp(arg, "--relative-date")) {
1130 1131 1132 1133 1134 1135
				revs->date_mode = DATE_RELATIVE;
				continue;
			}
			if (!strncmp(arg, "--date=", 7)) {
				if (!strcmp(arg + 7, "relative"))
					revs->date_mode = DATE_RELATIVE;
1136 1137 1138 1139 1140 1141 1142 1143
				else if (!strcmp(arg + 7, "iso8601") ||
					 !strcmp(arg + 7, "iso"))
					revs->date_mode = DATE_ISO8601;
				else if (!strcmp(arg + 7, "rfc2822") ||
					 !strcmp(arg + 7, "rfc"))
					revs->date_mode = DATE_RFC2822;
				else if (!strcmp(arg + 7, "short"))
					revs->date_mode = DATE_SHORT;
1144 1145 1146 1147 1148 1149
				else if (!strcmp(arg + 7, "local"))
					revs->date_mode = DATE_LOCAL;
				else if (!strcmp(arg + 7, "default"))
					revs->date_mode = DATE_NORMAL;
				else
					die("unknown date format %s", arg);
1150 1151
				continue;
			}
1152 1153 1154 1155

			/*
			 * Grepping the commit log
			 */
1156
			if (!prefixcmp(arg, "--author=")) {
1157 1158 1159
				add_header_grep(revs, "author", arg+9);
				continue;
			}
1160
			if (!prefixcmp(arg, "--committer=")) {
1161 1162 1163
				add_header_grep(revs, "committer", arg+12);
				continue;
			}
1164
			if (!prefixcmp(arg, "--grep=")) {
1165 1166 1167
				add_message_grep(revs, arg+7);
				continue;
			}
1168 1169 1170 1171 1172 1173 1174 1175
			if (!prefixcmp(arg, "--extended-regexp")) {
				regflags |= REG_EXTENDED;
				continue;
			}
			if (!prefixcmp(arg, "--regexp-ignore-case")) {
				regflags |= REG_ICASE;
				continue;
			}
1176 1177 1178 1179
			if (!strcmp(arg, "--all-match")) {
				all_match = 1;
				continue;
			}
1180
			if (!prefixcmp(arg, "--encoding=")) {
1181 1182
				arg += 11;
				if (strcmp(arg, "none"))
1183
					git_log_output_encoding = xstrdup(arg);
1184 1185 1186 1187
				else
					git_log_output_encoding = "";
				continue;
			}
1188 1189 1190 1191
			if (!strcmp(arg, "--reverse")) {
				revs->reverse ^= 1;
				continue;
			}
1192

1193 1194
			opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
			if (opts > 0) {
J
Junio C Hamano 已提交
1195 1196
				if (strcmp(argv[i], "-z"))
					revs->diff = 1;
1197 1198 1199
				i += opts - 1;
				continue;
			}
1200 1201 1202 1203 1204
			*unrecognized++ = arg;
			left++;
			continue;
		}

1205 1206 1207
		if (handle_revision_arg(arg, revs, flags, seen_dashdash)) {
			int j;
			if (seen_dashdash || *arg == '^')
1208 1209
				die("bad revision '%s'", arg);

1210 1211 1212 1213 1214 1215
			/* If we didn't have a "--":
			 * (1) all filenames must exist;
			 * (2) all rev-args must not be interpretable
			 *     as a valid filename.
			 * but the latter we have checked in the main loop.
			 */
1216 1217 1218
			for (j = i; j < argc; j++)
				verify_filename(revs->prefix, argv[j]);

1219 1220
			revs->prune_data = get_pathspec(revs->prefix,
							argv + i);
1221 1222 1223
			break;
		}
	}
1224

1225 1226 1227
	if (revs->grep_filter)
		revs->grep_filter->regflags |= regflags;

1228 1229
	if (show_merge)
		prepare_show_merge(revs);
1230
	if (def && !revs->pending.nr) {
1231
		unsigned char sha1[20];
1232
		struct object *object;
1233 1234
		unsigned mode;
		if (get_sha1_with_mode(def, sha1, &mode))
1235
			die("bad default revision '%s'", def);
1236
		object = get_reference(revs, def, sha1, 0);
1237
		add_pending_object_with_mode(revs, object, def, mode);
1238
	}
1239

1240
	if (revs->topo_order)
1241 1242
		revs->limited = 1;

1243
	if (revs->prune_data) {
1244
		diff_tree_setup_paths(revs->prune_data, &revs->pruning);
1245 1246 1247
		/* Can't prune commits with rename following: the paths change.. */
		if (!revs->diffopt.follow_renames)
			revs->prune_fn = try_to_simplify_commit;
1248 1249
		if (!revs->full_diff)
			diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
1250
	}
1251 1252
	if (revs->combine_merges) {
		revs->ignore_merges = 0;
1253
		if (revs->dense_combined_merges && !revs->diffopt.output_format)
1254 1255 1256
			revs->diffopt.output_format = DIFF_FORMAT_PATCH;
	}
	revs->diffopt.abbrev = revs->abbrev;
1257 1258
	if (diff_setup_done(&revs->diffopt) < 0)
		die("diff_setup_done failed");
1259

1260 1261
	if (revs->grep_filter) {
		revs->grep_filter->all_match = all_match;
1262
		compile_grep_patterns(revs->grep_filter);
1263
	}
1264

1265 1266
	return left;
}
1267

1268
int prepare_revision_walk(struct rev_info *revs)
1269
{
1270
	int nr = revs->pending.nr;
1271
	struct object_array_entry *e, *list;
1272

1273
	e = list = revs->pending.objects;
1274 1275 1276 1277
	revs->pending.nr = 0;
	revs->pending.alloc = 0;
	revs->pending.objects = NULL;
	while (--nr >= 0) {
1278
		struct commit *commit = handle_commit(revs, e->item, e->name);
1279 1280 1281 1282 1283 1284
		if (commit) {
			if (!(commit->object.flags & SEEN)) {
				commit->object.flags |= SEEN;
				insert_by_date(commit, &revs->commits);
			}
		}
1285
		e++;
1286
	}
1287
	free(list);
1288

L
Linus Torvalds 已提交
1289
	if (revs->no_walk)
1290
		return 0;
1291
	if (revs->limited)
1292 1293
		if (limit_list(revs) < 0)
			return -1;
1294
	if (revs->topo_order)
1295 1296 1297
		sort_in_topological_order_fn(&revs->commits, revs->lifo,
					     revs->topo_setter,
					     revs->topo_getter);
1298
	return 0;
1299 1300
}

1301 1302 1303 1304 1305 1306 1307
enum rewrite_result {
	rewrite_one_ok,
	rewrite_one_noparents,
	rewrite_one_error,
};

static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)
1308 1309 1310
{
	for (;;) {
		struct commit *p = *pp;
1311
		if (!revs->limited)
1312 1313
			if (add_parents_to_list(revs, p, &revs->commits) < 0)
				return rewrite_one_error;
L
Linus Torvalds 已提交
1314
		if (p->parents && p->parents->next)
1315
			return rewrite_one_ok;
1316
		if (p->object.flags & (TREECHANGE | UNINTERESTING))
1317
			return rewrite_one_ok;
1318
		if (!p->parents)
1319
			return rewrite_one_noparents;
1320 1321 1322 1323
		*pp = p->parents->item;
	}
}

1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
static void remove_duplicate_parents(struct commit *commit)
{
	struct commit_list *p;
	struct commit_list **pp = &commit->parents;

	/* Examine existing parents while marking ones we have seen... */
	for (p = commit->parents; p; p = p->next) {
		struct commit *parent = p->item;
		if (parent->object.flags & TMP_MARK)
			continue;
		parent->object.flags |= TMP_MARK;
		*pp = p;
		pp = &p->next;
	}
	/* ... and clear the temporary mark */
	for (p = commit->parents; p; p = p->next)
		p->item->object.flags &= ~TMP_MARK;
}

1343
static int rewrite_parents(struct rev_info *revs, struct commit *commit)
1344 1345 1346 1347
{
	struct commit_list **pp = &commit->parents;
	while (*pp) {
		struct commit_list *parent = *pp;
1348 1349 1350 1351
		switch (rewrite_one(revs, &parent->item)) {
		case rewrite_one_ok:
			break;
		case rewrite_one_noparents:
1352 1353
			*pp = parent->next;
			continue;
1354 1355
		case rewrite_one_error:
			return -1;
1356 1357 1358
		}
		pp = &parent->next;
	}
1359
	remove_duplicate_parents(commit);
1360
	return 0;
1361 1362
}

1363 1364
static int commit_match(struct commit *commit, struct rev_info *opt)
{
1365
	if (!opt->grep_filter)
1366
		return 1;
1367 1368 1369
	return grep_buffer(opt->grep_filter,
			   NULL, /* we say nothing, not even filename */
			   commit->buffer, strlen(commit->buffer));
1370 1371
}

J
Junio C Hamano 已提交
1372
static struct commit *get_revision_1(struct rev_info *revs)
1373
{
J
Junio C Hamano 已提交
1374
	if (!revs->commits)
1375 1376
		return NULL;

1377
	do {
L
Linus Torvalds 已提交
1378 1379
		struct commit_list *entry = revs->commits;
		struct commit *commit = entry->item;
1380

L
Linus Torvalds 已提交
1381 1382
		revs->commits = entry->next;
		free(entry);
1383

1384 1385 1386
		if (revs->reflog_info)
			fake_reflog_parent(revs->reflog_info, commit);

1387 1388
		/*
		 * If we haven't done the list limiting, we need to look at
1389 1390
		 * the parents here. We also need to do the date-based limiting
		 * that we'd otherwise have done in limit_list().
1391
		 */
1392
		if (!revs->limited) {
1393
			if (revs->max_age != -1 &&
1394 1395
			    (commit->date < revs->max_age))
				continue;
1396 1397
			if (add_parents_to_list(revs, commit, &revs->commits) < 0)
				return NULL;
1398
		}
J
Junio C Hamano 已提交
1399
		if (commit->object.flags & SHOWN)
1400
			continue;
1401

1402 1403 1404 1405
		if (revs->unpacked && has_sha1_pack(commit->object.sha1,
						    revs->ignore_packed))
		    continue;

1406
		if (commit->object.flags & UNINTERESTING)
1407
			continue;
1408
		if (revs->min_age != -1 && (commit->date > revs->min_age))
1409
			continue;
J
Junio C Hamano 已提交
1410 1411
		if (revs->no_merges &&
		    commit->parents && commit->parents->next)
1412
			continue;
1413 1414
		if (!commit_match(commit, revs))
			continue;
1415
		if (revs->prune_fn && revs->dense) {
L
Linus Torvalds 已提交
1416 1417 1418 1419 1420 1421
			/* Commit without changes? */
			if (!(commit->object.flags & TREECHANGE)) {
				/* drop merges unless we want parenthood */
				if (!revs->parents)
					continue;
				/* non-merge - always ignore it */
1422
				if (!commit->parents || !commit->parents->next)
L
Linus Torvalds 已提交
1423 1424
					continue;
			}
1425 1426
			if (revs->parents && rewrite_parents(revs, commit) < 0)
				return NULL;
J
Junio C Hamano 已提交
1427
		}
1428 1429 1430 1431
		return commit;
	} while (revs->commits);
	return NULL;
}
J
Junio C Hamano 已提交
1432

1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447
static void gc_boundary(struct object_array *array)
{
	unsigned nr = array->nr;
	unsigned alloc = array->alloc;
	struct object_array_entry *objects = array->objects;

	if (alloc <= nr) {
		unsigned i, j;
		for (i = j = 0; i < nr; i++) {
			if (objects[i].item->flags & SHOWN)
				continue;
			if (i != j)
				objects[j] = objects[i];
			j++;
		}
1448
		for (i = j; i < nr; i++)
1449 1450 1451 1452 1453
			objects[i].item = NULL;
		array->nr = j;
	}
}

J
Junio C Hamano 已提交
1454 1455 1456
struct commit *get_revision(struct rev_info *revs)
{
	struct commit *c = NULL;
1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470
	struct commit_list *l;

	if (revs->boundary == 2) {
		unsigned i;
		struct object_array *array = &revs->boundary_commits;
		struct object_array_entry *objects = array->objects;
		for (i = 0; i < array->nr; i++) {
			c = (struct commit *)(objects[i].item);
			if (!c)
				continue;
			if (!(c->object.flags & CHILD_SHOWN))
				continue;
			if (!(c->object.flags & SHOWN))
				break;
1471
		}
1472
		if (array->nr <= i)
1473
			return NULL;
1474 1475

		c->object.flags |= SHOWN | BOUNDARY;
1476 1477 1478
		return c;
	}

1479
	if (revs->reverse) {
1480 1481 1482 1483 1484 1485 1486
		int limit = -1;

		if (0 <= revs->max_count) {
			limit = revs->max_count;
			if (0 < revs->skip_count)
				limit += revs->skip_count;
		}
1487
		l = NULL;
1488
		while ((c = get_revision_1(revs))) {
1489
			commit_list_insert(c, &l);
1490 1491 1492
			if ((0 < limit) && !--limit)
				break;
		}
1493 1494
		revs->commits = l;
		revs->reverse = 0;
1495
		revs->max_count = -1;
1496
		c = NULL;
J
Junio C Hamano 已提交
1497 1498
	}

1499 1500 1501
	/*
	 * Now pick up what they want to give us
	 */
1502 1503 1504 1505 1506 1507 1508 1509
	c = get_revision_1(revs);
	if (c) {
		while (0 < revs->skip_count) {
			revs->skip_count--;
			c = get_revision_1(revs);
			if (!c)
				break;
		}
1510 1511 1512 1513 1514
	}

	/*
	 * Check the max_count.
	 */
J
Junio C Hamano 已提交
1515 1516 1517 1518
	switch (revs->max_count) {
	case -1:
		break;
	case 0:
1519 1520
		c = NULL;
		break;
J
Junio C Hamano 已提交
1521 1522 1523
	default:
		revs->max_count--;
	}
1524

1525 1526 1527 1528
	if (c)
		c->object.flags |= SHOWN;

	if (!revs->boundary) {
J
Junio C Hamano 已提交
1529
		return c;
1530
	}
1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551

	if (!c) {
		/*
		 * get_revision_1() runs out the commits, and
		 * we are done computing the boundaries.
		 * switch to boundary commits output mode.
		 */
		revs->boundary = 2;
		return get_revision(revs);
	}

	/*
	 * boundary commits are the commits that are parents of the
	 * ones we got from get_revision_1() but they themselves are
	 * not returned from get_revision_1().  Before returning
	 * 'c', we need to mark its parents that they could be boundaries.
	 */

	for (l = c->parents; l; l = l->next) {
		struct object *p;
		p = &(l->item->object);
1552
		if (p->flags & (CHILD_SHOWN | SHOWN))
1553 1554 1555 1556 1557 1558 1559
			continue;
		p->flags |= CHILD_SHOWN;
		gc_boundary(&revs->boundary_commits);
		add_object_array(p, NULL, &revs->boundary_commits);
	}

	return c;
J
Junio C Hamano 已提交
1560
}