All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dennis Kaarsemaker <dennis@kaarsemaker.net>
To: Jeff King <peff@peff.net>
Cc: doak <doak@gmx.de>, "git@vger.kernel.org" <git@vger.kernel.org>
Subject: Re: bug: 'core.logallrefupdates' is not set by default in non-bare repository
Date: Fri, 02 Sep 2016 11:01:54 +0200	[thread overview]
Message-ID: <1472806914.4680.50.camel@kaarsemaker.net> (raw)
In-Reply-To: <20160902080416.jmrctu3onfmylmeq@sigill.intra.peff.net>

On vr, 2016-09-02 at 04:04 -0400, Jeff King wrote:
> On Wed, Aug 31, 2016 at 05:32:33PM +0200, Dennis Kaarsemaker wrote:
> 
> > 
> > > 
> > > We may need to do something like turn off the
> > > need_shared_repository_from_config in init-db, since I think it would
> > > not want to ever read from the default config sources in most of its
> > > code-paths (OTOH, it should in theory respect core.sharedRepository
> > > in ~/.gitconfig, so maybe there is another more elegant way of
> > > handling this).
> > I would go even further and say that git init should completely ignore
> > the config of a repository you happen to be in when creating a new
> > repository.
> Hmm. I'd think we would already be avoiding that, because we shouldn't
> be calling setup_git_directory(). But some of the lazy-loaded setup is a
> bit overzealous, and we blindly look at ".git/config". If we try the
> same operation from a subdir of an existing repo, we _don't_ end up
> confused. Eek.

Yikes. Didnt' dig that deep, but that sounds wrong :)

> So I actually wonder if that is the root of the bug. In your patch, you
> disable config reading when we chdir to the new repo:
> 
> > 
> > diff --git a/builtin/init-db.c b/builtin/init-db.c
> > index 3a45f0b..d0fd3dc 100644
> > --- a/builtin/init-db.c
> > +++ b/builtin/init-db.c
> > @@ -493,6 +493,12 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
> >  		int mkdir_tried = 0;
> >  	retry:
> >  		if (chdir(argv[0]) < 0) {
> > +			/*
> > +			 * We're creating a new repository. If we're already in another
> > +			 * repository, ignore its config
> > +			 */
> > +			ignore_repo_config = 1;
> > +			git_config_clear();
> But I think we should go further and avoid ever looking at the original
> repository in the first place. I.e., I would say that "git init" should
> never ever behave differently if run in an existing repo versus outside
> of one.

Well, 'git init' is a valid operation to run inside an existing repo to
reinitialize some bits, so we definitely need to not ignore the config
once we're sure we're not creating a new repo.

> So really we ought to be setting ignore_repo_config from the very start
> of cmd_init(), and then re-enabling it once we are "inside" the new
> repo.  The git_config_clear() should in theory come once we are
> "inside", as well; we may have cached system/global config, and
> need to flush so we read them anew along with the new local config.

That's why I git_config_clear() twice.

> OTOH, since there shouldn't be anything interesting in the new
> repo-level config, I'm not sure that's really necessary. The rest of
> "init" can probably proceed without caring.

Except when running 'git init' to re-init existing repo.

> I also wonder if there are other things besides config which might
> accidentally read from .git (because they call git_pathdup(), and it
> just blindly looks in ".git" if nobody called setup_git_directory()). So
> it would be nice to have some flag for "do not ever lazy-call
> setup_git_env; we do not care about any repository".  But I think that's
> ahrd; functions like git_pathdup() are always expected to return _some_
> value, so what would they say? The best we could do is return
> "/does-not-exist/" or something, but that is awfully hacky.
> 
> > 
> > @@ -500,7 +506,6 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
> >  				 * and we know shared_repository should always be 0;
> >  				 * but just in case we play safe.
> >  				 */
> > -				saved = get_shared_repository();
> >  				set_shared_repository(0);
> >  				switch (safe_create_leading_directories_const(argv[0])) {
> >  				case SCLD_OK:
> I don't know if anybody cares about being able to set core.sharedRepository
> from ~/.gitconfig. It didn't work until v2.9.0 anyway (when I moved it
> out of the repository-format check), but it seems like you _should_ be
> able to set it and have it Just Work.
> 
> And in that case, this "we know shared_repository should always be 0" is
> not true, and we would want to keep doing the save/set-to-0/restore
> dance here.

We don't need to save if we throw away the cache below.

> > @@ -524,6 +528,11 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
> >  	} else if (0 < argc) {
> >  		usage(init_db_usage[0]);
> >  	}
> > +
> > +	need_shared_repository_from_config = 1;
> > +	ignore_repo_config = 0;
> > +	git_config_clear();
> This is the part I think we could actually skip. The only thing we might
> not have loaded is the "config" we just wrote to the new repository. But
> I don't think we have to care about what is in it.

We do, because this is also called for existing repos.

> > diff --git a/config.c b/config.c
> > index 0dfed68..2df0189 100644
> > --- a/config.c
> > +++ b/config.c
> > @@ -1304,7 +1304,7 @@ static int do_git_config_sequence(config_fn_t fn, void *data)
> >  		ret += git_config_from_file(fn, user_config, data);
> >  
> >  	current_parsing_scope = CONFIG_SCOPE_REPO;
> > -	if (repo_config && !access_or_die(repo_config, R_OK, 0))
> > +	if (repo_config && !ignore_repo_config && !access_or_die(repo_config, R_OK, 0))
> >  		ret += git_config_from_file(fn, repo_config, data);
> We probably want to intercept the call to git_pathdup() earlier than
> this, if the point is not to touch any of the lazy-load setup_git_dir()
> stuff at all. The effect is the same for config, but I think it makes
> sense to have as little effect as possible.

Thought about doing that, but didn't know what side-effects that would
have.

> So here's the minimal fix that seems to work for me:
> 
> diff --git a/builtin/init-db.c b/builtin/init-db.c
> index 3a45f0b..56e7b9a 100644
> --- a/builtin/init-db.c
> +++ b/builtin/init-db.c
> @@ -484,6 +484,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
>  		OPT_END()
>  	};
>  
> +	ignore_repo_config = 1;
> +
>  	argc = parse_options(argc, argv, prefix, init_db_options, init_db_usage, 0);
>  
>  	if (real_git_dir && !is_absolute_path(real_git_dir))
> diff --git a/cache.h b/cache.h
> index b780a91..13b78e4 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -1582,6 +1582,13 @@ enum config_origin_type {
>  	CONFIG_ORIGIN_CMDLINE
>  };
>  
> +/*
> + * If non-zero, git_config() will avoid any attempt to find the repo config;
> + * this is useful for programs like git-init that might look at config before
> + * actually setting up the new repository.
> + */
> +extern int ignore_repo_config;
> +
>  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 *);
> diff --git a/config.c b/config.c
> index 0dfed68..c9fc62e 100644
> --- a/config.c
> +++ b/config.c
> @@ -14,6 +14,8 @@
>  #include "string-list.h"
>  #include "utf8.h"
>  
> +int ignore_repo_config;
> +
>  struct config_source {
>  	struct config_source *prev;
>  	union {
> @@ -1289,7 +1291,7 @@ static int do_git_config_sequence(config_fn_t fn, void *data)
>  	int ret = 0;
>  	char *xdg_config = xdg_config_home("config");
>  	char *user_config = expand_user_path("~/.gitconfig");
> -	char *repo_config = git_pathdup("config");
> +	char *repo_config = ignore_repo_config ? NULL : git_pathdup("config");;
>  
>  	current_parsing_scope = CONFIG_SCOPE_SYSTEM;
>  	if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0))
> diff --git a/t/t0001-init.sh b/t/t0001-init.sh
> index a6fdd5e..8efddaa 100755
> --- a/t/t0001-init.sh
> +++ b/t/t0001-init.sh
> @@ -384,4 +384,13 @@ test_expect_success MINGW 'bare git dir not hidden' '
>  	! is_hidden newdir
>  '
>  
> +test_expect_success 'init from existing directory does not confuse config' '
> +	rm -rf newdir &&
> +	test_config core.logallrefupdates true &&
> +	git init newdir &&
> +	echo true >expect &&
> +	git -C newdir config --bool core.logallrefupdates >actual &&
> +	test_cmp expect actual
> +'
> +
>  test_done
> 
> 

  parent reply	other threads:[~2016-09-02  9:02 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-08-31  8:09 bug: 'core.logallrefupdates' is not set by default in non-bare repository doak
2016-08-31  9:12 ` Dennis Kaarsemaker
2016-08-31 10:48   ` Jeff King
2016-08-31 15:32     ` Dennis Kaarsemaker
2016-09-02  8:04       ` Jeff King
2016-09-02  8:47         ` Jeff King
2016-09-02  9:01         ` Dennis Kaarsemaker [this message]
2016-09-02  9:11           ` Jeff King

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=1472806914.4680.50.camel@kaarsemaker.net \
    --to=dennis@kaarsemaker.net \
    --cc=doak@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=peff@peff.net \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.