Skip to content

Commit f26c494

Browse files
Miklos Vajnagitster
authored andcommitted
parse-opt: migrate builtin-apply.
The only incompatible change is that the user how have to use '--' before a patch file if it is named "--build-fake-ancestor=something". Signed-off-by: Miklos Vajna <vmiklos@frugalware.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent c32f76f commit f26c494

File tree

2 files changed

+154
-131
lines changed

2 files changed

+154
-131
lines changed

Documentation/git-apply.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ SYNOPSIS
1010
--------
1111
[verse]
1212
'git apply' [--stat] [--numstat] [--summary] [--check] [--index]
13-
[--apply] [--no-add] [--build-fake-ancestor <file>] [-R | --reverse]
13+
[--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
1414
[--allow-binary-replacement | --binary] [--reject] [-z]
1515
[-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
1616
[--whitespace=<nowarn|warn|fix|error|error-all>]
@@ -64,7 +64,7 @@ OPTIONS
6464
cached data, apply the patch, and store the result in the index,
6565
without using the working tree. This implies '--index'.
6666

67-
--build-fake-ancestor <file>::
67+
--build-fake-ancestor=<file>::
6868
Newer 'git-diff' output has embedded 'index information'
6969
for each blob to help identify the original version that
7070
the patch applies to. When this flag is given, and if

builtin-apply.c

Lines changed: 152 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
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;
4546
static int no_add;
4647
static const char *fake_ancestor;
4748
static 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

5255
static enum ws_error_action {
5356
nowarn_ws_error,
@@ -61,6 +64,8 @@ static int applied_after_fixing_ws;
6164
static const char *patch_input_file;
6265
static const char *root;
6366
static int root_len;
67+
static int read_stdin = 1;
68+
static int options;
6469

6570
static 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

31393210
int 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

Comments
 (0)