if (parse_tree(tree) < 0)
die("bad tree %s", sha1_to_hex(obj->sha1));
- desc.buf = tree->buffer;
- desc.size = tree->size;
+ init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
mark_tree_uninteresting(lookup_tree(entry.sha1));
return 1;
}
+/*
+ * 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.
+ */
static int tree_difference = REV_TREE_SAME;
static void file_add_remove(struct diff_options *options,
diff = REV_TREE_NEW;
}
tree_difference = diff;
+ if (tree_difference == REV_TREE_DIFFERENT)
+ options->has_changes = 1;
}
static void file_change(struct diff_options *options,
const char *base, const char *path)
{
tree_difference = REV_TREE_DIFFERENT;
+ options->has_changes = 1;
}
int rev_compare_tree(struct rev_info *revs, struct tree *t1, struct tree *t2)
if (!t2)
return REV_TREE_DIFFERENT;
tree_difference = REV_TREE_SAME;
+ revs->pruning.has_changes = 0;
if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
&revs->pruning) < 0)
return REV_TREE_DIFFERENT;
{
int retval;
void *tree;
+ unsigned long size;
struct tree_desc empty, real;
if (!t1)
return 0;
- tree = read_object_with_reference(t1->object.sha1, tree_type, &real.size, NULL);
+ tree = read_object_with_reference(t1->object.sha1, tree_type, &size, NULL);
if (!tree)
return 0;
- real.buf = tree;
+ init_tree_desc(&real, tree, size);
+ init_tree_desc(&empty, "", 0);
- empty.buf = "";
- empty.size = 0;
-
- tree_difference = 0;
+ tree_difference = REV_TREE_SAME;
+ revs->pruning.has_changes = 0;
retval = diff_tree(&empty, &real, "", &revs->pruning);
free(tree);
- return retval >= 0 && !tree_difference;
+ return retval >= 0 && (tree_difference == REV_TREE_SAME);
}
static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
revs->ignore_merges = 1;
revs->simplify_history = 1;
revs->pruning.recursive = 1;
+ revs->pruning.quiet = 1;
revs->pruning.add_remove = file_add_remove;
revs->pruning.change = file_change;
revs->lifo = 1;
if (!prefixcmp(arg, "--encoding=")) {
arg += 11;
if (strcmp(arg, "none"))
- git_log_output_encoding = strdup(arg);
+ git_log_output_encoding = xstrdup(arg);
else
git_log_output_encoding = "";
continue;
if (revs->parents)
rewrite_parents(revs, commit);
}
- commit->object.flags |= SHOWN;
return commit;
} while (revs->commits);
return NULL;
objects[j] = objects[i];
j++;
}
- for (i = j; j < nr; j++)
+ for (i = j; i < nr; i++)
objects[i].item = NULL;
array->nr = j;
}
}
if (revs->reverse) {
+ int limit = -1;
+
+ if (0 <= revs->max_count) {
+ limit = revs->max_count;
+ if (0 < revs->skip_count)
+ limit += revs->skip_count;
+ }
l = NULL;
- while ((c = get_revision_1(revs)))
+ while ((c = get_revision_1(revs))) {
commit_list_insert(c, &l);
+ if ((0 < limit) && !--limit)
+ break;
+ }
revs->commits = l;
revs->reverse = 0;
+ revs->max_count = -1;
c = NULL;
}
/*
* Now pick up what they want to give us
*/
- if (!(c = get_revision_1(revs)))
- return NULL;
- while (0 < revs->skip_count) {
- revs->skip_count--;
- c = get_revision_1(revs);
- if (!c)
- break;
- /* Although we grabbed it, it is not shown. */
- c->object.flags &= ~SHOWN;
+ c = get_revision_1(revs);
+ if (c) {
+ while (0 < revs->skip_count) {
+ revs->skip_count--;
+ c = get_revision_1(revs);
+ if (!c)
+ break;
+ }
}
/*
case -1:
break;
case 0:
- /* Although we grabbed it, it is not shown. */
- if (c)
- c->object.flags &= ~SHOWN;
c = NULL;
break;
default:
revs->max_count--;
}
- if (!revs->boundary)
+ if (c)
+ c->object.flags |= SHOWN;
+
+ if (!revs->boundary) {
return c;
+ }
if (!c) {
/*
for (l = c->parents; l; l = l->next) {
struct object *p;
p = &(l->item->object);
- if (p->flags & CHILD_SHOWN)
+ if (p->flags & (CHILD_SHOWN | SHOWN))
continue;
p->flags |= CHILD_SHOWN;
gc_boundary(&revs->boundary_commits);