1818#include "shortlog.h"
1919#include "remote.h"
2020#include "string-list.h"
21+ #include "parse-options.h"
2122
2223/* Set a default date-time format for git log ("log.date" config variable) */
2324static const char * default_date_mode = NULL ;
@@ -740,27 +741,179 @@ static const char *set_outdir(const char *prefix, const char *output_directory)
740741 output_directory ));
741742}
742743
744+ static const char * const builtin_format_patch_usage [] = {
745+ "git format-patch [options] [<since> | <revision range>]" ,
746+ NULL
747+ };
748+
749+ static int keep_subject = 0 ;
750+
751+ static int keep_callback (const struct option * opt , const char * arg , int unset )
752+ {
753+ ((struct rev_info * )opt -> value )-> total = -1 ;
754+ keep_subject = 1 ;
755+ return 0 ;
756+ }
757+
758+ static int subject_prefix = 0 ;
759+
760+ static int subject_prefix_callback (const struct option * opt , const char * arg ,
761+ int unset )
762+ {
763+ subject_prefix = 1 ;
764+ ((struct rev_info * )opt -> value )-> subject_prefix = arg ;
765+ return 0 ;
766+ }
767+
768+ static int numbered_cmdline_opt = 0 ;
769+
770+ static int numbered_callback (const struct option * opt , const char * arg ,
771+ int unset )
772+ {
773+ * (int * )opt -> value = numbered_cmdline_opt = unset ? 0 : 1 ;
774+ if (unset )
775+ auto_number = 0 ;
776+ return 0 ;
777+ }
778+
779+ static int no_numbered_callback (const struct option * opt , const char * arg ,
780+ int unset )
781+ {
782+ return numbered_callback (opt , arg , 1 );
783+ }
784+
785+ static int output_directory_callback (const struct option * opt , const char * arg ,
786+ int unset )
787+ {
788+ const char * * dir = (const char * * )opt -> value ;
789+ if (* dir )
790+ die ("Two output directories?" );
791+ * dir = arg ;
792+ return 0 ;
793+ }
794+
795+ static int thread_callback (const struct option * opt , const char * arg , int unset )
796+ {
797+ int * thread = (int * )opt -> value ;
798+ if (unset )
799+ * thread = 0 ;
800+ else if (!arg || !strcmp (arg , "shallow" ))
801+ * thread = THREAD_SHALLOW ;
802+ else if (!strcmp (arg , "deep" ))
803+ * thread = THREAD_DEEP ;
804+ else
805+ return 1 ;
806+ return 0 ;
807+ }
808+
809+ static int attach_callback (const struct option * opt , const char * arg , int unset )
810+ {
811+ struct rev_info * rev = (struct rev_info * )opt -> value ;
812+ if (unset )
813+ rev -> mime_boundary = NULL ;
814+ else if (arg )
815+ rev -> mime_boundary = arg ;
816+ else
817+ rev -> mime_boundary = git_version_string ;
818+ rev -> no_inline = unset ? 0 : 1 ;
819+ return 0 ;
820+ }
821+
822+ static int inline_callback (const struct option * opt , const char * arg , int unset )
823+ {
824+ struct rev_info * rev = (struct rev_info * )opt -> value ;
825+ if (unset )
826+ rev -> mime_boundary = NULL ;
827+ else if (arg )
828+ rev -> mime_boundary = arg ;
829+ else
830+ rev -> mime_boundary = git_version_string ;
831+ rev -> no_inline = 0 ;
832+ return 0 ;
833+ }
834+
835+ static int header_callback (const struct option * opt , const char * arg , int unset )
836+ {
837+ add_header (arg );
838+ return 0 ;
839+ }
840+
841+ static int cc_callback (const struct option * opt , const char * arg , int unset )
842+ {
843+ ALLOC_GROW (extra_cc , extra_cc_nr + 1 , extra_cc_alloc );
844+ extra_cc [extra_cc_nr ++ ] = xstrdup (arg );
845+ return 0 ;
846+ }
847+
743848int cmd_format_patch (int argc , const char * * argv , const char * prefix )
744849{
745850 struct commit * commit ;
746851 struct commit * * list = NULL ;
747852 struct rev_info rev ;
748- int nr = 0 , total , i , j ;
853+ int nr = 0 , total , i ;
749854 int use_stdout = 0 ;
750855 int start_number = -1 ;
751- int keep_subject = 0 ;
752856 int numbered_files = 0 ; /* _just_ numbers */
753- int subject_prefix = 0 ;
754857 int ignore_if_in_upstream = 0 ;
755858 int cover_letter = 0 ;
756859 int boundary_count = 0 ;
757860 int no_binary_diff = 0 ;
758- int numbered_cmdline_opt = 0 ;
759861 struct commit * origin = NULL , * head = NULL ;
760862 const char * in_reply_to = NULL ;
761863 struct patch_ids ids ;
762864 char * add_signoff = NULL ;
763865 struct strbuf buf = STRBUF_INIT ;
866+ const struct option builtin_format_patch_options [] = {
867+ { OPTION_CALLBACK , 'n' , "numbered" , & numbered , NULL ,
868+ "use [PATCH n/m] even with a single patch" ,
869+ PARSE_OPT_NOARG , numbered_callback },
870+ { OPTION_CALLBACK , 'N' , "no-numbered" , & numbered , NULL ,
871+ "use [PATCH] even with multiple patches" ,
872+ PARSE_OPT_NOARG , no_numbered_callback },
873+ OPT_BOOLEAN ('s' , "signoff" , & do_signoff , "add Signed-off-by:" ),
874+ OPT_BOOLEAN (0 , "stdout" , & use_stdout ,
875+ "print patches to standard out" ),
876+ OPT_BOOLEAN (0 , "cover-letter" , & cover_letter ,
877+ "generate a cover letter" ),
878+ OPT_BOOLEAN (0 , "numbered-files" , & numbered_files ,
879+ "use simple number sequence for output file names" ),
880+ OPT_STRING (0 , "suffix" , & fmt_patch_suffix , "sfx" ,
881+ "use <sfx> instead of '.patch'" ),
882+ OPT_INTEGER (0 , "start-number" , & start_number ,
883+ "start numbering patches at <n> instead of 1" ),
884+ { OPTION_CALLBACK , 0 , "subject-prefix" , & rev , "prefix" ,
885+ "Use [<prefix>] instead of [PATCH]" ,
886+ PARSE_OPT_NONEG , subject_prefix_callback },
887+ { OPTION_CALLBACK , 'o' , "output-directory" , & output_directory ,
888+ "dir" , "store resulting files in <dir>" ,
889+ PARSE_OPT_NONEG , output_directory_callback },
890+ { OPTION_CALLBACK , 'k' , "keep-subject" , & rev , NULL ,
891+ "don't strip/add [PATCH]" ,
892+ PARSE_OPT_NOARG | PARSE_OPT_NONEG , keep_callback },
893+ OPT_BOOLEAN (0 , "no-binary" , & no_binary_diff ,
894+ "don't output binary diffs" ),
895+ OPT_BOOLEAN (0 , "ignore-if-in-upstream" , & ignore_if_in_upstream ,
896+ "don't include a patch matching a commit upstream" ),
897+ OPT_GROUP ("Messaging" ),
898+ { OPTION_CALLBACK , 0 , "add-header" , NULL , "header" ,
899+ "add email header" , PARSE_OPT_NONEG ,
900+ header_callback },
901+ { OPTION_CALLBACK , 0 , "cc" , NULL , "email" , "add Cc: header" ,
902+ PARSE_OPT_NONEG , cc_callback },
903+ OPT_STRING (0 , "in-reply-to" , & in_reply_to , "message-id" ,
904+ "make first mail a reply to <message-id>" ),
905+ { OPTION_CALLBACK , 0 , "attach" , & rev , "boundary" ,
906+ "attach the patch" , PARSE_OPT_OPTARG ,
907+ attach_callback },
908+ { OPTION_CALLBACK , 0 , "inline" , & rev , "boundary" ,
909+ "inline the patch" ,
910+ PARSE_OPT_OPTARG | PARSE_OPT_NONEG ,
911+ inline_callback },
912+ { OPTION_CALLBACK , 0 , "thread" , & thread , "style" ,
913+ "enable message threading, styles: shallow, deep" ,
914+ PARSE_OPT_OPTARG , thread_callback },
915+ OPT_END ()
916+ };
764917
765918 git_config (git_format_config , NULL );
766919 init_revisions (& rev , prefix );
@@ -783,102 +936,9 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
783936 * like "git format-patch -o a123 HEAD^.." may fail; a123 is
784937 * possibly a valid SHA1.
785938 */
786- for (i = 1 , j = 1 ; i < argc ; i ++ ) {
787- if (!strcmp (argv [i ], "--stdout" ))
788- use_stdout = 1 ;
789- else if (!strcmp (argv [i ], "-n" ) ||
790- !strcmp (argv [i ], "--numbered" )) {
791- numbered = 1 ;
792- numbered_cmdline_opt = 1 ;
793- }
794- else if (!strcmp (argv [i ], "-N" ) ||
795- !strcmp (argv [i ], "--no-numbered" )) {
796- numbered = 0 ;
797- auto_number = 0 ;
798- }
799- else if (!prefixcmp (argv [i ], "--start-number=" ))
800- start_number = strtol (argv [i ] + 15 , NULL , 10 );
801- else if (!strcmp (argv [i ], "--numbered-files" ))
802- numbered_files = 1 ;
803- else if (!strcmp (argv [i ], "--start-number" )) {
804- i ++ ;
805- if (i == argc )
806- die ("Need a number for --start-number" );
807- start_number = strtol (argv [i ], NULL , 10 );
808- }
809- else if (!prefixcmp (argv [i ], "--cc=" )) {
810- ALLOC_GROW (extra_cc , extra_cc_nr + 1 , extra_cc_alloc );
811- extra_cc [extra_cc_nr ++ ] = xstrdup (argv [i ] + 5 );
812- }
813- else if (!strcmp (argv [i ], "-k" ) ||
814- !strcmp (argv [i ], "--keep-subject" )) {
815- keep_subject = 1 ;
816- rev .total = -1 ;
817- }
818- else if (!strcmp (argv [i ], "--output-directory" ) ||
819- !strcmp (argv [i ], "-o" )) {
820- i ++ ;
821- if (argc <= i )
822- die ("Which directory?" );
823- if (output_directory )
824- die ("Two output directories?" );
825- output_directory = argv [i ];
826- }
827- else if (!strcmp (argv [i ], "--signoff" ) ||
828- !strcmp (argv [i ], "-s" )) {
829- do_signoff = 1 ;
830- }
831- else if (!strcmp (argv [i ], "--attach" )) {
832- rev .mime_boundary = git_version_string ;
833- rev .no_inline = 1 ;
834- }
835- else if (!prefixcmp (argv [i ], "--attach=" )) {
836- rev .mime_boundary = argv [i ] + 9 ;
837- rev .no_inline = 1 ;
838- }
839- else if (!strcmp (argv [i ], "--no-attach" )) {
840- rev .mime_boundary = NULL ;
841- rev .no_inline = 0 ;
842- }
843- else if (!strcmp (argv [i ], "--inline" )) {
844- rev .mime_boundary = git_version_string ;
845- rev .no_inline = 0 ;
846- }
847- else if (!prefixcmp (argv [i ], "--inline=" )) {
848- rev .mime_boundary = argv [i ] + 9 ;
849- rev .no_inline = 0 ;
850- }
851- else if (!strcmp (argv [i ], "--ignore-if-in-upstream" ))
852- ignore_if_in_upstream = 1 ;
853- else if (!strcmp (argv [i ], "--thread" )
854- || !strcmp (argv [i ], "--thread=shallow" ))
855- thread = THREAD_SHALLOW ;
856- else if (!strcmp (argv [i ], "--thread=deep" ))
857- thread = THREAD_DEEP ;
858- else if (!strcmp (argv [i ], "--no-thread" ))
859- thread = 0 ;
860- else if (!prefixcmp (argv [i ], "--in-reply-to=" ))
861- in_reply_to = argv [i ] + 14 ;
862- else if (!strcmp (argv [i ], "--in-reply-to" )) {
863- i ++ ;
864- if (i == argc )
865- die ("Need a Message-Id for --in-reply-to" );
866- in_reply_to = argv [i ];
867- } else if (!prefixcmp (argv [i ], "--subject-prefix=" )) {
868- subject_prefix = 1 ;
869- rev .subject_prefix = argv [i ] + 17 ;
870- } else if (!prefixcmp (argv [i ], "--suffix=" ))
871- fmt_patch_suffix = argv [i ] + 9 ;
872- else if (!strcmp (argv [i ], "--cover-letter" ))
873- cover_letter = 1 ;
874- else if (!strcmp (argv [i ], "--no-binary" ))
875- no_binary_diff = 1 ;
876- else if (!prefixcmp (argv [i ], "--add-header=" ))
877- add_header (argv [i ] + 13 );
878- else
879- argv [j ++ ] = argv [i ];
880- }
881- argc = j ;
939+ argc = parse_options (argc , argv , builtin_format_patch_options ,
940+ builtin_format_patch_usage ,
941+ PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN );
882942
883943 if (do_signoff ) {
884944 const char * committer ;
0 commit comments