* [PATCH] handle_options(): do not miscount how many arguments were used
@ 2011-05-24 21:15 Junio C Hamano
2011-05-24 21:18 ` [PATCH] Allow built-ins to also use -c var=val via alias Junio C Hamano
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2011-05-24 21:15 UTC (permalink / raw)
To: git; +Cc: Jeff King, Kazuki Tsujimoto, Alex Riesen
The handle_options() function advances the base of the argument array and
returns the number of arguments it used. The caller in handle_alias()
wants to reallocate the argv array it passes to this function, and
attempts to do so by subtracting the returned value to compensate for the
change handle_options() makes to the new_argv.
But handle_options() did not correctly count when "-c <config=value>" is
given, causing a wrong pointer to be passed to realloc().
Fix it by saving the original argv at the beginning of handle_options(),
and return the difference between the final value of argv, which will
relieve the places that move the array pointer from the additional burden
of keeping track of "handled" counter.
Noticed-by: Kazuki Tsujimoto
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* This fixes 8b1fa77 (Allow passing of configuration parameters in the
command line, 2010-03-26), and when applied there, the new test passes,
but if applied to newer codebase, the test fails for a different
reason, for which another fix will be sent out separately.
git.c | 6 ++----
t/t1300-repo-config.sh | 10 ++++++++++
2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/git.c b/git.c
index 1753811..55c2eda 100644
--- a/git.c
+++ b/git.c
@@ -53,7 +53,7 @@ static void commit_pager_choice(void) {
static int handle_options(const char ***argv, int *argc, int *envchanged)
{
- int handled = 0;
+ const char **orig_argv = *argv;
if (!getenv("GIT_ASKPASS") && getenv("SSH_ASKPASS"))
setenv("GIT_ASKPASS", getenv("SSH_ASKPASS"), 1);
@@ -106,7 +106,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
*envchanged = 1;
(*argv)++;
(*argc)--;
- handled++;
} else if (!prefixcmp(cmd, "--git-dir=")) {
setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
if (envchanged)
@@ -146,9 +145,8 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
(*argv)++;
(*argc)--;
- handled++;
}
- return handled;
+ return (*argv) - orig_argv;
}
static int handle_alias(int *argcp, const char ***argv)
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 64f0508..5f6766d 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -832,4 +832,14 @@ test_expect_success 'git -c "key=value" support' '
test_must_fail git -c core.name=value config name
'
+test_expect_success 'alias to give a configuration value' '
+ echo "foo and space " >foo &&
+ git diff HEAD >foo.patch &&
+ git checkout foo &&
+ git config alias.aw "-c apply.whitespace=fix apply" &&
+ git aw foo.patch &&
+ echo "foo and space" >expect &&
+ test_cmp expect foo
+'
+
test_done
--
1.7.5.2.459.g67e41
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH] Allow built-ins to also use -c var=val via alias
2011-05-24 21:15 [PATCH] handle_options(): do not miscount how many arguments were used Junio C Hamano
@ 2011-05-24 21:18 ` Junio C Hamano
2011-05-24 21:46 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Junio C Hamano @ 2011-05-24 21:18 UTC (permalink / raw)
To: Jeff King; +Cc: git
The previous commit 2b64fc8 (pass "git -c foo=bar" params through
environment, 2010-08-23) tried to make all the one-shot configuration
setting made via the "-c" option to the "git" wrapper go through an
environment variable, so that the value can be propagated to external
commands _as well as_ the internal ones, but ended up breaking one of the
codepaths that invokes internal commands, because it incorrectly assumed
that git_config_from_parmeters() can never be called in a single process
after git_config_parse_environment() was called once.
Not so.
When the options came as part of an alias to an internal command, e.g.
[alias]
aw = -c apply.whitespace=fix apply
and then run as "git aw P.diff", we have already read the configuration to
find out about the alias definition (setting loaded_environment to true),
then pushed apply.whitespace=fix to the environment, but not to the
in-core list of configuration variables. The implementation of the
internal command, e.g. cmd_apply(), will try to read from git_config() but
the setting is lost, as the environment is never read in this codepath.
Add the in-core queuing of the parameters back to fix this.
Note that the handling of such an alias is still broken for another reason
in this codepath; a separate patch fixes it.
While at it, avoid getting our test confused by GIT_CONFIG_PARAMETERS
exported to the tester's environment.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
* And this is the other fix. Applying this on top of 2b64fc8 does not
make "git aw P.diff" in the test t1300 in the other patch, but this
is prerequisite for the other fix to work in a more modern codebase.
config.c | 1 +
t/test-lib.sh | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/config.c b/config.c
index c2c995f..c803ae8 100644
--- a/config.c
+++ b/config.c
@@ -43,6 +43,7 @@ void git_config_push_parameter(const char *text)
strbuf_addstr(&env, old);
strbuf_addch(&env, ' ');
}
+ git_config_parse_parameter(text);
sq_quote_buf(&env, text);
setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
strbuf_release(&env);
diff --git a/t/test-lib.sh b/t/test-lib.sh
index e5523dd..0b1358e 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -57,6 +57,7 @@ GIT_AUTHOR_NAME='A U Thor'
unset GIT_COMMITTER_DATE
GIT_COMMITTER_EMAIL=committer@example.com
GIT_COMMITTER_NAME='C O Mitter'
+unset GIT_CONFIG_PARAMETERS
unset GIT_DIFF_OPTS
unset GIT_DIR
unset GIT_WORK_TREE
--
1.7.5.2.459.g67e41
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] Allow built-ins to also use -c var=val via alias
2011-05-24 21:18 ` [PATCH] Allow built-ins to also use -c var=val via alias Junio C Hamano
@ 2011-05-24 21:46 ` Jeff King
2011-05-24 21:52 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2011-05-24 21:46 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Tue, May 24, 2011 at 02:18:18PM -0700, Junio C Hamano wrote:
> When the options came as part of an alias to an internal command, e.g.
>
> [alias]
> aw = -c apply.whitespace=fix apply
>
> and then run as "git aw P.diff", we have already read the configuration to
> find out about the alias definition (setting loaded_environment to true),
> then pushed apply.whitespace=fix to the environment, but not to the
> in-core list of configuration variables. The implementation of the
> internal command, e.g. cmd_apply(), will try to read from git_config() but
> the setting is lost, as the environment is never read in this codepath.
>
> Add the in-core queuing of the parameters back to fix this.
Hmm. I'm not sure that is right. The fatal assumption in 2b64fc89 is
that we do not load the parameters again once they have already been
loaded. So if your sequence is:
git_config(...);
git_config_push_parameter(...);
git_config(...);
then the first git_config will try git_config_from_parameters, which
will call git_config_parse_environment, which will set the static
loaded_environment variable. And so in the second git_config call, we
will not reparse the environment, and your fix is correct.
But what if the sequence is:
git_config_push_parameter(...);
git_config(...);
With your fix, the push_parameter will add the variable to the in-memory
list, and put it in the environment. But our git_config call will then
re-parse the environment, adding a duplicate of the variable.
For most variables, that means a simple overwrite. But there are some
that are additive if multiple instances are found, and they may be
broken.
I say "may" because I am not sure if there are code paths which don't
call git_config before git_config_push_parameter. I suspect there are,
since otherwise "-c" wouldn't work for builtins at all. Even if there
aren't, I'd rather not leave such a fragile thing in place.
I think the right fix is simply to drop the "don't re-check the
environment after the first time" logic. It's not expensive to parse
compared to parsing config files, which is when we would do it. We can
just drop the existing list and reparse. You can even get rid of the
whole list and drop a bunch of code, I think, like:
---
config.c | 53 +++++++++++++++--------------------------------------
1 files changed, 15 insertions(+), 38 deletions(-)
diff --git a/config.c b/config.c
index 80dc715..bc5666f 100644
--- a/config.c
+++ b/config.c
@@ -20,14 +20,6 @@ static int zlib_compression_seen;
const char *config_exclusive_filename = NULL;
-struct config_item {
- struct config_item *next;
- char *name;
- char *value;
-};
-static struct config_item *config_parameters;
-static struct config_item **config_parameters_tail = &config_parameters;
-
static void lowercase(char *p)
{
for (; *p; p++)
@@ -47,9 +39,9 @@ void git_config_push_parameter(const char *text)
strbuf_release(&env);
}
-int git_config_parse_parameter(const char *text)
+int git_config_parse_parameter(const char *text,
+ const char **name, const char **value)
{
- struct config_item *ct;
struct strbuf tmp = STRBUF_INIT;
struct strbuf **pair;
strbuf_addstr(&tmp, text);
@@ -61,25 +53,24 @@ int git_config_parse_parameter(const char *text)
strbuf_list_free(pair);
return -1;
}
- ct = xcalloc(1, sizeof(struct config_item));
- ct->name = strbuf_detach(pair[0], NULL);
+ *key = strbuf_detach(pair[0], NULL);
if (pair[1]) {
strbuf_trim(pair[1]);
- ct->value = strbuf_detach(pair[1], NULL);
+ *value = strbuf_detach(pair[1], NULL);
}
strbuf_list_free(pair);
- lowercase(ct->name);
- *config_parameters_tail = ct;
- config_parameters_tail = &ct->next;
+ lowercase(name);
return 0;
}
-int git_config_parse_environment(void) {
+int git_config_from_parameters(config_fn_t fn, void *data)
+{
const char *env = getenv(CONFIG_DATA_ENVIRONMENT);
char *envw;
const char **argv = NULL;
int nr = 0, alloc = 0;
int i;
+ int ret = -1;
if (!env)
return 0;
@@ -92,17 +83,19 @@ int git_config_parse_environment(void) {
}
for (i = 0; i < nr; i++) {
- if (git_config_parse_parameter(argv[i]) < 0) {
+ if (git_config_parse_parameter(argv[i], &name, &value) < 0) {
error("bogus config parameter: %s", argv[i]);
- free(argv);
- free(envw);
- return -1;
+ goto out;
}
+ if (fn(name, value, data) < 0)
+ goto out;
}
+ ret = 0;
+out:
free(argv);
free(envw);
- return 0;
+ return ret;
}
static int get_next_char(void)
@@ -850,22 +843,6 @@ int git_config_system(void)
return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
}
-int git_config_from_parameters(config_fn_t fn, void *data)
-{
- static int loaded_environment;
- const struct config_item *ct;
-
- if (!loaded_environment) {
- if (git_config_parse_environment() < 0)
- return -1;
- loaded_environment = 1;
- }
- for (ct = config_parameters; ct; ct = ct->next)
- if (fn(ct->name, ct->value, data) < 0)
- return -1;
- return 0;
-}
-
int git_config_early(config_fn_t fn, void *data, const char *repo_config)
{
int ret = 0, found = 0;
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] Allow built-ins to also use -c var=val via alias
2011-05-24 21:46 ` Jeff King
@ 2011-05-24 21:52 ` Jeff King
2011-05-24 21:57 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2011-05-24 21:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Tue, May 24, 2011 at 05:46:18PM -0400, Jeff King wrote:
> I think the right fix is simply to drop the "don't re-check the
> environment after the first time" logic. It's not expensive to parse
> compared to parsing config files, which is when we would do it. We can
> just drop the existing list and reparse. You can even get rid of the
> whole list and drop a bunch of code, I think, like:
Ack, wrong patch. That one doesn't even come close to compiling.
Try this (still not well tested, though).
---
cache.h | 2 -
config.c | 68 ++++++++++++++++++++++++-------------------------------------
2 files changed, 27 insertions(+), 43 deletions(-)
diff --git a/cache.h b/cache.h
index 28a921d..69e09a1 100644
--- a/cache.h
+++ b/cache.h
@@ -1037,8 +1037,6 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
extern int git_default_config(const char *, const char *, void *);
extern int git_config_from_file(config_fn_t fn, const char *, void *);
extern void git_config_push_parameter(const char *text);
-extern int git_config_parse_parameter(const char *text);
-extern int git_config_parse_environment(void);
extern int git_config_from_parameters(config_fn_t fn, void *data);
extern int git_config(config_fn_t fn, void *);
extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
diff --git a/config.c b/config.c
index 9d36848..90d5e6d 100644
--- a/config.c
+++ b/config.c
@@ -20,14 +20,6 @@ static int zlib_compression_seen;
const char *config_exclusive_filename = NULL;
-struct config_item {
- struct config_item *next;
- char *name;
- char *value;
-};
-static struct config_item *config_parameters;
-static struct config_item **config_parameters_tail = &config_parameters;
-
static void lowercase(char *p)
{
for (; *p; p++)
@@ -47,9 +39,9 @@ void git_config_push_parameter(const char *text)
strbuf_release(&env);
}
-int git_config_parse_parameter(const char *text)
+int git_config_parse_parameter(const char *text,
+ char **name, char **value)
{
- struct config_item *ct;
struct strbuf tmp = STRBUF_INIT;
struct strbuf **pair;
strbuf_addstr(&tmp, text);
@@ -61,25 +53,24 @@ int git_config_parse_parameter(const char *text)
strbuf_list_free(pair);
return -1;
}
- ct = xcalloc(1, sizeof(struct config_item));
- ct->name = strbuf_detach(pair[0], NULL);
+ *name = strbuf_detach(pair[0], NULL);
if (pair[1]) {
strbuf_trim(pair[1]);
- ct->value = strbuf_detach(pair[1], NULL);
+ *value = strbuf_detach(pair[1], NULL);
}
strbuf_list_free(pair);
- lowercase(ct->name);
- *config_parameters_tail = ct;
- config_parameters_tail = &ct->next;
+ lowercase(*name);
return 0;
}
-int git_config_parse_environment(void) {
+int git_config_from_parameters(config_fn_t fn, void *data)
+{
const char *env = getenv(CONFIG_DATA_ENVIRONMENT);
char *envw;
const char **argv = NULL;
int nr = 0, alloc = 0;
int i;
+ int ret = 0;
if (!env)
return 0;
@@ -92,17 +83,25 @@ int git_config_parse_environment(void) {
}
for (i = 0; i < nr; i++) {
- if (git_config_parse_parameter(argv[i]) < 0) {
+ char *name, *value;
+ if (git_config_parse_parameter(argv[i], &name, &value) < 0) {
error("bogus config parameter: %s", argv[i]);
- free(argv);
- free(envw);
- return -1;
+ ret = -1;
+ goto out;
}
+ if (fn(name, value, data) < 0) {
+ ret = -1;
+ goto out;
+ }
+ free(name);
+ free(value);
+ ret++;
}
+out:
free(argv);
free(envw);
- return 0;
+ return ret;
}
static int get_next_char(void)
@@ -837,25 +836,10 @@ int git_config_system(void)
return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
}
-int git_config_from_parameters(config_fn_t fn, void *data)
-{
- static int loaded_environment;
- const struct config_item *ct;
-
- if (!loaded_environment) {
- if (git_config_parse_environment() < 0)
- return -1;
- loaded_environment = 1;
- }
- for (ct = config_parameters; ct; ct = ct->next)
- if (fn(ct->name, ct->value, data) < 0)
- return -1;
- return 0;
-}
-
int git_config_early(config_fn_t fn, void *data, const char *repo_config)
{
int ret = 0, found = 0;
+ int n;
const char *home = NULL;
/* Setting $GIT_CONFIG makes git read _only_ the given config file. */
@@ -882,9 +866,11 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
found += 1;
}
- ret += git_config_from_parameters(fn, data);
- if (config_parameters)
- found += 1;
+ n = git_config_from_parameters(fn, data);
+ if (n < 0)
+ ret += n;
+ else
+ found += n;
return ret == 0 ? found : ret;
}
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH] Allow built-ins to also use -c var=val via alias
2011-05-24 21:52 ` Jeff King
@ 2011-05-24 21:57 ` Jeff King
2011-05-24 22:49 ` Jeff King
0 siblings, 1 reply; 10+ messages in thread
From: Jeff King @ 2011-05-24 21:57 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Tue, May 24, 2011 at 05:52:02PM -0400, Jeff King wrote:
> On Tue, May 24, 2011 at 05:46:18PM -0400, Jeff King wrote:
>
> > I think the right fix is simply to drop the "don't re-check the
> > environment after the first time" logic. It's not expensive to parse
> > compared to parsing config files, which is when we would do it. We can
> > just drop the existing list and reparse. You can even get rid of the
> > whole list and drop a bunch of code, I think, like:
>
> Ack, wrong patch. That one doesn't even come close to compiling.
>
> Try this (still not well tested, though).
Ugh, broken. That will teach me to just paste any random junk into my
MUA. Hopefully you got the gist of what I was trying to say, but let me
come up with a more readable and tested series.
-Peff
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Allow built-ins to also use -c var=val via alias
2011-05-24 21:57 ` Jeff King
@ 2011-05-24 22:49 ` Jeff King
2011-05-24 22:49 ` [PATCH 1/4] config: make environment parsing routines static Jeff King
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Jeff King @ 2011-05-24 22:49 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
On Tue, May 24, 2011 at 05:57:59PM -0400, Jeff King wrote:
> On Tue, May 24, 2011 at 05:52:02PM -0400, Jeff King wrote:
>
> > On Tue, May 24, 2011 at 05:46:18PM -0400, Jeff King wrote:
> >
> > > I think the right fix is simply to drop the "don't re-check the
> > > environment after the first time" logic. It's not expensive to parse
> > > compared to parsing config files, which is when we would do it. We can
> > > just drop the existing list and reparse. You can even get rid of the
> > > whole list and drop a bunch of code, I think, like:
> >
> > Ack, wrong patch. That one doesn't even come close to compiling.
> >
> > Try this (still not well tested, though).
>
> Ugh, broken. That will teach me to just paste any random junk into my
> MUA. Hopefully you got the gist of what I was trying to say, but let me
> come up with a more readable and tested series.
OK, for real this time. This is how I would do the whole fix on top of
master, including your 1/2. I'll let you handle the
apply-to-maint-and-merge as you would have with your original series.
The first two are refactoring to make 3/4 a little easier to read. The
third one is my fix, and the fourth is your original patch (together
with my 3/4 it passes the test; btw, I ended up writing a slightly
simpler test. Feel free to throw it out if you prefer yours).
[1/4]: config: make environment parsing routines static
[2/4]: git_config: don't peek at global config_parameters
[3/4]: config: always parse GIT_CONFIG_PARAMETERS during git_config
[4/4]: handle_options(): do not miscount how many arguments were used
-Peff
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/4] config: make environment parsing routines static
2011-05-24 22:49 ` Jeff King
@ 2011-05-24 22:49 ` Jeff King
2011-05-24 22:49 ` [PATCH 2/4] git_config: don't peek at global config_parameters Jeff King
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Jeff King @ 2011-05-24 22:49 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Nobody outside of git_config_from_parameters should need
to use the GIT_CONFIG_PARAMETERS parsing functions, so let's
make them private.
Signed-off-by: Jeff King <peff@peff.net>
---
cache.h | 2 --
config.c | 4 ++--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/cache.h b/cache.h
index 28a921d..69e09a1 100644
--- a/cache.h
+++ b/cache.h
@@ -1037,8 +1037,6 @@ typedef int (*config_fn_t)(const char *, const char *, void *);
extern int git_default_config(const char *, const char *, void *);
extern int git_config_from_file(config_fn_t fn, const char *, void *);
extern void git_config_push_parameter(const char *text);
-extern int git_config_parse_parameter(const char *text);
-extern int git_config_parse_environment(void);
extern int git_config_from_parameters(config_fn_t fn, void *data);
extern int git_config(config_fn_t fn, void *);
extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
diff --git a/config.c b/config.c
index 9d36848..46aeb9c 100644
--- a/config.c
+++ b/config.c
@@ -47,7 +47,7 @@ void git_config_push_parameter(const char *text)
strbuf_release(&env);
}
-int git_config_parse_parameter(const char *text)
+static int git_config_parse_parameter(const char *text)
{
struct config_item *ct;
struct strbuf tmp = STRBUF_INIT;
@@ -74,7 +74,7 @@ int git_config_parse_parameter(const char *text)
return 0;
}
-int git_config_parse_environment(void) {
+static int git_config_parse_environment(void) {
const char *env = getenv(CONFIG_DATA_ENVIRONMENT);
char *envw;
const char **argv = NULL;
--
1.7.4.5.7.g2e01
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/4] git_config: don't peek at global config_parameters
2011-05-24 22:49 ` Jeff King
2011-05-24 22:49 ` [PATCH 1/4] config: make environment parsing routines static Jeff King
@ 2011-05-24 22:49 ` Jeff King
2011-05-24 22:49 ` [PATCH 3/4] config: always parse GIT_CONFIG_PARAMETERS during git_config Jeff King
2011-05-24 22:50 ` [PATCH 4/4] handle_options(): do not miscount how many arguments were used Jeff King
3 siblings, 0 replies; 10+ messages in thread
From: Jeff King @ 2011-05-24 22:49 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
The config_parameters list in config.c is an implementation
detail of git_config_from_parameters; instead, that function
should tell us whether it found anything.
Signed-off-by: Jeff King <peff@peff.net>
---
config.c | 15 +++++++++++----
1 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/config.c b/config.c
index 46aeb9c..fb88839 100644
--- a/config.c
+++ b/config.c
@@ -850,7 +850,7 @@ int git_config_from_parameters(config_fn_t fn, void *data)
for (ct = config_parameters; ct; ct = ct->next)
if (fn(ct->name, ct->value, data) < 0)
return -1;
- return 0;
+ return config_parameters != NULL;
}
int git_config_early(config_fn_t fn, void *data, const char *repo_config)
@@ -882,9 +882,16 @@ int git_config_early(config_fn_t fn, void *data, const char *repo_config)
found += 1;
}
- ret += git_config_from_parameters(fn, data);
- if (config_parameters)
- found += 1;
+ switch (git_config_from_parameters(fn, data)) {
+ case -1: /* error */
+ ret--;
+ break;
+ case 0: /* found nothing */
+ break;
+ default: /* found at least one item */
+ found++;
+ break;
+ }
return ret == 0 ? found : ret;
}
--
1.7.4.5.7.g2e01
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/4] config: always parse GIT_CONFIG_PARAMETERS during git_config
2011-05-24 22:49 ` Jeff King
2011-05-24 22:49 ` [PATCH 1/4] config: make environment parsing routines static Jeff King
2011-05-24 22:49 ` [PATCH 2/4] git_config: don't peek at global config_parameters Jeff King
@ 2011-05-24 22:49 ` Jeff King
2011-05-24 22:50 ` [PATCH 4/4] handle_options(): do not miscount how many arguments were used Jeff King
3 siblings, 0 replies; 10+ messages in thread
From: Jeff King @ 2011-05-24 22:49 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Previously we parsed GIT_CONFIG_PARAMETERS lazily into a
linked list, and then checked that list during future
invocations of git_config. However, that ignores the fact
that the environment variable could change during our run
(e.g., because we parse more "-c" as part of an alias).
Instead, let's just re-parse the environment variable each
time. It's generally not very big, and it's no more work
than parsing the config files, anyway.
As a bonus, we can ditch all of the linked list storage code
entirely, making the code much simpler.
The test unfortunately still does not pass because of an
unrelated bug in handle_options.
Signed-off-by: Jeff King <peff@peff.net>
---
config.c | 50 ++++++++++-------------------------------------
t/t1300-repo-config.sh | 7 ++++++
2 files changed, 18 insertions(+), 39 deletions(-)
diff --git a/config.c b/config.c
index fb88839..e0b3b80 100644
--- a/config.c
+++ b/config.c
@@ -20,14 +20,6 @@ static int zlib_compression_seen;
const char *config_exclusive_filename = NULL;
-struct config_item {
- struct config_item *next;
- char *name;
- char *value;
-};
-static struct config_item *config_parameters;
-static struct config_item **config_parameters_tail = &config_parameters;
-
static void lowercase(char *p)
{
for (; *p; p++)
@@ -47,9 +39,9 @@ void git_config_push_parameter(const char *text)
strbuf_release(&env);
}
-static int git_config_parse_parameter(const char *text)
+static int git_config_parse_parameter(const char *text,
+ config_fn_t fn, void *data)
{
- struct config_item *ct;
struct strbuf tmp = STRBUF_INIT;
struct strbuf **pair;
strbuf_addstr(&tmp, text);
@@ -59,22 +51,19 @@ static int git_config_parse_parameter(const char *text)
strbuf_trim(pair[0]);
if (!pair[0]->len) {
strbuf_list_free(pair);
- return -1;
+ return error("bogus config parameter: %s", text);
}
- ct = xcalloc(1, sizeof(struct config_item));
- ct->name = strbuf_detach(pair[0], NULL);
- if (pair[1]) {
- strbuf_trim(pair[1]);
- ct->value = strbuf_detach(pair[1], NULL);
+ lowercase(pair[0]->buf);
+ if (fn(pair[0]->buf, pair[1] ? pair[1]->buf : NULL, data) < 0) {
+ strbuf_list_free(pair);
+ return -1;
}
strbuf_list_free(pair);
- lowercase(ct->name);
- *config_parameters_tail = ct;
- config_parameters_tail = &ct->next;
return 0;
}
-static int git_config_parse_environment(void) {
+int git_config_from_parameters(config_fn_t fn, void *data)
+{
const char *env = getenv(CONFIG_DATA_ENVIRONMENT);
char *envw;
const char **argv = NULL;
@@ -92,8 +81,7 @@ static int git_config_parse_environment(void) {
}
for (i = 0; i < nr; i++) {
- if (git_config_parse_parameter(argv[i]) < 0) {
- error("bogus config parameter: %s", argv[i]);
+ if (git_config_parse_parameter(argv[i], fn, data) < 0) {
free(argv);
free(envw);
return -1;
@@ -102,7 +90,7 @@ static int git_config_parse_environment(void) {
free(argv);
free(envw);
- return 0;
+ return nr > 0;
}
static int get_next_char(void)
@@ -837,22 +825,6 @@ int git_config_system(void)
return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
}
-int git_config_from_parameters(config_fn_t fn, void *data)
-{
- static int loaded_environment;
- const struct config_item *ct;
-
- if (!loaded_environment) {
- if (git_config_parse_environment() < 0)
- return -1;
- loaded_environment = 1;
- }
- for (ct = config_parameters; ct; ct = ct->next)
- if (fn(ct->name, ct->value, data) < 0)
- return -1;
- return config_parameters != NULL;
-}
-
int git_config_early(config_fn_t fn, void *data, const char *repo_config)
{
int ret = 0, found = 0;
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 53fb822..fe7a153 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -897,4 +897,11 @@ test_expect_success 'key sanity-checking' '
git config foo."ba =z".bar false
'
+test_expect_failure 'git -c works with aliases of builtins' '
+ git config alias.checkconfig "-c foo.check=bar config foo.check" &&
+ echo bar >expect &&
+ git checkconfig >actual &&
+ test_cmp expect actual
+'
+
test_done
--
1.7.4.5.7.g2e01
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/4] handle_options(): do not miscount how many arguments were used
2011-05-24 22:49 ` Jeff King
` (2 preceding siblings ...)
2011-05-24 22:49 ` [PATCH 3/4] config: always parse GIT_CONFIG_PARAMETERS during git_config Jeff King
@ 2011-05-24 22:50 ` Jeff King
3 siblings, 0 replies; 10+ messages in thread
From: Jeff King @ 2011-05-24 22:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
From: Junio C Hamano <gitster@pobox.com>
The handle_options() function advances the base of the argument array and
returns the number of arguments it used. The caller in handle_alias()
wants to reallocate the argv array it passes to this function, and
attempts to do so by subtracting the returned value to compensate for the
change handle_options() makes to the new_argv.
But handle_options() did not correctly count when "-c <config=value>" is
given, causing a wrong pointer to be passed to realloc().
Fix it by saving the original argv at the beginning of handle_options(),
and return the difference between the final value of argv, which will
relieve the places that move the array pointer from the additional burden
of keeping track of "handled" counter.
Noticed-by: Kazuki Tsujimoto
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Jeff King <peff@peff.net>
---
git.c | 6 ++----
t/t1300-repo-config.sh | 2 +-
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/git.c b/git.c
index a5ef3c6..89721d4 100644
--- a/git.c
+++ b/git.c
@@ -66,7 +66,7 @@ static void commit_pager_choice(void) {
static int handle_options(const char ***argv, int *argc, int *envchanged)
{
- int handled = 0;
+ const char **orig_argv = *argv;
while (*argc > 0) {
const char *cmd = (*argv)[0];
@@ -122,7 +122,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
*envchanged = 1;
(*argv)++;
(*argc)--;
- handled++;
} else if (!prefixcmp(cmd, "--git-dir=")) {
setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
if (envchanged)
@@ -162,9 +161,8 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
(*argv)++;
(*argc)--;
- handled++;
}
- return handled;
+ return (*argv) - orig_argv;
}
static int handle_alias(int *argcp, const char ***argv)
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index fe7a153..3db5626 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -897,7 +897,7 @@ test_expect_success 'key sanity-checking' '
git config foo."ba =z".bar false
'
-test_expect_failure 'git -c works with aliases of builtins' '
+test_expect_success 'git -c works with aliases of builtins' '
git config alias.checkconfig "-c foo.check=bar config foo.check" &&
echo bar >expect &&
git checkconfig >actual &&
--
1.7.4.5.7.g2e01
^ permalink raw reply related [flat|nested] 10+ messages in thread
end of thread, other threads:[~2011-05-24 22:50 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-24 21:15 [PATCH] handle_options(): do not miscount how many arguments were used Junio C Hamano
2011-05-24 21:18 ` [PATCH] Allow built-ins to also use -c var=val via alias Junio C Hamano
2011-05-24 21:46 ` Jeff King
2011-05-24 21:52 ` Jeff King
2011-05-24 21:57 ` Jeff King
2011-05-24 22:49 ` Jeff King
2011-05-24 22:49 ` [PATCH 1/4] config: make environment parsing routines static Jeff King
2011-05-24 22:49 ` [PATCH 2/4] git_config: don't peek at global config_parameters Jeff King
2011-05-24 22:49 ` [PATCH 3/4] config: always parse GIT_CONFIG_PARAMETERS during git_config Jeff King
2011-05-24 22:50 ` [PATCH 4/4] handle_options(): do not miscount how many arguments were used Jeff King
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).