From: Josh Steadmon <steadmon@google.com>
To: git@vger.kernel.org
Cc: jonathantanmy@google.com, calvinwan@google.com,
glencbz@gmail.com, gitster@pobox.com
Subject: [PATCH v3 0/5] config-parse: create config parsing library
Date: Thu, 21 Sep 2023 14:17:19 -0700 [thread overview]
Message-ID: <cover.1695330852.git.steadmon@google.com> (raw)
In-Reply-To: <pull.1551.git.git.1689891436.gitgitgadget@gmail.com>
Config parsing no longer uses global state as of gc/config-context, so the
natural next step for libification is to turn that into its own library.
This series starts that process by moving config parsing into
config-parse.[c|h] so that other programs can include this functionality
without pulling in all of config.[c|h].
Open questions:
- How do folks feel about the do_event() refactor in patches 2 & 3?
Changes since v2:
- Added patch 2/5 to refactor do_event() into start_event() and
flush_event().
- In patch 3/5, we can now add do_event_and_flush() to immediately run
an event callback, rather than having to do_event() twice in a row.
Changes since v1.5:
- Dropped patch 1/5: config: return positive from git_config_parse_key()
Glen Choo (4):
config: split out config_parse_options
config: report config parse errors using cb
config.c: accept config_parse_options in git_config_from_stdin
config-parse: split library out of config.[c|h]
Josh Steadmon (1):
config: split do_event() into start and flush operations
Makefile | 1 +
builtin/config.c | 4 +-
bundle-uri.c | 4 +-
config-parse.c | 601 +++++++++++++++++++++++++++++++++++++++++
config-parse.h | 155 +++++++++++
config.c | 658 ++++-----------------------------------------
config.h | 134 +--------
fsck.c | 4 +-
submodule-config.c | 9 +-
9 files changed, 836 insertions(+), 734 deletions(-)
create mode 100644 config-parse.c
create mode 100644 config-parse.h
Range-diff against v2:
1: 5c676fbac3 ! 1: fa55b7836f config: split out config_parse_options
@@ Metadata
## Commit message ##
config: split out config_parse_options
- "struct config_options" is a disjoint set of options options used by the
- config parser (e.g. event listners) and options used by
- config_with_options() (e.g. to handle includes, choose which config
- files to parse). Split parser-only options into config_parse_options.
+ "struct config_options" is a disjoint set of options used by the config
+ parser (e.g. event listeners) and options used by config_with_options()
+ (e.g. to handle includes, choose which config files to parse). Split
+ parser-only options into config_parse_options.
Signed-off-by: Glen Choo <chooglen@google.com>
## bundle-uri.c ##
-: ---------- > 2: 8a1463c223 config: split do_event() into start and flush operations
2: cb92a1f2e3 ! 3: a888045c04 config: report config parse errors using cb
@@ Commit message
CONFIG_ERROR_UNSET and the config_source 'default', since all callers
are now expected to specify the error handling they want.
+ Add a new "do_event_and_flush" function for running event callbacks
+ immediately, where the event does not need to calculate an end offset.
+
Signed-off-by: Glen Choo <chooglen@google.com>
## builtin/config.c ##
@@ config.c: static int add_remote_url(const char *var, const char *value,
opts = *inc->opts;
opts.unconditional_remote_url = 1;
+@@ config.c: static int do_event(struct config_source *cs, enum config_event_t type,
+ return 0;
+ }
+
++static int do_event_and_flush(struct config_source *cs,
++ enum config_event_t type,
++ struct parse_event_data *data)
++{
++ int maybe_ret;
++
++ if ((maybe_ret = flush_event(cs, type, data)) < 1)
++ return maybe_ret;
++
++ start_event(cs, type, data);
++
++ if ((maybe_ret = flush_event(cs, type, data)) < 1)
++ return maybe_ret;
++
++ /*
++ * Not actually EOF, but this indicates we don't have a valid event
++ * to flush next time around.
++ */
++ data->previous_type = CONFIG_EVENT_EOF;
++
++ return 0;
++}
++
+ static void kvi_from_source(struct config_source *cs,
+ enum config_scope scope,
+ struct key_value_info *out)
@@ config.c: static void kvi_from_source(struct config_source *cs,
out->path = cs->path;
}
@@ config.c: static int git_parse_source(struct config_source *cs, config_fn_t fn,
-
- free(error_msg);
- return error_return;
-+ /*
-+ * FIXME for whatever reason, do_event passes the _previous_ event, so
-+ * in order for our callback to receive the error event, we have to call
-+ * do_event twice
-+ */
-+ do_event(cs, CONFIG_EVENT_ERROR, &event_data);
-+ do_event(cs, CONFIG_EVENT_ERROR, &event_data);
++ do_event_and_flush(cs, CONFIG_EVENT_ERROR, &event_data);
+ return -1;
}
@@ config.c: void read_early_config(config_fn_t cb, void *data)
void read_very_early_config(config_fn_t cb, void *data)
{
- struct config_options opts = { 0 };
+-
+- opts.respect_includes = 1;
+- opts.ignore_repo = 1;
+- opts.ignore_worktree = 1;
+- opts.ignore_cmdline = 1;
+- opts.system_gently = 1;
+ struct config_options opts = {
++ .respect_includes = 1,
++ .ignore_repo = 1,
++ .ignore_worktree = 1,
++ .ignore_cmdline = 1,
++ .system_gently = 1,
+ .parse_options = CP_OPTS_INIT(CONFIG_ERROR_DIE),
+ };
- opts.respect_includes = 1;
- opts.ignore_repo = 1;
+ config_with_options(cb, data, NULL, NULL, &opts);
+ }
@@ config.c: int git_configset_get_pathname(struct config_set *set, const char *key, const ch
/* Functions use to read configuration from a repository */
static void repo_read_config(struct repository *repo)
@@ config.c: int git_configset_get_pathname(struct config_set *set, const char *key
opts.respect_includes = 1;
opts.commondir = repo->commondir;
-@@ config.c: int repo_config_get_pathname(struct repository *repo,
- static void read_protected_config(void)
- {
- struct config_options opts = {
-- .respect_includes = 1,
-- .ignore_repo = 1,
-- .ignore_worktree = 1,
-- .system_gently = 1,
+@@ config.c: static void read_protected_config(void)
+ .ignore_repo = 1,
+ .ignore_worktree = 1,
+ .system_gently = 1,
+ .parse_options = CP_OPTS_INIT(CONFIG_ERROR_DIE),
};
-+ opts.respect_includes = 1;
-+ opts.ignore_repo = 1;
-+ opts.ignore_worktree = 1;
-+ opts.system_gently = 1;
+
git_configset_init(&protected_config);
config_with_options(config_set_callback, &protected_config, NULL,
3: e034d0780c = 4: 49d4b64991 config.c: accept config_parse_options in git_config_from_stdin
4: 74c5dcd5a2 ! 5: e59ca992d0 config-parse: split library out of config.[c|h]
@@ config-parse.c (new)
+ const struct config_parse_options *opts;
+};
+
-+static int do_event(struct config_source *cs, enum config_event_t type,
-+ struct parse_event_data *data)
++static size_t get_corrected_offset(struct config_source *cs,
++ enum config_event_t type)
+{
-+ size_t offset;
-+
-+ if (!data->opts || !data->opts->event_fn)
-+ return 0;
++ size_t offset = cs->do_ftell(cs);
+
-+ if (type == CONFIG_EVENT_WHITESPACE &&
-+ data->previous_type == type)
-+ return 0;
-+
-+ offset = cs->do_ftell(cs);
+ /*
+ * At EOF, the parser always "inserts" an extra '\n', therefore
+ * the end offset of the event is the current file position, otherwise
@@ config-parse.c (new)
+ */
+ if (type != CONFIG_EVENT_EOF)
+ offset--;
++ return offset;
++}
++
++static void start_event(struct config_source *cs, enum config_event_t type,
++ struct parse_event_data *data)
++{
++ data->previous_type = type;
++ data->previous_offset = get_corrected_offset(cs, type);
++}
++
++static int flush_event(struct config_source *cs, enum config_event_t type,
++ struct parse_event_data *data)
++{
++ if (!data->opts || !data->opts->event_fn)
++ return 0;
++
++ if (type == CONFIG_EVENT_WHITESPACE &&
++ data->previous_type == type)
++ return 0;
+
+ if (data->previous_type != CONFIG_EVENT_EOF &&
+ data->opts->event_fn(data->previous_type, data->previous_offset,
-+ offset, cs, data->opts->event_fn_data) < 0)
++ get_corrected_offset(cs, type), cs,
++ data->opts->event_fn_data) < 0)
+ return -1;
+
-+ data->previous_type = type;
-+ data->previous_offset = offset;
++ return 1;
++}
++
++static int do_event(struct config_source *cs, enum config_event_t type,
++ struct parse_event_data *data)
++{
++ int maybe_ret;
++
++ if ((maybe_ret = flush_event(cs, type, data)) < 1)
++ return maybe_ret;
++
++ start_event(cs, type, data);
++
++ return 0;
++}
++
++static int do_event_and_flush(struct config_source *cs,
++ enum config_event_t type,
++ struct parse_event_data *data)
++{
++ int maybe_ret;
++
++ if ((maybe_ret = flush_event(cs, type, data)) < 1)
++ return maybe_ret;
++
++ start_event(cs, type, data);
++
++ if ((maybe_ret = flush_event(cs, type, data)) < 1)
++ return maybe_ret;
++
++ /*
++ * Not actually EOF, but this indicates we don't have a valid event
++ * to flush next time around.
++ */
++ data->previous_type = CONFIG_EVENT_EOF;
+
+ return 0;
+}
@@ config-parse.c (new)
+ if (get_value(cs, kvi, fn, data, var) < 0)
+ break;
+ }
-+ /*
-+ * FIXME for whatever reason, do_event passes the _previous_ event, so
-+ * in order for our callback to receive the error event, we have to call
-+ * do_event twice
-+ */
-+ do_event(cs, CONFIG_EVENT_ERROR, &event_data);
-+ do_event(cs, CONFIG_EVENT_ERROR, &event_data);
++
++ do_event_and_flush(cs, CONFIG_EVENT_ERROR, &event_data);
+ return -1;
+}
+
@@ config.c: int git_config_from_parameters(config_fn_t fn, void *data)
- const struct config_parse_options *opts;
-};
-
--static int do_event(struct config_source *cs, enum config_event_t type,
-- struct parse_event_data *data)
+-static size_t get_corrected_offset(struct config_source *cs,
+- enum config_event_t type)
-{
-- size_t offset;
--
-- if (!data->opts || !data->opts->event_fn)
-- return 0;
+- size_t offset = cs->do_ftell(cs);
-
-- if (type == CONFIG_EVENT_WHITESPACE &&
-- data->previous_type == type)
-- return 0;
--
-- offset = cs->do_ftell(cs);
- /*
- * At EOF, the parser always "inserts" an extra '\n', therefore
- * the end offset of the event is the current file position, otherwise
@@ config.c: int git_config_from_parameters(config_fn_t fn, void *data)
- */
- if (type != CONFIG_EVENT_EOF)
- offset--;
+- return offset;
+-}
+-
+-static void start_event(struct config_source *cs, enum config_event_t type,
+- struct parse_event_data *data)
+-{
+- data->previous_type = type;
+- data->previous_offset = get_corrected_offset(cs, type);
+-}
+-
+-static int flush_event(struct config_source *cs, enum config_event_t type,
+- struct parse_event_data *data)
+-{
+- if (!data->opts || !data->opts->event_fn)
+- return 0;
+-
+- if (type == CONFIG_EVENT_WHITESPACE &&
+- data->previous_type == type)
+- return 0;
-
- if (data->previous_type != CONFIG_EVENT_EOF &&
- data->opts->event_fn(data->previous_type, data->previous_offset,
-- offset, cs, data->opts->event_fn_data) < 0)
+- get_corrected_offset(cs, type), cs,
+- data->opts->event_fn_data) < 0)
- return -1;
-
-- data->previous_type = type;
-- data->previous_offset = offset;
+- return 1;
+-}
+-
+-static int do_event(struct config_source *cs, enum config_event_t type,
+- struct parse_event_data *data)
+-{
+- int maybe_ret;
+-
+- if ((maybe_ret = flush_event(cs, type, data)) < 1)
+- return maybe_ret;
+-
+- start_event(cs, type, data);
+-
+- return 0;
+-}
+-
+-static int do_event_and_flush(struct config_source *cs,
+- enum config_event_t type,
+- struct parse_event_data *data)
+-{
+- int maybe_ret;
+-
+- if ((maybe_ret = flush_event(cs, type, data)) < 1)
+- return maybe_ret;
+-
+- start_event(cs, type, data);
+-
+- if ((maybe_ret = flush_event(cs, type, data)) < 1)
+- return maybe_ret;
+-
+- /*
+- * Not actually EOF, but this indicates we don't have a valid event
+- * to flush next time around.
+- */
+- data->previous_type = CONFIG_EVENT_EOF;
-
- return 0;
-}
@@ config.c: int git_config_err_fn(enum config_event_t type, size_t begin_offset UN
- break;
- }
-
-- /*
-- * FIXME for whatever reason, do_event passes the _previous_ event, so
-- * in order for our callback to receive the error event, we have to call
-- * do_event twice
-- */
-- do_event(cs, CONFIG_EVENT_ERROR, &event_data);
-- do_event(cs, CONFIG_EVENT_ERROR, &event_data);
+- do_event_and_flush(cs, CONFIG_EVENT_ERROR, &event_data);
- return -1;
-}
-
base-commit: aa9166bcc0ba654fc21f198a30647ec087f733ed
--
2.42.0.515.g380fc7ccd1-goog
next prev parent reply other threads:[~2023-09-21 21:41 UTC|newest]
Thread overview: 49+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-20 22:17 [PATCH 0/2] config-parse: create config parsing library Glen Choo via GitGitGadget
2023-07-20 22:17 ` [PATCH 1/2] config: return positive from git_config_parse_key() Glen Choo via GitGitGadget
2023-07-20 23:44 ` Jonathan Tan
2023-07-21 4:32 ` Junio C Hamano
2023-07-21 16:12 ` Glen Choo
2023-07-21 16:36 ` Junio C Hamano
2023-07-20 22:17 ` [PATCH 2/2] config-parse: split library out of config.[c|h] Glen Choo via GitGitGadget
2023-07-21 0:31 ` Jonathan Tan
2023-07-21 15:55 ` Glen Choo
2023-07-31 23:46 ` [RFC PATCH v1.5 0/5] config-parse: create config parsing library Glen Choo
2023-07-31 23:46 ` [RFC PATCH v1.5 1/5] config: return positive from git_config_parse_key() Glen Choo
2023-07-31 23:46 ` [RFC PATCH v1.5 2/5] config: split out config_parse_options Glen Choo
2023-07-31 23:46 ` [RFC PATCH v1.5 3/5] config: report config parse errors using cb Glen Choo
2023-08-04 21:34 ` Jonathan Tan
2023-07-31 23:46 ` [RFC PATCH v1.5 4/5] config.c: accept config_parse_options in git_config_from_stdin Glen Choo
2023-07-31 23:46 ` [RFC PATCH v1.5 5/5] config-parse: split library out of config.[c|h] Glen Choo
2023-08-23 21:53 ` [PATCH v2 0/4] config-parse: create config parsing library Josh Steadmon
2023-08-23 21:53 ` [PATCH v2 1/4] config: split out config_parse_options Josh Steadmon
2023-08-23 23:26 ` Junio C Hamano
2023-09-21 21:08 ` Josh Steadmon
2023-08-23 21:53 ` [PATCH v2 2/4] config: report config parse errors using cb Josh Steadmon
2023-08-24 1:19 ` Junio C Hamano
2023-08-24 17:31 ` Jonathan Tan
2023-08-24 18:48 ` Junio C Hamano
2023-09-21 21:11 ` Josh Steadmon
2023-09-21 23:36 ` Junio C Hamano
2023-08-23 21:53 ` [PATCH v2 3/4] config.c: accept config_parse_options in git_config_from_stdin Josh Steadmon
2023-08-23 21:53 ` [PATCH v2 4/4] config-parse: split library out of config.[c|h] Josh Steadmon
2023-08-24 20:10 ` [PATCH v2 0/4] config-parse: create config parsing library Josh Steadmon
2023-09-21 21:17 ` Josh Steadmon [this message]
2023-09-21 21:17 ` [PATCH v3 1/5] config: split out config_parse_options Josh Steadmon
2023-10-23 17:52 ` Jonathan Tan
2023-10-23 18:46 ` Taylor Blau
2023-09-21 21:17 ` [PATCH v3 2/5] config: split do_event() into start and flush operations Josh Steadmon
2023-10-23 18:05 ` Jonathan Tan
2023-09-21 21:17 ` [PATCH v3 3/5] config: report config parse errors using cb Josh Steadmon
2023-10-23 18:41 ` Jonathan Tan
2023-10-23 19:29 ` Taylor Blau
2023-10-23 20:11 ` Junio C Hamano
2023-09-21 21:17 ` [PATCH v3 4/5] config.c: accept config_parse_options in git_config_from_stdin Josh Steadmon
2023-10-23 18:52 ` Jonathan Tan
2023-09-21 21:17 ` [PATCH v3 5/5] config-parse: split library out of config.[c|h] Josh Steadmon
2023-10-23 18:53 ` Jonathan Tan
2023-10-17 17:13 ` [PATCH v3 0/5] config-parse: create config parsing library Junio C Hamano
2023-10-23 19:34 ` Taylor Blau
2023-10-23 20:13 ` Junio C Hamano
2023-10-24 22:50 ` Jonathan Tan
2023-10-25 19:37 ` Josh Steadmon
2023-10-27 13:04 ` Junio C Hamano
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cover.1695330852.git.steadmon@google.com \
--to=steadmon@google.com \
--cc=calvinwan@google.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=glencbz@gmail.com \
--cc=jonathantanmy@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).