2828#include "date.h"
2929#include "write-or-die.h"
3030#include "object-file-convert.h"
31+ #include "trailer.h"
3132
3233static const char * const git_tag_usage [] = {
3334 N_ ("git tag [-a | -s | -u <key-id>] [-f] [-m <msg> | -F <file>] [-e]\n"
35+ " [(--trailer <token>[(=|:)<value>])...]\n"
3436 " <tagname> [<commit> | <object>]" ),
3537 N_ ("git tag -d <tagname>..." ),
3638 N_ ("git tag [-n[<num>]] -l [--contains <commit>] [--no-contains <commit>]\n"
@@ -290,10 +292,12 @@ static const char message_advice_nested_tag[] =
290292static void create_tag (const struct object_id * object , const char * object_ref ,
291293 const char * tag ,
292294 struct strbuf * buf , struct create_tag_options * opt ,
293- struct object_id * prev , struct object_id * result , char * path )
295+ struct object_id * prev , struct object_id * result ,
296+ struct strvec * trailer_args , char * path )
294297{
295298 enum object_type type ;
296299 struct strbuf header = STRBUF_INIT ;
300+ int should_edit ;
297301
298302 type = oid_object_info (the_repository , object , NULL );
299303 if (type <= OBJ_NONE )
@@ -313,13 +317,15 @@ static void create_tag(const struct object_id *object, const char *object_ref,
313317 tag ,
314318 git_committer_info (IDENT_STRICT ));
315319
316- if (!opt -> message_given || opt -> use_editor ) {
320+ should_edit = opt -> use_editor || !opt -> message_given ;
321+ if (should_edit || trailer_args -> nr ) {
317322 int fd ;
318323
319324 /* write the template message before editing: */
320325 fd = xopen (path , O_CREAT | O_TRUNC | O_WRONLY , 0600 );
321326
322- if (opt -> message_given ) {
327+ if (opt -> message_given && buf -> len ) {
328+ strbuf_complete (buf , '\n' );
323329 write_or_die (fd , buf -> buf , buf -> len );
324330 strbuf_reset (buf );
325331 } else if (!is_null_oid (prev )) {
@@ -338,10 +344,19 @@ static void create_tag(const struct object_id *object, const char *object_ref,
338344 }
339345 close (fd );
340346
341- if (launch_editor (path , buf , NULL )) {
342- fprintf (stderr ,
343- _ ("Please supply the message using either -m or -F option.\n" ));
344- exit (1 );
347+ if (trailer_args -> nr && amend_file_with_trailers (path , trailer_args ))
348+ die (_ ("unable to pass trailers to --trailers" ));
349+
350+ if (should_edit ) {
351+ if (launch_editor (path , buf , NULL )) {
352+ fprintf (stderr ,
353+ _ ("Please supply the message using either -m or -F option.\n" ));
354+ exit (1 );
355+ }
356+ } else if (trailer_args -> nr ) {
357+ strbuf_reset (buf );
358+ if (strbuf_read_file (buf , path , 0 ) < 0 )
359+ die_errno (_ ("failed to read '%s'" ), path );
345360 }
346361 }
347362
@@ -463,6 +478,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
463478 struct ref_sorting * sorting ;
464479 struct string_list sorting_options = STRING_LIST_INIT_DUP ;
465480 struct ref_format format = REF_FORMAT_INIT ;
481+ struct strvec trailer_args = STRVEC_INIT ;
466482 int icase = 0 ;
467483 int edit_flag = 0 ;
468484 struct option options [] = {
@@ -479,6 +495,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
479495 OPT_CALLBACK_F ('m' , "message" , & msg , N_ ("message" ),
480496 N_ ("tag message" ), PARSE_OPT_NONEG , parse_msg_arg ),
481497 OPT_FILENAME ('F' , "file" , & msgfile , N_ ("read message from file" )),
498+ OPT_PASSTHRU_ARGV (0 , "trailer" , & trailer_args , N_ ("trailer" ),
499+ N_ ("add custom trailer(s)" ), PARSE_OPT_NONEG ),
482500 OPT_BOOL ('e' , "edit" , & edit_flag , N_ ("force edit of tag message" )),
483501 OPT_BOOL ('s' , "sign" , & opt .sign , N_ ("annotated and GPG-signed tag" )),
484502 OPT_CLEANUP (& cleanup_arg ),
@@ -548,7 +566,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
548566 opt .sign = 1 ;
549567 set_signing_key (keyid );
550568 }
551- create_tag_object = (opt .sign || annotate || msg .given || msgfile );
569+ create_tag_object = (opt .sign || annotate || msg .given || msgfile ||
570+ edit_flag || trailer_args .nr );
552571
553572 if ((create_tag_object || force ) && (cmdmode != 0 ))
554573 usage_with_options (git_tag_usage , options );
@@ -654,7 +673,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
654673 opt .sign = 1 ;
655674 path = git_pathdup ("TAG_EDITMSG" );
656675 create_tag (& object , object_ref , tag , & buf , & opt , & prev , & object ,
657- path );
676+ & trailer_args , path );
658677 }
659678
660679 transaction = ref_transaction_begin (& err );
@@ -686,6 +705,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
686705 strbuf_release (& reflog_msg );
687706 strbuf_release (& msg .buf );
688707 strbuf_release (& err );
708+ strvec_clear (& trailer_args );
689709 free (msgfile );
690710 return ret ;
691711}
0 commit comments