diff options
Diffstat (limited to 'revision.c')
-rw-r--r-- | revision.c | 97 |
1 files changed, 71 insertions, 26 deletions
diff --git a/revision.c b/revision.c index 10854b0707..bd027bc015 100644 --- a/revision.c +++ b/revision.c @@ -16,6 +16,7 @@ #include "line-log.h" #include "mailmap.h" #include "commit-slab.h" +#include "dir.h" volatile show_early_output_fn_t show_early_output; @@ -104,17 +105,12 @@ static void mark_blob_uninteresting(struct blob *blob) blob->object.flags |= UNINTERESTING; } -void mark_tree_uninteresting(struct tree *tree) +static void mark_tree_contents_uninteresting(struct tree *tree) { struct tree_desc desc; struct name_entry entry; struct object *obj = &tree->object; - if (!tree) - return; - if (obj->flags & UNINTERESTING) - return; - obj->flags |= UNINTERESTING; if (!has_sha1_file(obj->sha1)) return; if (parse_tree(tree) < 0) @@ -142,6 +138,18 @@ void mark_tree_uninteresting(struct tree *tree) free_tree_buffer(tree); } +void mark_tree_uninteresting(struct tree *tree) +{ + struct object *obj = &tree->object; + + if (!tree) + return; + if (obj->flags & UNINTERESTING) + return; + obj->flags |= UNINTERESTING; + mark_tree_contents_uninteresting(tree); +} + void mark_parents_uninteresting(struct commit *commit) { struct commit_list *parents = NULL, *l; @@ -276,6 +284,7 @@ static struct commit *handle_commit(struct rev_info *revs, return NULL; die("bad object %s", sha1_to_hex(tag->tagged->sha1)); } + object->flags |= flags; } /* @@ -287,7 +296,6 @@ static struct commit *handle_commit(struct rev_info *revs, if (parse_commit(commit) < 0) die("unable to parse commit %s", name); if (flags & UNINTERESTING) { - commit->object.flags |= UNINTERESTING; mark_parents_uninteresting(commit); revs->limited = 1; } @@ -305,7 +313,7 @@ static struct commit *handle_commit(struct rev_info *revs, if (!revs->tree_objects) return NULL; if (flags & UNINTERESTING) { - mark_tree_uninteresting(tree); + mark_tree_contents_uninteresting(tree); return NULL; } add_pending_object(revs, object, ""); @@ -316,13 +324,10 @@ static struct commit *handle_commit(struct rev_info *revs, * Blob object? You know the drill by now.. */ if (object->type == OBJ_BLOB) { - struct blob *blob = (struct blob *)object; if (!revs->blob_objects) return NULL; - if (flags & UNINTERESTING) { - mark_blob_uninteresting(blob); + if (flags & UNINTERESTING) return NULL; - } add_pending_object(revs, object, ""); return NULL; } @@ -492,24 +497,14 @@ static int rev_compare_tree(struct rev_info *revs, static int rev_same_tree_as_empty(struct rev_info *revs, struct commit *commit) { int retval; - void *tree; - unsigned long size; - struct tree_desc empty, real; struct tree *t1 = commit->tree; if (!t1) return 0; - tree = read_object_with_reference(t1->object.sha1, tree_type, &size, NULL); - if (!tree) - return 0; - init_tree_desc(&real, tree, size); - init_tree_desc(&empty, "", 0); - tree_difference = REV_TREE_SAME; DIFF_OPT_CLR(&revs->pruning, HAS_CHANGES); - retval = diff_tree(&empty, &real, "", &revs->pruning); - free(tree); + retval = diff_tree_sha1(NULL, t1->object.sha1, "", &revs->pruning); return retval >= 0 && (tree_difference == REV_TREE_SAME); } @@ -779,6 +774,10 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, return 0; commit->object.flags |= ADDED; + if (revs->include_check && + !revs->include_check(commit, revs->include_check_data)) + return 0; + /* * If the commit is uninteresting, don't try to * prune parents - we want the maximal uninteresting @@ -1180,11 +1179,28 @@ struct all_refs_cb { const char *name_for_errormsg; }; +int ref_excluded(struct string_list *ref_excludes, const char *path) +{ + struct string_list_item *item; + + if (!ref_excludes) + return 0; + for_each_string_list_item(item, ref_excludes) { + if (!fnmatch(item->string, path, 0)) + return 1; + } + return 0; +} + static int handle_one_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data) { struct all_refs_cb *cb = cb_data; - struct object *object = get_reference(cb->all_revs, path, sha1, - cb->all_flags); + struct object *object; + + if (ref_excluded(cb->all_revs->ref_excludes, path)) + return 0; + + object = get_reference(cb->all_revs, path, sha1, cb->all_flags); add_rev_cmdline(cb->all_revs, object, path, REV_CMD_REF, cb->all_flags); add_pending_sha1(cb->all_revs, path, sha1, cb->all_flags); return 0; @@ -1197,6 +1213,24 @@ static void init_all_refs_cb(struct all_refs_cb *cb, struct rev_info *revs, cb->all_flags = flags; } +void clear_ref_exclusion(struct string_list **ref_excludes_p) +{ + if (*ref_excludes_p) { + string_list_clear(*ref_excludes_p, 0); + free(*ref_excludes_p); + } + *ref_excludes_p = NULL; +} + +void add_ref_exclusion(struct string_list **ref_excludes_p, const char *exclude) +{ + if (!*ref_excludes_p) { + *ref_excludes_p = xcalloc(1, sizeof(**ref_excludes_p)); + (*ref_excludes_p)->strdup_strings = 1; + } + string_list_append(*ref_excludes_p, exclude); +} + static void handle_refs(const char *submodule, struct rev_info *revs, unsigned flags, int (*for_each)(const char *, each_ref_fn, void *)) { @@ -1361,7 +1395,7 @@ static void prepare_show_merge(struct rev_info *revs) const struct cache_entry *ce = active_cache[i]; if (!ce_stage(ce)) continue; - if (ce_path_match(ce, &revs->prune_data)) { + if (ce_path_match(ce, &revs->prune_data, NULL)) { prune_num++; prune = xrealloc(prune, sizeof(*prune) * prune_num); prune[prune_num-2] = ce->name; @@ -1969,33 +2003,44 @@ static int handle_revision_pseudo_opt(const char *submodule, if (!strcmp(arg, "--all")) { handle_refs(submodule, revs, *flags, for_each_ref_submodule); handle_refs(submodule, revs, *flags, head_ref_submodule); + clear_ref_exclusion(&revs->ref_excludes); } else if (!strcmp(arg, "--branches")) { handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule); + clear_ref_exclusion(&revs->ref_excludes); } else if (!strcmp(arg, "--bisect")) { handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref); handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref); revs->bisect = 1; } else if (!strcmp(arg, "--tags")) { handle_refs(submodule, revs, *flags, for_each_tag_ref_submodule); + clear_ref_exclusion(&revs->ref_excludes); } else if (!strcmp(arg, "--remotes")) { handle_refs(submodule, revs, *flags, for_each_remote_ref_submodule); + clear_ref_exclusion(&revs->ref_excludes); } else if ((argcount = parse_long_opt("glob", argv, &optarg))) { struct all_refs_cb cb; init_all_refs_cb(&cb, revs, *flags); for_each_glob_ref(handle_one_ref, optarg, &cb); + clear_ref_exclusion(&revs->ref_excludes); + return argcount; + } else if ((argcount = parse_long_opt("exclude", argv, &optarg))) { + add_ref_exclusion(&revs->ref_excludes, optarg); return argcount; } else if (starts_with(arg, "--branches=")) { struct all_refs_cb cb; init_all_refs_cb(&cb, revs, *flags); for_each_glob_ref_in(handle_one_ref, arg + 11, "refs/heads/", &cb); + clear_ref_exclusion(&revs->ref_excludes); } else if (starts_with(arg, "--tags=")) { struct all_refs_cb cb; init_all_refs_cb(&cb, revs, *flags); for_each_glob_ref_in(handle_one_ref, arg + 7, "refs/tags/", &cb); + clear_ref_exclusion(&revs->ref_excludes); } else if (starts_with(arg, "--remotes=")) { struct all_refs_cb cb; init_all_refs_cb(&cb, revs, *flags); for_each_glob_ref_in(handle_one_ref, arg + 10, "refs/remotes/", &cb); + clear_ref_exclusion(&revs->ref_excludes); } else if (!strcmp(arg, "--reflog")) { handle_reflog(revs, *flags); } else if (!strcmp(arg, "--not")) { |