]> git.ipfire.org Git - thirdparty/git.git/commitdiff
ref-filter: handle nested tags in --points-at option
authorJan Klötzke <jan@kloetzke.net>
Sat, 1 Jul 2023 20:57:02 +0000 (22:57 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 17 Jul 2023 21:16:05 +0000 (14:16 -0700)
Tags are dereferenced until reaching a different object type to handle
nested tags, e.g. on checkout. In contrast, "git tag --points-at=..."
fails to list such nested tags because only one level of indirection is
obtained in filter_refs(). Implement the recursive dereferencing for the
"--points-at" option when filtering refs to unify the behaviour.

Signed-off-by: Jan Klötzke <jan@kloetzke.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
ref-filter.c
t/t6302-for-each-ref-filter.sh

index 60919f375fe574e34bbf93343b7678a3e8876bd0..7b17128bef531aeb3681dd3d61a7ea75f68956b7 100644 (file)
@@ -2332,10 +2332,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
  * of oids. If the given ref is a tag, check if the given tag points
  * at one of the oids in the given oid array.
  * NEEDSWORK:
- * 1. Only a single level of indirection is obtained, we might want to
- * change this to account for multiple levels (e.g. annotated tags
- * pointing to annotated tags pointing to a commit.)
- * 2. As the refs are cached we might know what refname peels to without
+ * As the refs are cached we might know what refname peels to without
  * the need to parse the object via parse_object(). peel_ref() might be a
  * more efficient alternative to obtain the pointee.
  */
@@ -2343,18 +2340,19 @@ static const struct object_id *match_points_at(struct oid_array *points_at,
                                               const struct object_id *oid,
                                               const char *refname)
 {
-       const struct object_id *tagged_oid = NULL;
        struct object *obj;
 
        if (oid_array_lookup(points_at, oid) >= 0)
                return oid;
        obj = parse_object(the_repository, oid);
+       while (obj && obj->type == OBJ_TAG) {
+               oid = get_tagged_oid((struct tag *)obj);
+               if (oid_array_lookup(points_at, oid) >= 0)
+                       return oid;
+               obj = parse_object(the_repository, oid);
+       }
        if (!obj)
                die(_("malformed object at '%s'"), refname);
-       if (obj->type == OBJ_TAG)
-               tagged_oid = get_tagged_oid((struct tag *)obj);
-       if (tagged_oid && oid_array_lookup(points_at, tagged_oid) >= 0)
-               return tagged_oid;
        return NULL;
 }
 
index 1ce5f490e99d374e039d29e708ee98dfb8988eab..af223e44d679571b3148d265ebb09049275cef3a 100755 (executable)
@@ -45,6 +45,8 @@ test_expect_success 'check signed tags with --points-at' '
        sed -e "s/Z$//" >expect <<-\EOF &&
        refs/heads/side Z
        refs/tags/annotated-tag four
+       refs/tags/doubly-annotated-tag An annotated tag
+       refs/tags/doubly-signed-tag A signed tag
        refs/tags/four Z
        refs/tags/signed-tag four
        EOF