1111#include "refs.h"
1212#include "tag.h"
1313#include "run-command.h"
14-
15- static const char builtin_tag_usage [] =
16- "git-tag [-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg> | -F <file>] <tagname> [<head>]" ;
14+ #include "parse-options.h"
15+
16+ static const char * const git_tag_usage [] = {
17+ "git-tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]" ,
18+ "git-tag -d <tagname>..." ,
19+ "git-tag [-n [<num>]] -l [<pattern>]" ,
20+ "git-tag -v <tagname>..." ,
21+ NULL
22+ };
1723
1824static char signingkey [1000 ];
1925
@@ -339,101 +345,74 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
339345{
340346 struct strbuf buf ;
341347 unsigned char object [20 ], prev [20 ];
342- int annotate = 0 , sign = 0 , force = 0 , lines = 0 , message = 0 ;
343348 char ref [PATH_MAX ];
344349 const char * object_ref , * tag ;
345- int i ;
346350 struct ref_lock * lock ;
347351
352+ int annotate = 0 , sign = 0 , force = 0 , lines = 0 ,
353+ delete = 0 , verify = 0 ;
354+ char * list = NULL , * msg = NULL , * msgfile = NULL , * keyid = NULL ;
355+ const char * no_pattern = "NO_PATTERN" ;
356+ struct option options [] = {
357+ { OPTION_STRING , 'l' , NULL , & list , "pattern" , "list tag names" ,
358+ PARSE_OPT_OPTARG , NULL , (intptr_t ) no_pattern },
359+ { OPTION_INTEGER , 'n' , NULL , & lines , NULL ,
360+ "print n lines of each tag message" ,
361+ PARSE_OPT_OPTARG , NULL , 1 },
362+ OPT_BOOLEAN ('d' , NULL , & delete , "delete tags" ),
363+ OPT_BOOLEAN ('v' , NULL , & verify , "verify tags" ),
364+
365+ OPT_GROUP ("Tag creation options" ),
366+ OPT_BOOLEAN ('a' , NULL , & annotate ,
367+ "annotated tag, needs a message" ),
368+ OPT_STRING ('m' , NULL , & msg , "msg" , "message for the tag" ),
369+ OPT_STRING ('F' , NULL , & msgfile , "file" , "message in a file" ),
370+ OPT_BOOLEAN ('s' , NULL , & sign , "annotated and GPG-signed tag" ),
371+ OPT_STRING ('u' , NULL , & keyid , "key-id" ,
372+ "use another key to sign the tag" ),
373+ OPT_BOOLEAN ('f' , NULL , & force , "replace the tag if exists" ),
374+ OPT_END ()
375+ };
376+
348377 git_config (git_tag_config );
349- strbuf_init (& buf , 0 );
350378
351- for (i = 1 ; i < argc ; i ++ ) {
352- const char * arg = argv [i ];
379+ argc = parse_options (argc , argv , options , git_tag_usage , 0 );
353380
354- if (arg [0 ] != '-' )
355- break ;
356- if (!strcmp (arg , "-a" )) {
357- annotate = 1 ;
358- continue ;
359- }
360- if (!strcmp (arg , "-s" )) {
361- annotate = 1 ;
362- sign = 1 ;
363- continue ;
364- }
365- if (!strcmp (arg , "-f" )) {
366- force = 1 ;
367- continue ;
368- }
369- if (!strcmp (arg , "-n" )) {
370- if (i + 1 == argc || * argv [i + 1 ] == '-' )
371- /* no argument */
372- lines = 1 ;
373- else
374- lines = isdigit (* argv [++ i ]) ?
375- atoi (argv [i ]) : 1 ;
376- continue ;
377- }
378- if (!strcmp (arg , "-m" )) {
379- annotate = 1 ;
380- i ++ ;
381- if (i == argc )
382- die ("option -m needs an argument." );
383- if (message )
384- die ("only one -F or -m option is allowed." );
385- strbuf_addstr (& buf , argv [i ]);
386- message = 1 ;
387- continue ;
388- }
389- if (!strcmp (arg , "-F" )) {
390- annotate = 1 ;
391- i ++ ;
392- if (i == argc )
393- die ("option -F needs an argument." );
394- if (message )
395- die ("only one -F or -m option is allowed." );
396-
397- if (!strcmp (argv [i ], "-" )) {
381+ if (list )
382+ return list_tags (list == no_pattern ? NULL : list , lines );
383+ if (delete )
384+ return for_each_tag_name (argv , delete_tag );
385+ if (verify )
386+ return for_each_tag_name (argv , verify_tag );
387+
388+ strbuf_init (& buf , 0 );
389+ if (msg || msgfile ) {
390+ if (msg && msgfile )
391+ die ("only one -F or -m option is allowed." );
392+ annotate = 1 ;
393+ if (msg )
394+ strbuf_addstr (& buf , msg );
395+ else {
396+ if (!strcmp (msgfile , "-" )) {
398397 if (strbuf_read (& buf , 0 , 1024 ) < 0 )
399- die ("cannot read %s" , argv [ i ] );
398+ die ("cannot read %s" , msgfile );
400399 } else {
401- if (strbuf_read_file (& buf , argv [ i ] , 1024 ) < 0 )
400+ if (strbuf_read_file (& buf , msgfile , 1024 ) < 0 )
402401 die ("could not open or read '%s': %s" ,
403- argv [ i ] , strerror (errno ));
402+ msgfile , strerror (errno ));
404403 }
405- message = 1 ;
406- continue ;
407- }
408- if (!strcmp (arg , "-u" )) {
409- annotate = 1 ;
410- sign = 1 ;
411- i ++ ;
412- if (i == argc )
413- die ("option -u needs an argument." );
414- if (strlcpy (signingkey , argv [i ], sizeof (signingkey ))
415- >= sizeof (signingkey ))
416- die ("argument to option -u too long" );
417- continue ;
418404 }
419- if (!strcmp (arg , "-l" ))
420- return list_tags (argv [i + 1 ], lines );
421- if (!strcmp (arg , "-d" ))
422- return for_each_tag_name (argv + i + 1 , delete_tag );
423- if (!strcmp (arg , "-v" ))
424- return for_each_tag_name (argv + i + 1 , verify_tag );
425- usage (builtin_tag_usage );
426405 }
427406
428- if (i == argc ) {
407+ if (argc == 0 ) {
429408 if (annotate )
430- usage ( builtin_tag_usage );
409+ usage_with_options ( git_tag_usage , options );
431410 return list_tags (NULL , lines );
432411 }
433- tag = argv [i ++ ];
412+ tag = argv [0 ];
434413
435- object_ref = i < argc ? argv [i ] : "HEAD" ;
436- if (i + 1 < argc )
414+ object_ref = argc == 2 ? argv [1 ] : "HEAD" ;
415+ if (argc > 2 )
437416 die ("too many params" );
438417
439418 if (get_sha1 (object_ref , object ))
@@ -450,7 +429,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
450429 die ("tag '%s' already exists" , tag );
451430
452431 if (annotate )
453- create_tag (object , tag , & buf , message , sign , prev , object );
432+ create_tag (object , tag , & buf , msg || msgfile , sign , prev , object );
454433
455434 lock = lock_any_ref_for_update (ref , prev , 0 );
456435 if (!lock )
0 commit comments