git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[RFC/PATCH 06/48] builtin/apply: introduce 'struct apply_state' to start libifying

From
Christian Couder <christian.couder@gmail.com>
Date
Mar 9, 2016, 17:48 UTC
Message-ID
<1457545756-20616-7-git-send-email-chriscool@tuxfamily.org>
In-Reply-To
<1457545756-20616-1-git-send-email-chriscool@tuxfamily.org>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
 builtin/apply.c | 94 ++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 56 insertions(+), 38 deletions(-)
diff --git a/builtin/apply.c b/builtin/apply.c
index 838e46a..462e28f 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -21,6 +21,11 @@
 #include "ll-merge.h"
 #include "rerere.h"
 
+struct apply_state {
+	const char *prefix;
+	int prefix_length;
+};
+
 /*
  *  --check turns on checking that the working tree matches the
  *    files that are being modified, but doesn't apply the patch
@@ -30,8 +35,6 @@
  *  --index updates the cache as well.
  *  --cached updates only the cache without ever touching the working tree.
  */
-static const char *prefix;
-static int prefix_length = -1;
 static int newfd = -1;
 
 static int unidiff_zero;
@@ -749,7 +752,7 @@ static int count_slashes(const char *cp)
  * Given the string after "--- " or "+++ ", guess the appropriate
  * p_value for the given patch.
  */
-static int guess_p_value(const char *nameline)
+static int guess_p_value(struct apply_state *state, const char *nameline)
 {
 	char *name, *cp;
 	int val = -1;
@@ -762,17 +765,17 @@ static int guess_p_value(const char *nameline)
 	cp = strchr(name, '/');
 	if (!cp)
 		val = 0;
-	else if (prefix) {
+	else if (state->prefix) {
 		/*
 		 * Does it begin with "a/$our-prefix" and such?  Then this is
 		 * very likely to apply to our directory.
 		 */
-		if (!strncmp(name, prefix, prefix_length))
-			val = count_slashes(prefix);
+		if (!strncmp(name, state->prefix, state->prefix_length))
+			val = count_slashes(state->prefix);
 		else {
 			cp++;
-			if (!strncmp(cp, prefix, prefix_length))
-				val = count_slashes(prefix) + 1;
+			if (!strncmp(cp, state->prefix, state->prefix_length))
+				val = count_slashes(state->prefix) + 1;
 		}
 	}
 	free(name);
@@ -859,7 +862,10 @@ static int has_epoch_timestamp(const char *nameline)
  * files, we can happily check the index for a match, but for creating a
  * new file we should try to match whatever "patch" does. I have no idea.
  */
-static void parse_traditional_patch(const char *first, const char *second, struct patch *patch)
+static void parse_traditional_patch(struct apply_state *state,
+				    const char *first,
+				    const char *second,
+				    struct patch *patch)
 {
 	char *name;
 
@@ -867,8 +873,8 @@ static void parse_traditional_patch(const char *first, const char *second, struc
 	second += 4;	/* skip "+++ " */
 	if (!p_value_known) {
 		int p, q;
-		p = guess_p_value(first);
-		q = guess_p_value(second);
+		p = guess_p_value(state, first);
+		q = guess_p_value(state, second);
 		if (p < 0) p = q;
 		if (0 <= p && p == q) {
 			p_value = p;
@@ -1439,7 +1445,11 @@ static int parse_fragment_header(const char *line, int len, struct fragment *fra
 	return offset;
 }
 
-static int find_header(const char *line, unsigned long size, int *hdrsize, struct patch *patch)
+static int find_header(struct apply_state *state,
+		       const char *line,
+		       unsigned long size,
+		       int *hdrsize,
+		       struct patch *patch)
 {
 	unsigned long offset, len;
 
@@ -1516,7 +1526,7 @@ static int find_header(const char *line, unsigned long size, int *hdrsize, struc
 			continue;
 
 		/* Ok, we'll consider it a patch */
-		parse_traditional_patch(line, line+len, patch);
+		parse_traditional_patch(state, line, line+len, patch);
 		*hdrsize = len + nextlen;
 		linenr += 2;
 		return offset;
@@ -1918,21 +1928,21 @@ static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
 	return used;
 }
 
-static void prefix_one(char **name)
+static void prefix_one(struct apply_state *state, char **name)
 {
 	char *old_name = *name;
 	if (!old_name)
 		return;
-	*name = xstrdup(prefix_filename(prefix, prefix_length, *name));
+	*name = xstrdup(prefix_filename(state->prefix, state->prefix_length, *name));
 	free(old_name);
 }
 
-static void prefix_patch(struct patch *p)
+static void prefix_patch(struct apply_state *state, struct patch *p)
 {
-	if (!prefix || p->is_toplevel_relative)
+	if (!state->prefix || p->is_toplevel_relative)
 		return;
-	prefix_one(&p->new_name);
-	prefix_one(&p->old_name);
+	prefix_one(state, &p->new_name);
+	prefix_one(state, &p->old_name);
 }
 
 /*
@@ -1949,16 +1959,16 @@ static void add_name_limit(const char *name, int exclude)
 	it->util = exclude ? NULL : (void *) 1;
 }
 
-static int use_patch(struct patch *p)
+static int use_patch(struct apply_state *state, struct patch *p)
 {
 	const char *pathname = p->new_name ? p->new_name : p->old_name;
 	int i;
 
 	/* Paths outside are not touched regardless of "--include" */
-	if (0 < prefix_length) {
+	if (0 < state->prefix_length) {
 		int pathlen = strlen(pathname);
-		if (pathlen <= prefix_length ||
-		    memcmp(prefix, pathname, prefix_length))
+		if (pathlen <= state->prefix_length ||
+		    memcmp(state->prefix, pathname, state->prefix_length))
 			return 0;
 	}
 
@@ -1985,17 +1995,17 @@ static int use_patch(struct patch *p)
  * Return the number of bytes consumed, so that the caller can call us
  * again for the next patch.
  */
-static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
+static int parse_chunk(struct apply_state *state, char *buffer, unsigned long size, struct patch *patch)
 {
 	int hdrsize, patchsize;
-	int offset = find_header(buffer, size, &hdrsize, patch);
+	int offset = find_header(state, buffer, size, &hdrsize, patch);
 
 	if (offset < 0)
 		return offset;
 
-	prefix_patch(patch);
+	prefix_patch(state, patch);
 
-	if (!use_patch(patch))
+	if (!use_patch(state, patch))
 		patch->ws_rule = 0;
 	else
 		patch->ws_rule = whitespace_rule(patch->new_name
@@ -4371,7 +4381,10 @@ static struct lock_file lock_file;
 #define INACCURATE_EOF	(1<<0)
 #define RECOUNT		(1<<1)
 
-static int apply_patch(int fd, const char *filename, int options)
+static int apply_patch(struct apply_state *state,
+		       int fd,
+		       const char *filename,
+		       int options)
 {
 	size_t offset;
 	struct strbuf buf = STRBUF_INIT; /* owns the patch text */
@@ -4388,12 +4401,12 @@ static int apply_patch(int fd, const char *filename, int options)
 		patch = xcalloc(1, sizeof(*patch));
 		patch->inaccurate_eof = !!(options & INACCURATE_EOF);
 		patch->recount =  !!(options & RECOUNT);
-		nr = parse_chunk(buf.buf + offset, buf.len - offset, patch);
+		nr = parse_chunk(state, buf.buf + offset, buf.len - offset, patch);
 		if (nr < 0)
 			break;
 		if (apply_in_reverse)
 			reverse_patches(patch);
-		if (use_patch(patch)) {
+		if (use_patch(state, patch)) {
 			patch_stats(patch);
 			*listp = patch;
 			listp = &patch->next;
@@ -4516,6 +4529,7 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 	int is_not_gitdir = !startup_info->have_repository;
 	int force_apply = 0;
 	int options = 0;
+	struct apply_state state;
 
 	const char *whitespace_option = NULL;
 
@@ -4588,15 +4602,17 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 		OPT_END()
 	};
 
-	prefix = prefix_;
-	prefix_length = prefix ? strlen(prefix) : 0;
+	memset(&state, 0, sizeof(state));
+	state.prefix = prefix_;
+	state.prefix_length = state.prefix ? strlen(state.prefix) : 0;
+
 	git_apply_config();
 	if (apply_default_whitespace)
 		parse_whitespace_option(apply_default_whitespace);
 	if (apply_default_ignorewhitespace)
 		parse_ignorewhitespace_option(apply_default_ignorewhitespace);
 
-	argc = parse_options(argc, argv, prefix, builtin_apply_options,
+	argc = parse_options(argc, argv, state.prefix, builtin_apply_options,
 			apply_usage, 0);
 
 	if (apply_with_reject && threeway)
@@ -4627,23 +4643,25 @@ int cmd_apply(int argc, const char **argv, const char *prefix_)
 		int fd;
 
 		if (!strcmp(arg, "-")) {
-			errs |= apply_patch(0, "<stdin>", options);
+			errs |= apply_patch(&state, 0, "<stdin>", options);
 			read_stdin = 0;
 			continue;
-		} else if (0 < prefix_length)
-			arg = prefix_filename(prefix, prefix_length, arg);
+		} else if (0 < state.prefix_length)
+			arg = prefix_filename(state.prefix,
+					      state.prefix_length,
+					      arg);
 
 		fd = open(arg, O_RDONLY);
 		if (fd < 0)
 			die_errno(_("can't open patch '%s'"), arg);
 		read_stdin = 0;
 		set_default_whitespace_mode(whitespace_option);
-		errs |= apply_patch(fd, arg, options);
+		errs |= apply_patch(&state, fd, arg, options);
 		close(fd);
 	}
 	set_default_whitespace_mode(whitespace_option);
 	if (read_stdin)
-		errs |= apply_patch(0, "<stdin>", options);
+		errs |= apply_patch(&state, 0, "<stdin>", options);
 	if (whitespace_error) {
 		if (squelch_whitespace_errors &&
 		    squelch_whitespace_errors < whitespace_error) {
-- 
2.8.0.rc1.49.gca61272
Previous: Christian CouderNext: Christian Couder
Message 12 of 58 in “Libifying git apply”
  1. 00/48 Libifying git applyChristian Couder, Mar 9, 2016
  2. 01/48 builtin/apply: avoid parameter shadowing 'p_value' globalChristian Couder, Mar 9, 2016
  3. Junio C HamanoMar 9, 2016
  4. Duy NguyenMar 10, 2016
  5. Christian CouderMar 10, 2016
  6. 02/48 builtin/apply: avoid parameter shadowing 'linenr' globalChristian Couder, Mar 9, 2016
  7. 03/48 builtin/apply: avoid local variable shadowing 'len' parameterChristian Couder, Mar 9, 2016
  8. 04/48 builtin/apply: extract line_by_line_fuzzy_match() from match_fragment()Christian Couder, Mar 9, 2016
  9. Stefan BellerMar 9, 2016
  10. Christian CouderMar 10, 2016
  11. 05/48 builtin/apply: move 'options' variable into cmd_apply()Christian Couder, Mar 9, 2016
  12. 06/48 builtin/apply: introduce 'struct apply_state' to start libifyingChristian Couder, Mar 9, 2016
  13. 07/48 builtin/apply: move 'newfd' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  14. 08/48 builtin/apply: move 'unidiff_zero' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  15. 09/48 builtin/apply: move 'check' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  16. 10/48 builtin/apply: move 'check_index' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  17. 11/48 builtin/apply: move 'apply_in_reverse' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  18. 12/48 builtin/apply: move 'apply_with_reject' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  19. 13/48 builtin/apply: move 'apply_verbosely' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  20. 14/48 builtin/apply: move 'update_index' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  21. 15/48 builtin/apply: move 'allow_overlap' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  22. 16/48 builtin/apply: move 'cached' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  23. 17/48 builtin/apply: move 'diffstat' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  24. 18/48 builtin/apply: move 'numstat' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  25. 19/48 builtin/apply: move 'summary' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  26. 20/48 builtin/apply: move 'threeway' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  27. 21/48 builtin/apply: move 'no-add' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  28. 22/48 builtin/apply: move 'unsafe_paths' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  29. 23/48 builtin/apply: move 'line_termination' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  30. 24/48 builtin/apply: move 'fake_ancestor' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  31. 25/48 builtin/apply: move 'p_context' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  32. 26/48 builtin/apply: move 'apply' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  33. 27/48 builtin/apply: move 'read_stdin' global into cmd_apply()Christian Couder, Mar 9, 2016
  34. 28/48 builtin/apply: move 'lock_file' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  35. 29/48 builtin/apply: move 'patch_input_file' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  36. 30/48 builtin/apply: move 'limit_by_name' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  37. 31/48 builtin/apply: move 'has_include' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  38. 32/48 builtin/apply: move 'p_value' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  39. 33/48 builtin/apply: move 'p_value_known' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  40. 34/48 builtin/apply: move 'root' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  41. 35/48 builtin/apply: move 'whitespace_error' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  42. 36/48 builtin/apply: move 'whitespace_option' into 'struct apply_state'Christian Couder, Mar 9, 2016
  43. 37/48 builtin/apply: remove whitespace_option arg from set_default_whitespace_mode()Christian Couder, Mar 9, 2016
  44. 38/48 builtin/apply: move 'squelch_whitespace_errors' into 'struct apply_state'Christian Couder, Mar 9, 2016
  45. 39/48 builtin/apply: move 'applied_after_fixing_ws' into 'struct apply_state'Christian Couder, Mar 9, 2016
  46. 40/48 builtin/apply: move 'ws_error_action' into 'struct apply_state'Christian Couder, Mar 9, 2016
  47. 41/48 builtin/apply: move 'ws_ignore_action' into 'struct apply_state'Christian Couder, Mar 9, 2016
  48. 42/48 builtin/apply: move 'max_change' and 'max_len' into 'struct apply_state'Christian Couder, Mar 9, 2016
  49. 43/48 builtin/apply: move 'linenr' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  50. 44/48 builtin/apply: move 'fn_table' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  51. 45/48 builtin/apply: move 'symlink_changes' global into 'struct apply_state'Christian Couder, Mar 9, 2016
  52. 46/48 builtin/apply: move 'state' init into init_apply_state()Christian Couder, Mar 9, 2016
  53. 47/48 builtin/apply: move 'state' check into check_apply_state()Christian Couder, Mar 9, 2016
  54. 48/48 builtin/apply: move applying patches into apply_all_patches()Christian Couder, Mar 9, 2016
  55. Junio C HamanoMar 9, 2016
  56. Christian CouderMar 11, 2016
  57. Duy NguyenMar 10, 2016
  58. Christian CouderMar 11, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.