void mark_tree_uninteresting(struct tree *tree)
{
+ struct tree_desc desc;
+ struct name_entry entry;
struct object *obj = &tree->object;
- struct tree_entry_list *entry;
if (obj->flags & UNINTERESTING)
return;
return;
if (parse_tree(tree) < 0)
die("bad tree %s", sha1_to_hex(obj->sha1));
- entry = tree->entries;
- tree->entries = NULL;
- while (entry) {
- struct tree_entry_list *next = entry->next;
- if (entry->directory)
- mark_tree_uninteresting(lookup_tree(entry->sha1));
+
+ desc.buf = tree->buffer;
+ desc.size = tree->size;
+ while (tree_entry(&desc, &entry)) {
+ if (S_ISDIR(entry.mode))
+ mark_tree_uninteresting(lookup_tree(entry.sha1));
else
- mark_blob_uninteresting(lookup_blob(entry->sha1));
- free(entry);
- entry = next;
+ mark_blob_uninteresting(lookup_blob(entry.sha1));
}
+
+ /*
+ * We don't care about the tree any more
+ * after it has been marked uninteresting.
+ */
+ free(tree->buffer);
+ tree->buffer = NULL;
}
void mark_parents_uninteresting(struct commit *commit)
/*
* Tag object? Look what it points to..
*/
- while (object->type == tag_type) {
+ while (object->type == TYPE_TAG) {
struct tag *tag = (struct tag *) object;
if (revs->tag_objects && !(flags & UNINTERESTING))
add_pending_object(revs, object, tag->tag);
* Commit object? Just return it, we'll do all the complex
* reachability crud.
*/
- if (object->type == commit_type) {
+ if (object->type == TYPE_COMMIT) {
struct commit *commit = (struct commit *)object;
if (parse_commit(commit) < 0)
die("unable to parse commit %s", name);
* Tree object? Either mark it uniniteresting, or add it
* to the list of objects to look at later..
*/
- if (object->type == tree_type) {
+ if (object->type == TYPE_TREE) {
struct tree *tree = (struct tree *)object;
if (!revs->tree_objects)
return NULL;
/*
* Blob object? You know the drill by now..
*/
- if (object->type == blob_type) {
+ if (object->type == TYPE_BLOB) {
struct blob *blob = (struct blob *)object;
if (!revs->blob_objects)
return NULL;
parse_commit(p);
switch (rev_compare_tree(revs, p->tree, commit->tree)) {
case REV_TREE_SAME:
- if (p->object.flags & UNINTERESTING) {
+ if (!revs->simplify_history || (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
return 0;
while (1) {
it = get_reference(revs, arg, sha1, 0);
- if (strcmp(it->type, tag_type))
+ if (it->type != TYPE_TAG)
break;
memcpy(sha1, ((struct tag*)it)->tagged->sha1, 20);
}
- if (strcmp(it->type, commit_type))
+ if (it->type != TYPE_COMMIT)
return 0;
commit = (struct commit *)it;
for (parents = commit->parents; parents; parents = parents->next) {
revs->abbrev = DEFAULT_ABBREV;
revs->ignore_merges = 1;
+ revs->simplify_history = 1;
revs->pruning.recursive = 1;
revs->pruning.add_remove = file_add_remove;
revs->pruning.change = file_change;
revs->full_diff = 1;
continue;
}
+ if (!strcmp(arg, "--full-history")) {
+ revs->simplify_history = 0;
+ continue;
+ }
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
if (opts > 0) {
revs->diff = 1;
}
do {
- struct commit *commit = revs->commits->item;
+ struct commit_list *entry = revs->commits;
+ struct commit *commit = entry->item;
- revs->commits = revs->commits->next;
+ revs->commits = entry->next;
+ free(entry);
/*
* If we haven't done the list limiting, we need to look at