static void mark_blob_uninteresting(struct blob *blob)
{
+ if (!blob)
+ return;
if (blob->object.flags & UNINTERESTING)
return;
blob->object.flags |= UNINTERESTING;
struct name_entry entry;
struct object *obj = &tree->object;
+ if (!tree)
+ return;
if (obj->flags & UNINTERESTING)
return;
obj->flags |= UNINTERESTING;
init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
- if (S_ISDIR(entry.mode))
+ switch (object_type(entry.mode)) {
+ case OBJ_TREE:
mark_tree_uninteresting(lookup_tree(entry.sha1));
- else
+ break;
+ case OBJ_BLOB:
mark_blob_uninteresting(lookup_blob(entry.sha1));
+ break;
+ default:
+ /* Subproject commit - not in this repository */
+ break;
+ }
}
/*
add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
}
+void add_head_to_pending(struct rev_info *revs)
+{
+ unsigned char sha1[20];
+ struct object *obj;
+ if (get_sha1("HEAD", sha1))
+ return;
+ obj = parse_object(sha1);
+ if (!obj)
+ return;
+ add_pending_object(revs, obj, "HEAD");
+}
+
static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
{
struct object *object;
struct tag *tag = (struct tag *) object;
if (revs->tag_objects && !(flags & UNINTERESTING))
add_pending_object(revs, object, tag->tag);
+ if (!tag->tagged)
+ die("bad tag");
object = parse_object(tag->tagged->sha1);
if (!object)
die("bad object %s", sha1_to_hex(tag->tagged->sha1));
}
tree_difference = diff;
if (tree_difference == REV_TREE_DIFFERENT)
- options->has_changes = 1;
+ DIFF_OPT_SET(options, HAS_CHANGES);
}
static void file_change(struct diff_options *options,
const char *base, const char *path)
{
tree_difference = REV_TREE_DIFFERENT;
- options->has_changes = 1;
+ DIFF_OPT_SET(options, HAS_CHANGES);
}
static 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;
+ DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "",
&revs->pruning) < 0)
return REV_TREE_DIFFERENT;
init_tree_desc(&empty, "", 0);
tree_difference = REV_TREE_SAME;
- revs->pruning.has_changes = 0;
+ DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES);
retval = diff_tree(&empty, &real, "", &revs->pruning);
free(tree);
struct commit_list **pp, *parent;
int tree_changed = 0, tree_same = 0;
+ /*
+ * If we don't do pruning, everything is interesting
+ */
+ if (!revs->prune)
+ return;
+
if (!commit->tree)
return;
if (!commit->parents) {
- if (!rev_same_tree_as_empty(revs, commit->tree))
- commit->object.flags |= TREECHANGE;
+ if (rev_same_tree_as_empty(revs, commit->tree))
+ commit->object.flags |= TREESAME;
return;
}
+ /*
+ * Normal non-merge commit? If we don't want to make the
+ * history dense, we consider it always to be a change..
+ */
+ if (!revs->dense && !commit->parents->next)
+ return;
+
pp = &commit->parents;
while ((parent = *pp) != NULL) {
struct commit *p = parent->item;
}
parent->next = NULL;
commit->parents = parent;
+ commit->object.flags |= TREESAME;
return;
case REV_TREE_NEW:
die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
}
if (tree_changed && !tree_same)
- commit->object.flags |= TREECHANGE;
+ return;
+ commit->object.flags |= TREESAME;
}
static int add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)
* simplify the commit history and find the parent
* that has no differences in the path set if one exists.
*/
- if (revs->prune_fn)
- revs->prune_fn(revs, commit);
+ try_to_simplify_commit(revs, commit);
if (revs->no_walk)
return 0;
it = get_reference(revs, arg, sha1, 0);
if (it->type != OBJ_TAG)
break;
+ if (!((struct tag*)it)->tagged)
+ return 0;
hashcpy(sha1, ((struct tag*)it)->tagged->sha1);
}
if (it->type != OBJ_COMMIT)
revs->abbrev = DEFAULT_ABBREV;
revs->ignore_merges = 1;
revs->simplify_history = 1;
- revs->pruning.recursive = 1;
- revs->pruning.quiet = 1;
+ DIFF_OPT_SET(&revs->pruning, RECURSIVE);
+ DIFF_OPT_SET(&revs->pruning, QUIET);
revs->pruning.add_remove = file_add_remove;
revs->pruning.change = file_change;
revs->lifo = 1;
revs->skip_count = -1;
revs->max_count = -1;
- revs->prune_fn = NULL;
- revs->prune_data = NULL;
-
revs->commit_format = CMIT_FMT_DEFAULT;
diff_setup(&revs->diffopt);
}
if (!strcmp(arg, "-r")) {
revs->diff = 1;
- revs->diffopt.recursive = 1;
+ DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
continue;
}
if (!strcmp(arg, "-t")) {
revs->diff = 1;
- revs->diffopt.recursive = 1;
- revs->diffopt.tree_in_recursive = 1;
+ DIFF_OPT_SET(&revs->diffopt, RECURSIVE);
+ DIFF_OPT_SET(&revs->diffopt, TREE_IN_RECURSIVE);
continue;
}
if (!strcmp(arg, "-m")) {
if (revs->diffopt.output_format & ~DIFF_FORMAT_NO_OUTPUT)
revs->diff = 1;
- /* Pickaxe and rename following needs diffs */
- if (revs->diffopt.pickaxe || revs->diffopt.follow_renames)
+ /* Pickaxe, diff-filter and rename following need diffs */
+ if (revs->diffopt.pickaxe ||
+ revs->diffopt.filter ||
+ DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
revs->diff = 1;
if (revs->topo_order)
if (revs->prune_data) {
diff_tree_setup_paths(revs->prune_data, &revs->pruning);
/* Can't prune commits with rename following: the paths change.. */
- if (!revs->diffopt.follow_renames)
- revs->prune_fn = try_to_simplify_commit;
+ if (!DIFF_OPT_TST(&revs->diffopt, FOLLOW_RENAMES))
+ revs->prune = 1;
if (!revs->full_diff)
diff_tree_setup_paths(revs->prune_data, &revs->diffopt);
}
return rewrite_one_error;
if (p->parents && p->parents->next)
return rewrite_one_ok;
- if (p->object.flags & (TREECHANGE | UNINTERESTING))
+ if (p->object.flags & UNINTERESTING)
+ return rewrite_one_ok;
+ if (!(p->object.flags & TREESAME))
return rewrite_one_ok;
if (!p->parents)
return rewrite_one_noparents;
return commit_ignore;
if (!commit_match(commit, revs))
return commit_ignore;
- if (revs->prune_fn && revs->dense) {
+ if (revs->prune && revs->dense) {
/* Commit without changes? */
- if (!(commit->object.flags & TREECHANGE)) {
+ if (commit->object.flags & TREESAME) {
/* drop merges unless we want parenthood */
if (!revs->parents)
return commit_ignore;