X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=list-objects.c;h=0966cdc9fa8dd448aa9955a2fb5324ae8ebbf97d;hb=f5833f0110119fc17973835cc0042e76e3375ccd;hp=2910becd6c65b66670215aefdf08e1933895aa39;hpb=3815afa233c3938e6f4b67d2f5551297f0c45509;p=platform%2Fupstream%2Fgit.git diff --git a/list-objects.c b/list-objects.c index 2910bec..0966cdc 100644 --- a/list-objects.c +++ b/list-objects.c @@ -7,15 +7,21 @@ #include "tree-walk.h" #include "revision.h" #include "list-objects.h" +#include "list-objects-filter.h" +#include "list-objects-filter-options.h" static void process_blob(struct rev_info *revs, struct blob *blob, show_object_fn show, - struct name_path *path, + struct strbuf *path, const char *name, - void *cb_data) + void *cb_data, + filter_object_fn filter_fn, + void *filter_data) { struct object *obj = &blob->object; + size_t pathlen; + enum list_objects_filter_result r = LOFR_MARK_SEEN | LOFR_DO_SHOW; if (!revs->blob_objects) return; @@ -23,8 +29,18 @@ static void process_blob(struct rev_info *revs, die("bad blob object"); if (obj->flags & (UNINTERESTING | SEEN)) return; - obj->flags |= SEEN; - show(obj, path, name, cb_data); + + pathlen = path->len; + strbuf_addstr(path, name); + if (filter_fn) + r = filter_fn(LOFS_BLOB, obj, + path->buf, &path->buf[pathlen], + filter_data); + if (r & LOFR_MARK_SEEN) + obj->flags |= SEEN; + if (r & LOFR_DO_SHOW) + show(obj, path->buf, cb_data); + strbuf_setlen(path, pathlen); } /* @@ -52,7 +68,7 @@ static void process_blob(struct rev_info *revs, static void process_gitlink(struct rev_info *revs, const unsigned char *sha1, show_object_fn show, - struct name_path *path, + struct strbuf *path, const char *name, void *cb_data) { @@ -62,18 +78,19 @@ static void process_gitlink(struct rev_info *revs, static void process_tree(struct rev_info *revs, struct tree *tree, show_object_fn show, - struct name_path *path, struct strbuf *base, const char *name, - void *cb_data) + void *cb_data, + filter_object_fn filter_fn, + void *filter_data) { struct object *obj = &tree->object; struct tree_desc desc; struct name_entry entry; - struct name_path me; enum interesting match = revs->diffopt.pathspec.nr == 0 ? all_entries_interesting: entry_not_interesting; int baselen = base->len; + enum list_objects_filter_result r = LOFR_MARK_SEEN | LOFR_DO_SHOW; if (!revs->tree_objects) return; @@ -81,23 +98,24 @@ static void process_tree(struct rev_info *revs, die("bad tree object"); if (obj->flags & (UNINTERESTING | SEEN)) return; - if (parse_tree(tree) < 0) { + if (parse_tree_gently(tree, revs->ignore_missing_links) < 0) { if (revs->ignore_missing_links) return; - die("bad tree object %s", sha1_to_hex(obj->sha1)); - } - obj->flags |= SEEN; - show(obj, path, name, cb_data); - me.up = path; - me.elem = name; - me.elem_len = strlen(name); - - if (!match) { - strbuf_addstr(base, name); - if (base->len) - strbuf_addch(base, '/'); + die("bad tree object %s", oid_to_hex(&obj->oid)); } + strbuf_addstr(base, name); + if (filter_fn) + r = filter_fn(LOFS_BEGIN_TREE, obj, + base->buf, &base->buf[baselen], + filter_data); + if (r & LOFR_MARK_SEEN) + obj->flags |= SEEN; + if (r & LOFR_DO_SHOW) + show(obj, base->buf, cb_data); + if (base->len) + strbuf_addch(base, '/'); + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { @@ -112,19 +130,30 @@ static void process_tree(struct rev_info *revs, if (S_ISDIR(entry.mode)) process_tree(revs, - lookup_tree(entry.sha1), - show, &me, base, entry.path, - cb_data); + lookup_tree(entry.oid), + show, base, entry.path, + cb_data, filter_fn, filter_data); else if (S_ISGITLINK(entry.mode)) - process_gitlink(revs, entry.sha1, - show, &me, entry.path, + process_gitlink(revs, entry.oid->hash, + show, base, entry.path, cb_data); else process_blob(revs, - lookup_blob(entry.sha1), - show, &me, entry.path, - cb_data); + lookup_blob(entry.oid), + show, base, entry.path, + cb_data, filter_fn, filter_data); + } + + if (filter_fn) { + r = filter_fn(LOFS_END_TREE, obj, + base->buf, &base->buf[baselen], + filter_data); + if (r & LOFR_MARK_SEEN) + obj->flags |= SEEN; + if (r & LOFR_DO_SHOW) + show(obj, base->buf, cb_data); } + strbuf_setlen(base, baselen); free_tree_buffer(tree); } @@ -157,7 +186,7 @@ void mark_edges_uninteresting(struct rev_info *revs, show_edge_fn show_edge) if (commit->object.flags & UNINTERESTING) { mark_tree_uninteresting(commit->tree); - if (revs->edge_hint && !(commit->object.flags & SHOWN)) { + if (revs->edge_hint_aggressive && !(commit->object.flags & SHOWN)) { commit->object.flags |= SHOWN; show_edge(commit); } @@ -165,7 +194,7 @@ void mark_edges_uninteresting(struct rev_info *revs, show_edge_fn show_edge) } mark_edge_parents_uninteresting(commit, revs, show_edge); } - if (revs->edge_hint) { + if (revs->edge_hint_aggressive) { for (i = 0; i < revs->cmdline.nr; i++) { struct object *obj = revs->cmdline.rev[i].item; struct commit *commit = (struct commit *)obj; @@ -185,25 +214,17 @@ static void add_pending_tree(struct rev_info *revs, struct tree *tree) add_pending_object(revs, &tree->object, ""); } -void traverse_commit_list(struct rev_info *revs, - show_commit_fn show_commit, - show_object_fn show_object, - void *data) +static void traverse_trees_and_blobs(struct rev_info *revs, + struct strbuf *base, + show_object_fn show_object, + void *show_data, + filter_object_fn filter_fn, + void *filter_data) { int i; - struct commit *commit; - struct strbuf base; - strbuf_init(&base, PATH_MAX); - while ((commit = get_revision(revs)) != NULL) { - /* - * an uninteresting boundary commit may not have its tree - * parsed yet, but we are not going to show them anyway - */ - if (commit->tree) - add_pending_tree(revs, commit->tree); - show_commit(commit, data); - } + assert(base->len == 0); + for (i = 0; i < revs->pending.nr; i++) { struct object_array_entry *pending = revs->pending.objects + i; struct object *obj = pending->item; @@ -213,24 +234,89 @@ void traverse_commit_list(struct rev_info *revs, continue; if (obj->type == OBJ_TAG) { obj->flags |= SEEN; - show_object(obj, NULL, name, data); + show_object(obj, name, show_data); continue; } if (!path) path = ""; if (obj->type == OBJ_TREE) { process_tree(revs, (struct tree *)obj, show_object, - NULL, &base, path, data); + base, path, show_data, + filter_fn, filter_data); continue; } if (obj->type == OBJ_BLOB) { process_blob(revs, (struct blob *)obj, show_object, - NULL, path, data); + base, path, show_data, + filter_fn, filter_data); continue; } die("unknown pending object %s (%s)", - sha1_to_hex(obj->sha1), name); + oid_to_hex(&obj->oid), name); } object_array_clear(&revs->pending); - strbuf_release(&base); +} + +static void do_traverse(struct rev_info *revs, + show_commit_fn show_commit, + show_object_fn show_object, + void *show_data, + filter_object_fn filter_fn, + void *filter_data) +{ + struct commit *commit; + struct strbuf csp; /* callee's scratch pad */ + strbuf_init(&csp, PATH_MAX); + + while ((commit = get_revision(revs)) != NULL) { + /* + * an uninteresting boundary commit may not have its tree + * parsed yet, but we are not going to show them anyway + */ + if (commit->tree) + add_pending_tree(revs, commit->tree); + show_commit(commit, show_data); + + if (revs->tree_blobs_in_commit_order) + /* + * NEEDSWORK: Adding the tree and then flushing it here + * needs a reallocation for each commit. Can we pass the + * tree directory without allocation churn? + */ + traverse_trees_and_blobs(revs, &csp, + show_object, show_data, + filter_fn, filter_data); + } + traverse_trees_and_blobs(revs, &csp, + show_object, show_data, + filter_fn, filter_data); + strbuf_release(&csp); +} + +void traverse_commit_list(struct rev_info *revs, + show_commit_fn show_commit, + show_object_fn show_object, + void *show_data) +{ + do_traverse(revs, show_commit, show_object, show_data, NULL, NULL); +} + +void traverse_commit_list_filtered( + struct list_objects_filter_options *filter_options, + struct rev_info *revs, + show_commit_fn show_commit, + show_object_fn show_object, + void *show_data, + struct oidset *omitted) +{ + filter_object_fn filter_fn = NULL; + filter_free_fn filter_free_fn = NULL; + void *filter_data = NULL; + + filter_data = list_objects_filter__init(omitted, filter_options, + &filter_fn, &filter_free_fn); + do_traverse(revs, show_commit, show_object, show_data, + filter_fn, filter_data); + if (filter_data && filter_free_fn) + filter_free_fn(filter_data); }