[PATCH] parse-opt: migrate builtin-apply.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The only notable user-visible/incompatible change is that the
--build-fake-ancestor option now conforms to gitcli(7).

Signed-off-by: Miklos Vajna <vmiklos@xxxxxxxxxxxxxx>
---

I know that we do care about incompatible changes a lot, though I think
this is the right direction and probably --build-fake-ancestor is not a
heavily used switch, so I hope that part is OK.

 Documentation/git-apply.txt |    4 +-
 builtin-apply.c             |  360 ++++++++++++++++++++++++++++---------------
 2 files changed, 234 insertions(+), 130 deletions(-)

diff --git a/Documentation/git-apply.txt b/Documentation/git-apply.txt
index e726510..9400f6a 100644
--- a/Documentation/git-apply.txt
+++ b/Documentation/git-apply.txt
@@ -10,7 +10,7 @@ SYNOPSIS
 --------
 [verse]
 'git apply' [--stat] [--numstat] [--summary] [--check] [--index]
-	  [--apply] [--no-add] [--build-fake-ancestor <file>] [-R | --reverse]
+	  [--apply] [--no-add] [--build-fake-ancestor=<file>] [-R | --reverse]
 	  [--allow-binary-replacement | --binary] [--reject] [-z]
 	  [-pNUM] [-CNUM] [--inaccurate-eof] [--recount] [--cached]
 	  [--whitespace=<nowarn|warn|fix|error|error-all>]
@@ -64,7 +64,7 @@ OPTIONS
 	cached data, apply the patch, and store the result in the index,
 	without using the working tree. This implies '--index'.
 
---build-fake-ancestor <file>::
+--build-fake-ancestor=<file>::
 	Newer 'git-diff' output has embedded 'index information'
 	for each blob to help identify the original version that
 	the patch applies to.  When this flag is given, and if
diff --git a/builtin-apply.c b/builtin-apply.c
index 07244b0..c2a587f 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -14,6 +14,7 @@
 #include "builtin.h"
 #include "string-list.h"
 #include "dir.h"
+#include "parse-options.h"
 
 /*
  *  --check turns on checking that the working tree matches the
@@ -46,8 +47,10 @@ static int no_add;
 static const char *fake_ancestor;
 static int line_termination = '\n';
 static unsigned long p_context = ULONG_MAX;
-static const char apply_usage[] =
-"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>...";
+static const char * const apply_usage[] = {
+	"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>...",
+	NULL
+};
 
 static enum ws_error_action {
 	nowarn_ws_error,
@@ -61,6 +64,8 @@ static int applied_after_fixing_ws;
 static const char *patch_input_file;
 static const char *root;
 static int root_len;
+static int read_stdin = 1;
+static int options;
 
 static void parse_whitespace_option(const char *option)
 {
@@ -3135,150 +3140,249 @@ static int git_apply_config(const char *var, const char *value, void *cb)
 	return git_default_config(var, value, cb);
 }
 
+static int option_parse_stdin(const struct option *opt,
+			      const char *arg, int unset)
+{
+	int *errs = opt->value;
+
+	*errs |= apply_patch(0, "<stdin>", options);
+	read_stdin = 0;
+	return 0;
+}
+
+static int option_parse_exclude(const struct option *opt,
+				const char *arg, int unset)
+{
+	add_name_limit(arg, 1);
+	return 0;
+}
+
+static int option_parse_include(const struct option *opt,
+				const char *arg, int unset)
+{
+	add_name_limit(arg, 0);
+	has_include = 1;
+	return 0;
+}
+
+static int option_parse_p(const struct option *opt,
+			  const char *arg, int unset)
+{
+	p_value = atoi(arg);
+	p_value_known = 1;
+	return 0;
+}
+
+static int option_parse_stat(const struct option *opt,
+			     const char *arg, int unset)
+{
+	apply = 0;
+	diffstat = 1;
+	return 0;
+}
+
+static int option_parse_numstat(const struct option *opt,
+				const char *arg, int unset)
+{
+	apply = 0;
+	numstat = 1;
+	return 0;
+}
+
+static int option_parse_summary(const struct option *opt,
+				const char *arg, int unset)
+{
+	apply = 0;
+	summary = 1;
+	return 0;
+}
+
+static int option_parse_check(const struct option *opt,
+			      const char *arg, int unset)
+{
+	apply = 0;
+	check = 1;
+	return 0;
+}
+
+static int option_parse_index(const struct option *opt,
+			      const char *arg, int unset)
+{
+	int *is_not_gitdir = opt->value;
+
+	if (*is_not_gitdir)
+		die("--index outside a repository");
+	check_index = 1;
+	return 0;
+}
+
+static int option_parse_cached(const struct option *opt,
+			       const char *arg, int unset)
+{
+	int *is_not_gitdir = opt->value;
+
+	if (*is_not_gitdir)
+		die("--cached outside a repository");
+	check_index = 1;
+	cached = 1;
+	return 0;
+}
+
+static int option_parse_ancestor(const struct option *opt,
+				 const char *arg, int unset)
+{
+	apply = 0;
+	fake_ancestor = arg;
+	return 0;
+}
+
+static int option_parse_z(const struct option *opt,
+			  const char *arg, int unset)
+{
+	if (unset)
+		line_termination = '\n';
+	else
+		line_termination = 0;
+	return 0;
+}
+
+static int option_parse_whitespace(const struct option *opt,
+				   const char *arg, int unset)
+{
+	const char **whitespace_option = opt->value;
+
+	*whitespace_option = arg;
+	parse_whitespace_option(arg);
+	return 0;
+}
+
+static int option_parse_reject(const struct option *opt,
+			       const char *arg, int unset)
+{
+	apply = apply_with_reject = apply_verbosely = 1;
+	return 0;
+}
+
+static int option_parse_inaccurate(const struct option *opt,
+				   const char *arg, int unset)
+{
+	options |= INACCURATE_EOF;
+	return 0;
+}
+
+static int option_parse_recount(const struct option *opt,
+				const char *arg, int unset)
+{
+	options |= RECOUNT;
+	return 0;
+}
+
+static int option_parse_directory(const struct option *opt,
+				  const char *arg, int unset)
+{
+	root_len = strlen(arg);
+	if (root_len && arg[root_len - 1] != '/') {
+		char *new_root;
+		root = new_root = xmalloc(root_len + 2);
+		strcpy(new_root, arg);
+		strcpy(new_root + root_len++, "/");
+	} else
+		root = arg;
+	return 0;
+}
 
 int cmd_apply(int argc, const char **argv, const char *unused_prefix)
 {
 	int i;
-	int read_stdin = 1;
-	int options = 0;
 	int errs = 0;
 	int is_not_gitdir;
+	int binary;
 
 	const char *whitespace_option = NULL;
 
+	struct option builtin_apply_options[] = {
+		{ OPTION_CALLBACK, '-', NULL, &errs, NULL,
+			"read the patch from the standard input",
+			PARSE_OPT_NOARG, option_parse_stdin },
+		{ OPTION_CALLBACK, 0, "exclude", NULL, "path",
+			"don´t apply changes matching the given path",
+			0, option_parse_exclude },
+		{ OPTION_CALLBACK, 0, "include", NULL, "path",
+			"apply changes matching the given path",
+			0, option_parse_include },
+		{ OPTION_CALLBACK, 'p', NULL, NULL, "num",
+			"remove <num> leading slashes from traditional diff paths",
+			0, option_parse_p },
+		OPT_BOOLEAN(0, "no-add", &no_add,
+			"ignore additions made by the patch"),
+		{ OPTION_CALLBACK, 0, "stat", NULL, NULL,
+			"instead of applying the patch, output diffstat for the input",
+			PARSE_OPT_NOARG, option_parse_stat },
+		OPT_BOOLEAN(0, "allow-binary-replacement", &binary,
+			"now no-op"),
+		OPT_BOOLEAN(0, "binary", &binary,
+			"now no-op"),
+		{ OPTION_CALLBACK, 0, "numstat", NULL, NULL,
+			"shows number of added and deleted lines in decimal notation",
+			PARSE_OPT_NOARG, option_parse_numstat },
+		{ OPTION_CALLBACK, 0, "summary", NULL, NULL,
+			"instead of applying the patch, output a summary for the input",
+			PARSE_OPT_NOARG, option_parse_summary },
+		{ OPTION_CALLBACK, 0, "check", NULL, NULL,
+			"instead of applying the patch, see if the patch is applicable",
+			PARSE_OPT_NOARG, option_parse_check },
+		{ OPTION_CALLBACK, 0, "index", &is_not_gitdir, NULL,
+			"make sure the patch is applicable to the current index",
+			PARSE_OPT_NOARG, option_parse_index },
+		{ OPTION_CALLBACK, 0, "cached", &is_not_gitdir, NULL,
+			"apply a patch without touching the working tree",
+			PARSE_OPT_NOARG, option_parse_cached },
+		OPT_BOOLEAN(0, "apply", &apply,
+			"also apply the patch (use with --stat/--summary/--check)"),
+		{ OPTION_CALLBACK, 0, "build-fake-ancestor", NULL, "file",
+			"build a temporary index based on embedded index information",
+			0, option_parse_ancestor },
+		{ OPTION_CALLBACK, 'z', NULL, NULL, NULL,
+			"paths are separated with NUL character",
+			PARSE_OPT_NOARG, option_parse_z },
+		OPT_INTEGER('C', NULL, &p_context,
+				"ensure at least <n> lines of context match"),
+		{ OPTION_CALLBACK, 0, "whitespace", &whitespace_option, "action",
+			"detect new or modified lines that have whitespace errors",
+			0, option_parse_whitespace },
+		OPT_BOOLEAN('R', "reverse", &apply_in_reverse,
+			"apply the patch in reverse"),
+		OPT_BOOLEAN(0, "unidiff-zero", &unidiff_zero,
+			"don't expect at least one line of context"),
+		{ OPTION_CALLBACK, 0, "reject", NULL, NULL,
+			"leave the rejected hunks in corresponding *.rej files",
+			PARSE_OPT_NOARG, option_parse_reject },
+		OPT__VERBOSE(&apply_verbosely),
+		{ OPTION_CALLBACK, 0, "inaccurate-eof", NULL, NULL,
+			"tolerate incorrectly detected missing new-line at the end of file",
+			PARSE_OPT_NOARG, option_parse_inaccurate },
+		{ OPTION_CALLBACK, 0, "recount", NULL, NULL,
+			"do not trust the line counts in the hunk headers",
+			PARSE_OPT_NOARG, option_parse_recount },
+		{ OPTION_CALLBACK, 0, "directory", NULL, "root",
+			"prepend <root> to all filenames",
+			0, option_parse_directory },
+		OPT_END()
+	};
+
 	prefix = setup_git_directory_gently(&is_not_gitdir);
 	prefix_length = prefix ? strlen(prefix) : 0;
 	git_config(git_apply_config, NULL);
 	if (apply_default_whitespace)
 		parse_whitespace_option(apply_default_whitespace);
 
-	for (i = 1; i < argc; i++) {
+	argc = parse_options(argc, argv, builtin_apply_options,
+			apply_usage, 0);
+
+	for (i = 0; i < argc; i++) {
 		const char *arg = argv[i];
-		char *end;
 		int fd;
 
-		if (!strcmp(arg, "-")) {
-			errs |= apply_patch(0, "<stdin>", options);
-			read_stdin = 0;
-			continue;
-		}
-		if (!prefixcmp(arg, "--exclude=")) {
-			add_name_limit(arg + 10, 1);
-			continue;
-		}
-		if (!prefixcmp(arg, "--include=")) {
-			add_name_limit(arg + 10, 0);
-			has_include = 1;
-			continue;
-		}
-		if (!prefixcmp(arg, "-p")) {
-			p_value = atoi(arg + 2);
-			p_value_known = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--no-add")) {
-			no_add = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--stat")) {
-			apply = 0;
-			diffstat = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--allow-binary-replacement") ||
-		    !strcmp(arg, "--binary")) {
-			continue; /* now no-op */
-		}
-		if (!strcmp(arg, "--numstat")) {
-			apply = 0;
-			numstat = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--summary")) {
-			apply = 0;
-			summary = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--check")) {
-			apply = 0;
-			check = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--index")) {
-			if (is_not_gitdir)
-				die("--index outside a repository");
-			check_index = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--cached")) {
-			if (is_not_gitdir)
-				die("--cached outside a repository");
-			check_index = 1;
-			cached = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--apply")) {
-			apply = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--build-fake-ancestor")) {
-			apply = 0;
-			if (++i >= argc)
-				die ("need a filename");
-			fake_ancestor = argv[i];
-			continue;
-		}
-		if (!strcmp(arg, "-z")) {
-			line_termination = 0;
-			continue;
-		}
-		if (!prefixcmp(arg, "-C")) {
-			p_context = strtoul(arg + 2, &end, 0);
-			if (*end != '\0')
-				die("unrecognized context count '%s'", arg + 2);
-			continue;
-		}
-		if (!prefixcmp(arg, "--whitespace=")) {
-			whitespace_option = arg + 13;
-			parse_whitespace_option(arg + 13);
-			continue;
-		}
-		if (!strcmp(arg, "-R") || !strcmp(arg, "--reverse")) {
-			apply_in_reverse = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--unidiff-zero")) {
-			unidiff_zero = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--reject")) {
-			apply = apply_with_reject = apply_verbosely = 1;
-			continue;
-		}
-		if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) {
-			apply_verbosely = 1;
-			continue;
-		}
-		if (!strcmp(arg, "--inaccurate-eof")) {
-			options |= INACCURATE_EOF;
-			continue;
-		}
-		if (!strcmp(arg, "--recount")) {
-			options |= RECOUNT;
-			continue;
-		}
-		if (!prefixcmp(arg, "--directory=")) {
-			arg += strlen("--directory=");
-			root_len = strlen(arg);
-			if (root_len && arg[root_len - 1] != '/') {
-				char *new_root;
-				root = new_root = xmalloc(root_len + 2);
-				strcpy(new_root, arg);
-				strcpy(new_root + root_len++, "/");
-			} else
-				root = arg;
-			continue;
-		}
 		if (0 < prefix_length)
 			arg = prefix_filename(prefix, prefix_length, arg);
 
-- 
1.6.1.rc1.35.gae26e.dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux