while (parents) {
struct commit *commit = parents->item;
- 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..
- */
- if (commit->parents)
- mark_parents_uninteresting(commit);
+ if (!(commit->object.flags & UNINTERESTING)) {
+ 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..
+ */
+ if (commit->parents)
+ mark_parents_uninteresting(commit);
+ }
/*
* A missing commit is ok iff its parent is marked
static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
{
struct commit_list **pp, *parent;
+ int tree_changed = 0;
if (!commit->tree)
return;
while ((parent = *pp) != NULL) {
struct commit *p = parent->item;
- if (p->object.flags & UNINTERESTING) {
- pp = &parent->next;
- continue;
- }
-
parse_commit(p);
switch (compare_tree(p->tree, commit->tree)) {
case TREE_SAME:
+ if (p->object.flags & UNINTERESTING) {
+ /* 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;
+ }
parent->next = NULL;
commit->parents = parent;
return;
}
/* fallthrough */
case TREE_DIFFERENT:
+ tree_changed = 1;
pp = &parent->next;
continue;
}
die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
}
- commit->object.flags |= TREECHANGE;
+ if (tree_changed)
+ commit->object.flags |= TREECHANGE;
}
static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
struct commit *get_revision(struct rev_info *revs)
{
struct commit_list *list = revs->commits;
- struct commit *commit;
if (!list)
return NULL;
/* Check the max_count ... */
- commit = list->item;
switch (revs->max_count) {
case -1:
break;
}
do {
- commit = pop_most_recent_commit(&revs->commits, SEEN);
+ struct commit *commit = revs->commits->item;
+
if (commit->object.flags & (UNINTERESTING|SHOWN))
- continue;
+ goto next;
if (revs->min_age != -1 && (commit->date > revs->min_age))
- continue;
+ goto next;
if (revs->max_age != -1 && (commit->date < revs->max_age))
return NULL;
if (revs->no_merges && commit->parents && commit->parents->next)
- continue;
+ goto next;
if (revs->paths && revs->dense) {
if (!(commit->object.flags & TREECHANGE))
- continue;
+ goto next;
rewrite_parents(commit);
}
+ /* More to go? */
+ if (revs->max_count)
+ pop_most_recent_commit(&revs->commits, SEEN);
commit->object.flags |= SHOWN;
return commit;
+next:
+ pop_most_recent_commit(&revs->commits, SEEN);
} while (revs->commits);
return NULL;
}