1414#include "builtin.h"
1515#include "string-list.h"
1616#include "dir.h"
17+ #include "parse-options.h"
1718
1819/*
1920 * --check turns on checking that the working tree matches the
@@ -45,9 +46,11 @@ static int apply_verbosely;
4546static int no_add ;
4647static const char * fake_ancestor ;
4748static int line_termination = '\n' ;
48- static unsigned long p_context = ULONG_MAX ;
49- static const char apply_usage [] =
50- "git apply [--stat] [--numstat] [--summary] [--check] [--index] [--cached] [--apply] [--no-add] [--index-info] [--allow-binary-replacement] [--reverse] [--reject] [--verbose] [-z] [-pNUM] [-CNUM] [--whitespace=<nowarn|warn|fix|error|error-all>] <patch>..." ;
49+ static unsigned int p_context = UINT_MAX ;
50+ static const char * const apply_usage [] = {
51+ "git apply [options] [<patch>...]" ,
52+ NULL
53+ };
5154
5255static enum ws_error_action {
5356 nowarn_ws_error ,
@@ -61,6 +64,8 @@ static int applied_after_fixing_ws;
6164static const char * patch_input_file ;
6265static const char * root ;
6366static int root_len ;
67+ static int read_stdin = 1 ;
68+ static int options ;
6469
6570static void parse_whitespace_option (const char * option )
6671{
@@ -3135,150 +3140,168 @@ static int git_apply_config(const char *var, const char *value, void *cb)
31353140 return git_default_config (var , value , cb );
31363141}
31373142
3143+ static int option_parse_stdin (const struct option * opt ,
3144+ const char * arg , int unset )
3145+ {
3146+ int * errs = opt -> value ;
3147+
3148+ * errs |= apply_patch (0 , "<stdin>" , options );
3149+ read_stdin = 0 ;
3150+ return 0 ;
3151+ }
3152+
3153+ static int option_parse_exclude (const struct option * opt ,
3154+ const char * arg , int unset )
3155+ {
3156+ add_name_limit (arg , 1 );
3157+ return 0 ;
3158+ }
3159+
3160+ static int option_parse_include (const struct option * opt ,
3161+ const char * arg , int unset )
3162+ {
3163+ add_name_limit (arg , 0 );
3164+ has_include = 1 ;
3165+ return 0 ;
3166+ }
3167+
3168+ static int option_parse_p (const struct option * opt ,
3169+ const char * arg , int unset )
3170+ {
3171+ p_value = atoi (arg );
3172+ p_value_known = 1 ;
3173+ return 0 ;
3174+ }
3175+
3176+ static int option_parse_z (const struct option * opt ,
3177+ const char * arg , int unset )
3178+ {
3179+ if (unset )
3180+ line_termination = '\n' ;
3181+ else
3182+ line_termination = 0 ;
3183+ return 0 ;
3184+ }
3185+
3186+ static int option_parse_whitespace (const struct option * opt ,
3187+ const char * arg , int unset )
3188+ {
3189+ const char * * whitespace_option = opt -> value ;
3190+
3191+ * whitespace_option = arg ;
3192+ parse_whitespace_option (arg );
3193+ return 0 ;
3194+ }
3195+
3196+ static int option_parse_directory (const struct option * opt ,
3197+ const char * arg , int unset )
3198+ {
3199+ root_len = strlen (arg );
3200+ if (root_len && arg [root_len - 1 ] != '/' ) {
3201+ char * new_root ;
3202+ root = new_root = xmalloc (root_len + 2 );
3203+ strcpy (new_root , arg );
3204+ strcpy (new_root + root_len ++ , "/" );
3205+ } else
3206+ root = arg ;
3207+ return 0 ;
3208+ }
31383209
31393210int cmd_apply (int argc , const char * * argv , const char * unused_prefix )
31403211{
31413212 int i ;
3142- int read_stdin = 1 ;
3143- int options = 0 ;
31443213 int errs = 0 ;
31453214 int is_not_gitdir ;
3215+ int binary ;
3216+ int force_apply = 0 ;
31463217
31473218 const char * whitespace_option = NULL ;
31483219
3220+ struct option builtin_apply_options [] = {
3221+ { OPTION_CALLBACK , '-' , NULL , & errs , NULL ,
3222+ "read the patch from the standard input" ,
3223+ PARSE_OPT_NOARG , option_parse_stdin },
3224+ { OPTION_CALLBACK , 0 , "exclude" , NULL , "path" ,
3225+ "don´t apply changes matching the given path" ,
3226+ 0 , option_parse_exclude },
3227+ { OPTION_CALLBACK , 0 , "include" , NULL , "path" ,
3228+ "apply changes matching the given path" ,
3229+ 0 , option_parse_include },
3230+ { OPTION_CALLBACK , 'p' , NULL , NULL , "num" ,
3231+ "remove <num> leading slashes from traditional diff paths" ,
3232+ 0 , option_parse_p },
3233+ OPT_BOOLEAN (0 , "no-add" , & no_add ,
3234+ "ignore additions made by the patch" ),
3235+ OPT_BOOLEAN (0 , "stat" , & diffstat ,
3236+ "instead of applying the patch, output diffstat for the input" ),
3237+ OPT_BOOLEAN (0 , "allow-binary-replacement" , & binary ,
3238+ "now no-op" ),
3239+ OPT_BOOLEAN (0 , "binary" , & binary ,
3240+ "now no-op" ),
3241+ OPT_BOOLEAN (0 , "numstat" , & numstat ,
3242+ "shows number of added and deleted lines in decimal notation" ),
3243+ OPT_BOOLEAN (0 , "summary" , & summary ,
3244+ "instead of applying the patch, output a summary for the input" ),
3245+ OPT_BOOLEAN (0 , "check" , & check ,
3246+ "instead of applying the patch, see if the patch is applicable" ),
3247+ OPT_BOOLEAN (0 , "index" , & check_index ,
3248+ "make sure the patch is applicable to the current index" ),
3249+ OPT_BOOLEAN (0 , "cached" , & cached ,
3250+ "apply a patch without touching the working tree" ),
3251+ OPT_BOOLEAN (0 , "apply" , & force_apply ,
3252+ "also apply the patch (use with --stat/--summary/--check)" ),
3253+ OPT_STRING (0 , "build-fake-ancestor" , & fake_ancestor , "file" ,
3254+ "build a temporary index based on embedded index information" ),
3255+ { OPTION_CALLBACK , 'z' , NULL , NULL , NULL ,
3256+ "paths are separated with NUL character" ,
3257+ PARSE_OPT_NOARG , option_parse_z },
3258+ OPT_INTEGER ('C' , NULL , & p_context ,
3259+ "ensure at least <n> lines of context match" ),
3260+ { OPTION_CALLBACK , 0 , "whitespace" , & whitespace_option , "action" ,
3261+ "detect new or modified lines that have whitespace errors" ,
3262+ 0 , option_parse_whitespace },
3263+ OPT_BOOLEAN ('R' , "reverse" , & apply_in_reverse ,
3264+ "apply the patch in reverse" ),
3265+ OPT_BOOLEAN (0 , "unidiff-zero" , & unidiff_zero ,
3266+ "don't expect at least one line of context" ),
3267+ OPT_BOOLEAN (0 , "reject" , & apply_with_reject ,
3268+ "leave the rejected hunks in corresponding *.rej files" ),
3269+ OPT__VERBOSE (& apply_verbosely ),
3270+ OPT_BIT (0 , "inaccurate-eof" , & options ,
3271+ "tolerate incorrectly detected missing new-line at the end of file" ,
3272+ INACCURATE_EOF ),
3273+ OPT_BIT (0 , "recount" , & options ,
3274+ "do not trust the line counts in the hunk headers" ,
3275+ RECOUNT ),
3276+ { OPTION_CALLBACK , 0 , "directory" , NULL , "root" ,
3277+ "prepend <root> to all filenames" ,
3278+ 0 , option_parse_directory },
3279+ OPT_END ()
3280+ };
3281+
31493282 prefix = setup_git_directory_gently (& is_not_gitdir );
31503283 prefix_length = prefix ? strlen (prefix ) : 0 ;
31513284 git_config (git_apply_config , NULL );
31523285 if (apply_default_whitespace )
31533286 parse_whitespace_option (apply_default_whitespace );
31543287
3155- for (i = 1 ; i < argc ; i ++ ) {
3288+ argc = parse_options (argc , argv , builtin_apply_options ,
3289+ apply_usage , 0 );
3290+ if (apply_with_reject )
3291+ apply = apply_verbosely = 1 ;
3292+ if (!force_apply && (diffstat || numstat || summary || check || fake_ancestor ))
3293+ apply = 0 ;
3294+ if (check_index && is_not_gitdir )
3295+ die ("--index outside a repository" );
3296+ if (cached ) {
3297+ if (is_not_gitdir )
3298+ die ("--cached outside a repository" );
3299+ check_index = 1 ;
3300+ }
3301+ for (i = 0 ; i < argc ; i ++ ) {
31563302 const char * arg = argv [i ];
3157- char * end ;
31583303 int fd ;
31593304
3160- if (!strcmp (arg , "-" )) {
3161- errs |= apply_patch (0 , "<stdin>" , options );
3162- read_stdin = 0 ;
3163- continue ;
3164- }
3165- if (!prefixcmp (arg , "--exclude=" )) {
3166- add_name_limit (arg + 10 , 1 );
3167- continue ;
3168- }
3169- if (!prefixcmp (arg , "--include=" )) {
3170- add_name_limit (arg + 10 , 0 );
3171- has_include = 1 ;
3172- continue ;
3173- }
3174- if (!prefixcmp (arg , "-p" )) {
3175- p_value = atoi (arg + 2 );
3176- p_value_known = 1 ;
3177- continue ;
3178- }
3179- if (!strcmp (arg , "--no-add" )) {
3180- no_add = 1 ;
3181- continue ;
3182- }
3183- if (!strcmp (arg , "--stat" )) {
3184- apply = 0 ;
3185- diffstat = 1 ;
3186- continue ;
3187- }
3188- if (!strcmp (arg , "--allow-binary-replacement" ) ||
3189- !strcmp (arg , "--binary" )) {
3190- continue ; /* now no-op */
3191- }
3192- if (!strcmp (arg , "--numstat" )) {
3193- apply = 0 ;
3194- numstat = 1 ;
3195- continue ;
3196- }
3197- if (!strcmp (arg , "--summary" )) {
3198- apply = 0 ;
3199- summary = 1 ;
3200- continue ;
3201- }
3202- if (!strcmp (arg , "--check" )) {
3203- apply = 0 ;
3204- check = 1 ;
3205- continue ;
3206- }
3207- if (!strcmp (arg , "--index" )) {
3208- if (is_not_gitdir )
3209- die ("--index outside a repository" );
3210- check_index = 1 ;
3211- continue ;
3212- }
3213- if (!strcmp (arg , "--cached" )) {
3214- if (is_not_gitdir )
3215- die ("--cached outside a repository" );
3216- check_index = 1 ;
3217- cached = 1 ;
3218- continue ;
3219- }
3220- if (!strcmp (arg , "--apply" )) {
3221- apply = 1 ;
3222- continue ;
3223- }
3224- if (!strcmp (arg , "--build-fake-ancestor" )) {
3225- apply = 0 ;
3226- if (++ i >= argc )
3227- die ("need a filename" );
3228- fake_ancestor = argv [i ];
3229- continue ;
3230- }
3231- if (!strcmp (arg , "-z" )) {
3232- line_termination = 0 ;
3233- continue ;
3234- }
3235- if (!prefixcmp (arg , "-C" )) {
3236- p_context = strtoul (arg + 2 , & end , 0 );
3237- if (* end != '\0' )
3238- die ("unrecognized context count '%s'" , arg + 2 );
3239- continue ;
3240- }
3241- if (!prefixcmp (arg , "--whitespace=" )) {
3242- whitespace_option = arg + 13 ;
3243- parse_whitespace_option (arg + 13 );
3244- continue ;
3245- }
3246- if (!strcmp (arg , "-R" ) || !strcmp (arg , "--reverse" )) {
3247- apply_in_reverse = 1 ;
3248- continue ;
3249- }
3250- if (!strcmp (arg , "--unidiff-zero" )) {
3251- unidiff_zero = 1 ;
3252- continue ;
3253- }
3254- if (!strcmp (arg , "--reject" )) {
3255- apply = apply_with_reject = apply_verbosely = 1 ;
3256- continue ;
3257- }
3258- if (!strcmp (arg , "-v" ) || !strcmp (arg , "--verbose" )) {
3259- apply_verbosely = 1 ;
3260- continue ;
3261- }
3262- if (!strcmp (arg , "--inaccurate-eof" )) {
3263- options |= INACCURATE_EOF ;
3264- continue ;
3265- }
3266- if (!strcmp (arg , "--recount" )) {
3267- options |= RECOUNT ;
3268- continue ;
3269- }
3270- if (!prefixcmp (arg , "--directory=" )) {
3271- arg += strlen ("--directory=" );
3272- root_len = strlen (arg );
3273- if (root_len && arg [root_len - 1 ] != '/' ) {
3274- char * new_root ;
3275- root = new_root = xmalloc (root_len + 2 );
3276- strcpy (new_root , arg );
3277- strcpy (new_root + root_len ++ , "/" );
3278- } else
3279- root = arg ;
3280- continue ;
3281- }
32823305 if (0 < prefix_length )
32833306 arg = prefix_filename (prefix , prefix_length , arg );
32843307
0 commit comments