1515#include "diff.h"
1616#include "revision.h"
1717#include "gpg-interface.h"
18+ #include "sha1-array.h"
1819
1920static const char * const git_tag_usage [] = {
2021 "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]" ,
2122 "git tag -d <tagname>..." ,
22- "git tag -l [-n[<num>]] [<pattern>...]" ,
23+ "git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] "
24+ "\n\t\t[<pattern>...]" ,
2325 "git tag -v <tagname>..." ,
2426 NULL
2527};
@@ -30,6 +32,8 @@ struct tag_filter {
3032 struct commit_list * with_commit ;
3133};
3234
35+ static struct sha1_array points_at ;
36+
3337static int match_pattern (const char * * patterns , const char * ref )
3438{
3539 /* no pattern means match everything */
@@ -41,6 +45,24 @@ static int match_pattern(const char **patterns, const char *ref)
4145 return 0 ;
4246}
4347
48+ static const unsigned char * match_points_at (const char * refname ,
49+ const unsigned char * sha1 )
50+ {
51+ const unsigned char * tagged_sha1 = NULL ;
52+ struct object * obj ;
53+
54+ if (sha1_array_lookup (& points_at , sha1 ) >= 0 )
55+ return sha1 ;
56+ obj = parse_object (sha1 );
57+ if (!obj )
58+ die (_ ("malformed object at '%s'" ), refname );
59+ if (obj -> type == OBJ_TAG )
60+ tagged_sha1 = ((struct tag * )obj )-> tagged -> sha1 ;
61+ if (tagged_sha1 && sha1_array_lookup (& points_at , tagged_sha1 ) >= 0 )
62+ return tagged_sha1 ;
63+ return NULL ;
64+ }
65+
4466static int in_commit_list (const struct commit_list * want , struct commit * c )
4567{
4668 for (; want ; want = want -> next )
@@ -138,6 +160,9 @@ static int show_reference(const char *refname, const unsigned char *sha1,
138160 return 0 ;
139161 }
140162
163+ if (points_at .nr && !match_points_at (refname , sha1 ))
164+ return 0 ;
165+
141166 if (!filter -> lines ) {
142167 printf ("%s\n" , refname );
143168 return 0 ;
@@ -383,6 +408,23 @@ static int strbuf_check_tag_ref(struct strbuf *sb, const char *name)
383408 return check_refname_format (sb -> buf , 0 );
384409}
385410
411+ static int parse_opt_points_at (const struct option * opt __attribute__((unused )),
412+ const char * arg , int unset )
413+ {
414+ unsigned char sha1 [20 ];
415+
416+ if (unset ) {
417+ sha1_array_clear (& points_at );
418+ return 0 ;
419+ }
420+ if (!arg )
421+ return error (_ ("switch 'points-at' requires an object" ));
422+ if (get_sha1 (arg , sha1 ))
423+ return error (_ ("malformed object name '%s'" ), arg );
424+ sha1_array_append (& points_at , sha1 );
425+ return 0 ;
426+ }
427+
386428int cmd_tag (int argc , const char * * argv , const char * prefix )
387429{
388430 struct strbuf buf = STRBUF_INIT ;
@@ -425,6 +467,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
425467 PARSE_OPT_LASTARG_DEFAULT ,
426468 parse_opt_with_commit , (intptr_t )"HEAD" ,
427469 },
470+ {
471+ OPTION_CALLBACK , 0 , "points-at" , NULL , "object" ,
472+ "print only tags of the object" , 0 , parse_opt_points_at
473+ },
428474 OPT_END ()
429475 };
430476
@@ -456,6 +502,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
456502 die (_ ("-n option is only allowed with -l." ));
457503 if (with_commit )
458504 die (_ ("--contains option is only allowed with -l." ));
505+ if (points_at .nr )
506+ die (_ ("--points-at option is only allowed with -l." ));
459507 if (delete )
460508 return for_each_tag_name (argv , delete_tag );
461509 if (verify )
0 commit comments