ident: add user.useConfigOnly boolean for when ident shouldn't be guessed

It used to be that: git config --global user.email "(none)" was a viable way for people to force themselves to set user.email in each repository. This was helpful for people with more than one email address, targeting different email addresses for different clones, as it barred git from creating a commit unless the user.email config was set in the per-repo config to the correct email address. A recent change, 19ce497c (ident: keep a flag for bogus default_email, 2015-12-10), however, declared that an explicitly configured user.email is not bogus, no matter what its value is, so this hack no longer works. Provide the same functionality by adding a new configuration variable user.useConfigOnly; when this variable is set, the user must explicitly set user.email configuration. Signed-off-by: Junio C Hamano <gitster@pobox.com> Helped-by: Eric Sunshine <sunshine@sunshineco.com> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Dan Aloni <alonid@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Dan Aloni committed Feb 6, 2016 at 08:23 UTC 4d5c2956969a6690db2bbb2f3ff40459c09d7646
3 files changed +65
Documentation/config.txt
+10
@@ -2775,6 +2775,16 @@ user.name::
2775 Can be overridden by the 'GIT_AUTHOR_NAME' and 'GIT_COMMITTER_NAME'
2776 environment variables. See linkgit:git-commit-tree[1].
2777
2778 +user.useConfigOnly::
2779 + Instruct Git to avoid trying to guess defaults for 'user.email'
2780 + and 'user.name', and instead retrieve the values only from the
2781 + configuration. For example, if you have multiple email addresses
2782 + and would like to use a different one for each repository, then
2783 + with this configuration option set to `true` in the global config
2784 + along with a name, Git will prompt you to set up an email before
2785 + making new commits in a newly cloned repository.
2786 + Defaults to `false`.
2787 +
2788 user.signingKey::
2789 If linkgit:git-tag[1] or linkgit:git-commit[1] is not selecting the
2790 key you want it to automatically when creating a signed tag or
ident.c
+16
@@ -13,11 +13,14 @@ static struct strbuf git_default_date = STRBUF_INIT;
13 static int default_email_is_bogus;
14 static int default_name_is_bogus;
15
16 +static int ident_use_config_only;
17 +
18 #define IDENT_NAME_GIVEN 01
19 #define IDENT_MAIL_GIVEN 02
20 #define IDENT_ALL_GIVEN (IDENT_NAME_GIVEN|IDENT_MAIL_GIVEN)
21 static int committer_ident_explicitly_given;
22 static int author_ident_explicitly_given;
23 +static int ident_config_given;
24
25 #ifdef NO_GECOS_IN_PWENT
26 #define get_gecos(ignored) "&"
@@ -354,6 +357,9 @@ const char *fmt_ident(const char *name, const char *email,
357 fputs(env_hint, stderr);
358 die("unable to auto-detect name (got '%s')", name);
359 }
360 + if (strict && ident_use_config_only
361 + && !(ident_config_given & IDENT_NAME_GIVEN))
362 + die("user.useConfigOnly set but no name given");
363 }
364 if (!*name) {
365 struct passwd *pw;
@@ -373,6 +379,9 @@ const char *fmt_ident(const char *name, const char *email,
379 fputs(env_hint, stderr);
380 die("unable to auto-detect email address (got '%s')", email);
381 }
382 + if (strict && ident_use_config_only
383 + && !(ident_config_given & IDENT_MAIL_GIVEN))
384 + die("user.useConfigOnly set but no mail given");
385 }
386
387 strbuf_reset(&ident);
@@ -446,6 +455,11 @@ int author_ident_sufficiently_given(void)
455
456 int git_ident_config(const char *var, const char *value, void *data)
457 {
458 + if (!strcmp(var, "user.useconfigonly")) {
459 + ident_use_config_only = git_config_bool(var, value);
460 + return 0;
461 + }
462 +
463 if (!strcmp(var, "user.name")) {
464 if (!value)
465 return config_error_nonbool(var);
@@ -453,6 +467,7 @@ int git_ident_config(const char *var, const char *value, void *data)
467 strbuf_addstr(&git_default_name, value);
468 committer_ident_explicitly_given |= IDENT_NAME_GIVEN;
469 author_ident_explicitly_given |= IDENT_NAME_GIVEN;
470 + ident_config_given |= IDENT_NAME_GIVEN;
471 return 0;
472 }
473
@@ -463,6 +478,7 @@ int git_ident_config(const char *var, const char *value, void *data)
478 strbuf_addstr(&git_default_email, value);
479 committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
480 author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
481 + ident_config_given |= IDENT_MAIL_GIVEN;
482 return 0;
483 }
484
t/t7517-per-repo-email.sh new
+39
@@ -0,0 +1,39 @@
1 +#!/bin/sh
2 +#
3 +# Copyright (c) 2016 Dan Aloni
4 +# Copyright (c) 2016 Jeff King
5 +#
6 +
7 +test_description='per-repo forced setting of email address'
8 +
9 +. ./test-lib.sh
10 +
11 +test_expect_success 'setup a likely user.useConfigOnly use case' '
12 + # we want to make sure a reflog is written, since that needs
13 + # a non-strict ident. So be sure we have an actual commit.
14 + test_commit foo &&
15 +
16 + sane_unset GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL &&
17 + sane_unset GIT_COMMITTER_NAME GIT_COMMITTER_EMAIL &&
18 + git config user.name "test" &&
19 + git config --global user.useConfigOnly true
20 +'
21 +
22 +test_expect_success 'fails committing if clone email is not set' '
23 + test_must_fail git commit --allow-empty -m msg
24 +'
25 +
26 +test_expect_success 'fails committing if clone email is not set, but EMAIL set' '
27 + test_must_fail env EMAIL=test@fail.com git commit --allow-empty -m msg
28 +'
29 +
30 +test_expect_success 'succeeds committing if clone email is set' '
31 + test_config user.email "test@ok.com" &&
32 + git commit --allow-empty -m msg
33 +'
34 +
35 +test_expect_success 'succeeds cloning if global email is not set' '
36 + git clone . clone
37 +'
38 +
39 +test_done