From: Teng Long <dyroneteng@xxxxxxxxx> This commit brings the tags exclusion feature of packfile-uri. The excluding level of tag is supported with "ET_SELF", "ET_INCLUDE" and "ET_REACHABLE". Exclusion scope on different level: 1. When a tag is specified to be excluded with level "ET_SELF", only the tag object itself will be excluded. 2. When it's specified to be excluded with level "ET_INCLUDE", exclude the referenced commit, and all trees and blobs contained in its top-level. If it's a annotated tag, the tag object will be excluded too. 3. When it is specified with level "ET_REACHABLE", exclude the ancestors of the referenced commit, as well as the objects need to be excluded under the level "ET_INCLUDED". Signed-off-by: Teng Long <dyroneteng@xxxxxxxxx> --- builtin/pack-objects.c | 6 +++++- list-objects.c | 20 ++++++++++++++++---- object.c | 1 + object.h | 1 + revision.c | 13 ++++++++++++- revision.h | 9 +++++++++ 6 files changed, 44 insertions(+), 6 deletions(-) diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c index 6713e734fb..073c3815a1 100644 --- a/builtin/pack-objects.c +++ b/builtin/pack-objects.c @@ -1416,6 +1416,9 @@ static int want_object_in_pack(const struct object_id *oid, if (referred_objs) { struct commit *commit = referred_objs->commit; struct object_list *trees = referred_objs->trees; + struct object_list *tags = referred_objs->tags; + if (want_exclude_object(tags)) + return 0; if (commit) { commit_ex = oidmap_get(&configured_exclusions, &commit->object.oid); if (match_packfile_uri_exclusions(commit_ex) && commit_ex->level > ET_SELF) @@ -3344,7 +3347,8 @@ static void read_object_list_from_stdin(void) static void show_commit(struct commit *commit, struct show_info *info) { - add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, NULL); + struct referred_objects *referred_objs = info->show_cache; + add_object_entry(&commit->object.oid, OBJ_COMMIT, NULL, 0, referred_objs); commit->object.flags |= OBJECT_ADDED; if (write_bitmap_index) diff --git a/list-objects.c b/list-objects.c index 40292e2cc8..2e241e8707 100644 --- a/list-objects.c +++ b/list-objects.c @@ -348,9 +348,10 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, for (i = 0; i < ctx->revs->pending.nr; i++) { struct object_array_entry *pending = ctx->revs->pending.objects + i; struct object *obj = pending->item; - struct referred_objects *referred_objs = pending->referred_objects; const char *name = pending->name; const char *path = pending->path; + struct referred_objects *referred_objs = pending->referred_objects; + struct commit_wraps_entry *cw_entry = NULL; if (obj->flags & (UNINTERESTING | SEEN)) continue; if (obj->type == OBJ_TAG) { @@ -358,6 +359,10 @@ static void traverse_trees_and_blobs(struct traversal_context *ctx, ctx->show_object(obj, name, &show_info); continue; } + if (referred_objs->commit) + cw_entry = oidmap_get(ctx->revs->commit_wraps, &referred_objs->commit->object.oid); + if (cw_entry) + referred_objs->tags = cw_entry->wraps; if (!path) path = ""; if (obj->type == OBJ_TREE) { @@ -378,12 +383,14 @@ static void do_traverse(struct traversal_context *ctx) { struct commit *commit; struct strbuf csp; /* callee's scratch pad */ - struct show_info show_info; + struct commit_wraps_entry *entry; + struct oidmap *commit_wraps = ctx->revs->commit_wraps; + struct referred_objects referred_objs = { NULL, NULL, NULL }; + struct show_info show_info = { ctx->show_data , NULL }; strbuf_init(&csp, PATH_MAX); - show_info.show_data = ctx->show_data; - show_info.show_cache = NULL; + show_info.show_cache = &referred_objs; while ((commit = get_revision(ctx->revs)) != NULL) { /* @@ -401,6 +408,11 @@ static void do_traverse(struct traversal_context *ctx) oid_to_hex(&commit->object.oid)); } + if (commit_wraps) { + entry = oidmap_get(commit_wraps, &commit->object.oid); + referred_objs.tags = entry ? entry->wraps : NULL; + } + ctx->show_commit(commit, &show_info); if (ctx->revs->tree_blobs_in_commit_order) diff --git a/object.c b/object.c index 895068cbc2..167cc87ec9 100644 --- a/object.c +++ b/object.c @@ -335,6 +335,7 @@ void add_object_array_with_path_and_referred_commit(struct object *obj, const ch referred_objs = xmalloc(sizeof(struct referred_objects)); referred_objs->commit = referred_commit; referred_objs->trees = NULL; + referred_objs->tags = NULL; if (nr >= alloc) { alloc = (alloc + 32) * 2; diff --git a/object.h b/object.h index 618d674249..42a2178531 100644 --- a/object.h +++ b/object.h @@ -66,6 +66,7 @@ struct object_array { struct referred_objects{ struct commit *commit; struct object_list *trees; + struct object_list *tags; }; #define OBJECT_ARRAY_INIT { 0, 0, NULL } diff --git a/revision.c b/revision.c index 89a8b311ea..d16f9bbbb9 100644 --- a/revision.c +++ b/revision.c @@ -416,14 +416,17 @@ static struct commit *handle_commit(struct rev_info *revs, const char *path = entry->path; unsigned int mode = entry->mode; unsigned long flags = object->flags; + struct object_list *wraps = NULL; /* * Tag object? Look what it points to.. */ while (object->type == OBJ_TAG) { struct tag *tag = (struct tag *) object; - if (revs->tag_objects && !(flags & UNINTERESTING)) + if (revs->tag_objects && !(flags & UNINTERESTING)) { add_pending_object(revs, object, tag->tag); + object_list_insert(object, &wraps); + } object = parse_object(revs->repo, get_tagged_oid(tag)); if (!object) { if (revs->ignore_missing_links || (flags & UNINTERESTING)) @@ -449,6 +452,14 @@ static struct commit *handle_commit(struct rev_info *revs, */ if (object->type == OBJ_COMMIT) { struct commit *commit = (struct commit *)object; + struct oidmap *commit_wraps = malloc(sizeof(struct oidmap)); + struct commit_wraps_entry *cw_entry = xmalloc(sizeof(struct commit_wraps_entry)); + + oidmap_init(commit_wraps, 0); + cw_entry->e.oid = object->oid; + cw_entry->wraps = wraps; + oidmap_put(commit_wraps, cw_entry); + revs->commit_wraps = commit_wraps; if (repo_parse_commit(revs->repo, commit) < 0) die("unable to parse commit %s", name); diff --git a/revision.h b/revision.h index b2e0c0b9b7..a633ea2174 100644 --- a/revision.h +++ b/revision.h @@ -8,6 +8,7 @@ #include "pretty.h" #include "diff.h" #include "commit-slab-decl.h" +#include "oidmap.h" /** * The revision walking API offers functions to build a list of revisions @@ -64,6 +65,11 @@ struct bloom_key; struct bloom_filter_settings; define_shared_commit_slab(revision_sources, char *); +struct commit_wraps_entry { + struct oidmap_entry e; + struct object_list *wraps; +}; + struct rev_cmdline_info { unsigned int nr; unsigned int alloc; @@ -321,6 +327,9 @@ struct rev_info { /* misc. flags related to '--no-kept-objects' */ unsigned keep_pack_cache_flags; + + /* The commit_wraps caches the referred wrapped objects(such as tags) of a commit */ + struct oidmap *commit_wraps; }; int ref_excluded(struct string_list *, const char *path); -- 2.31.1.453.g945ddc3a74.dirty