From e850194c83985396435b01b70d2db00b6d3af02e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 10 Dec 2015 16:33:05 -0500 Subject: ident: make xgetpwuid_self() a static local helper This function is defined in wrapper.c, but nobody besides ident.c uses it. And nobody is likely to in the future, either, as anything that cares about the user's name should be going through the ident code. Moving it here is a cleanup of the global namespace, but it will also enable further cleanups inside ident.c. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/git-compat-util.h b/git-compat-util.h index 4fe10cc..0feeae2 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -923,9 +923,6 @@ int access_or_die(const char *path, int mode, unsigned flag); /* Warn on an inaccessible file that ought to be accessible */ void warn_on_inaccessible(const char *path); -/* Get the passwd entry for the UID of the current process. */ -struct passwd *xgetpwuid_self(void); - #ifdef GMTIME_UNRELIABLE_ERRORS struct tm *git_gmtime(const time_t *); struct tm *git_gmtime_r(const time_t *, struct tm *); diff --git a/ident.c b/ident.c index 5ff1aad..d7c70e2 100644 --- a/ident.c +++ b/ident.c @@ -23,6 +23,18 @@ static int author_ident_explicitly_given; #define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos) #endif +static struct passwd *xgetpwuid_self(void) +{ + struct passwd *pw; + + errno = 0; + pw = getpwuid(getuid()); + if (!pw) + die(_("unable to look up current user in the passwd file: %s"), + errno ? strerror(errno) : _("no such user")); + return pw; +} + static void copy_gecos(const struct passwd *w, struct strbuf *name) { char *src; diff --git a/wrapper.c b/wrapper.c index 0e22d43..dae5675 100644 --- a/wrapper.c +++ b/wrapper.c @@ -601,18 +601,6 @@ int access_or_die(const char *path, int mode, unsigned flag) return ret; } -struct passwd *xgetpwuid_self(void) -{ - struct passwd *pw; - - errno = 0; - pw = getpwuid(getuid()); - if (!pw) - die(_("unable to look up current user in the passwd file: %s"), - errno ? strerror(errno) : _("no such user")); - return pw; -} - char *xgetcwd(void) { struct strbuf sb = STRBUF_INIT; -- cgit v0.10.2-6-g49f6 From 19ce497cf594a3c01af33a65b27b19e7459212d6 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 10 Dec 2015 16:35:36 -0500 Subject: ident: keep a flag for bogus default_email If we have to deduce the user's email address and can't come up with something plausible for the hostname, we simply write "(none)" or ".(none)" in the hostname. Later, our strict-check is forced to use strstr to look for this magic string. This is probably not a problem in practice, but it's rather ugly. Let's keep an extra flag that tells us the email is bogus, and check that instead. We could get away with simply setting the global in add_domainname(); it only gets called to write into git_default_email. However, let's make the code a little more obvious to future readers by actually passing a pointer to our "bogus" flag down the call-chain. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/ident.c b/ident.c index d7c70e2..085cfbe 100644 --- a/ident.c +++ b/ident.c @@ -10,6 +10,7 @@ static struct strbuf git_default_name = STRBUF_INIT; static struct strbuf git_default_email = STRBUF_INIT; static struct strbuf git_default_date = STRBUF_INIT; +static int default_email_is_bogus; #define IDENT_NAME_GIVEN 01 #define IDENT_MAIL_GIVEN 02 @@ -82,7 +83,7 @@ static int add_mailname_host(struct strbuf *buf) return 0; } -static void add_domainname(struct strbuf *out) +static void add_domainname(struct strbuf *out, int *is_bogus) { char buf[1024]; struct hostent *he; @@ -90,17 +91,21 @@ static void add_domainname(struct strbuf *out) if (gethostname(buf, sizeof(buf))) { warning("cannot get host name: %s", strerror(errno)); strbuf_addstr(out, "(none)"); + *is_bogus = 1; return; } if (strchr(buf, '.')) strbuf_addstr(out, buf); else if ((he = gethostbyname(buf)) && strchr(he->h_name, '.')) strbuf_addstr(out, he->h_name); - else + else { strbuf_addf(out, "%s.(none)", buf); + *is_bogus = 1; + } } -static void copy_email(const struct passwd *pw, struct strbuf *email) +static void copy_email(const struct passwd *pw, struct strbuf *email, + int *is_bogus) { /* * Make up a fake email address @@ -111,7 +116,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email) if (!add_mailname_host(email)) return; /* read from "/etc/mailname" (Debian) */ - add_domainname(email); + add_domainname(email, is_bogus); } const char *ident_default_name(void) @@ -133,7 +138,8 @@ const char *ident_default_email(void) committer_ident_explicitly_given |= IDENT_MAIL_GIVEN; author_ident_explicitly_given |= IDENT_MAIL_GIVEN; } else - copy_email(xgetpwuid_self(), &git_default_email); + copy_email(xgetpwuid_self(), &git_default_email, + &default_email_is_bogus); strbuf_trim(&git_default_email); } return git_default_email.buf; @@ -325,8 +331,7 @@ const char *fmt_ident(const char *name, const char *email, name = pw->pw_name; } - if (strict && email == git_default_email.buf && - strstr(email, "(none)")) { + if (strict && email == git_default_email.buf && default_email_is_bogus) { fputs(env_hint, stderr); die("unable to auto-detect email address (got '%s')", email); } -- cgit v0.10.2-6-g49f6 From 92bcbb9b338dd27f0fd4245525093c4bce867f3d Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 10 Dec 2015 16:41:29 -0500 Subject: ident: loosen getpwuid error in non-strict mode If the user has not specified an identity and we have to turn to getpwuid() to find the username or gecos field, we die immediately when getpwuid fails (e.g., because the user does not exist). This is OK for making a commit, where we have set IDENT_STRICT and would want to bail on bogus input. But for something like a reflog, where the ident is "best effort", it can be pain. For instance, even running "git clone" with a UID that is not in /etc/passwd will result in git barfing, just because we can't find an ident to put in the reflog. Instead of dying in xgetpwuid_self, we can instead return a fallback value, and set a "bogus" flag. For the username in an email, we already have a "default_email_is_bogus" flag. For the name field, we introduce (and check) a matching "default_name_is_bogus" flag. As a bonus, this means you now get the usual "tell me who you are" advice instead of just a "no such user" error. No tests, as this is dependent on configuration outside of git's control. However, I did confirm that it behaves sensibly when I delete myself from the local /etc/passwd (reflogs get written, and commits complain). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano diff --git a/ident.c b/ident.c index 085cfbe..bb1b174 100644 --- a/ident.c +++ b/ident.c @@ -11,6 +11,7 @@ static struct strbuf git_default_name = STRBUF_INIT; static struct strbuf git_default_email = STRBUF_INIT; static struct strbuf git_default_date = STRBUF_INIT; static int default_email_is_bogus; +static int default_name_is_bogus; #define IDENT_NAME_GIVEN 01 #define IDENT_MAIL_GIVEN 02 @@ -24,15 +25,22 @@ static int author_ident_explicitly_given; #define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos) #endif -static struct passwd *xgetpwuid_self(void) +static struct passwd *xgetpwuid_self(int *is_bogus) { struct passwd *pw; errno = 0; pw = getpwuid(getuid()); - if (!pw) - die(_("unable to look up current user in the passwd file: %s"), - errno ? strerror(errno) : _("no such user")); + if (!pw) { + static struct passwd fallback; + fallback.pw_name = "unknown"; +#ifndef NO_GECOS_IN_PWENT + fallback.pw_gecos = "Unknown"; +#endif + pw = &fallback; + if (is_bogus) + *is_bogus = 1; + } return pw; } @@ -122,7 +130,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email, const char *ident_default_name(void) { if (!git_default_name.len) { - copy_gecos(xgetpwuid_self(), &git_default_name); + copy_gecos(xgetpwuid_self(&default_name_is_bogus), &git_default_name); strbuf_trim(&git_default_name); } return git_default_name.buf; @@ -138,8 +146,8 @@ const char *ident_default_email(void) committer_ident_explicitly_given |= IDENT_MAIL_GIVEN; author_ident_explicitly_given |= IDENT_MAIL_GIVEN; } else - copy_email(xgetpwuid_self(), &git_default_email, - &default_email_is_bogus); + copy_email(xgetpwuid_self(&default_email_is_bogus), + &git_default_email, &default_email_is_bogus); strbuf_trim(&git_default_email); } return git_default_email.buf; @@ -327,10 +335,16 @@ const char *fmt_ident(const char *name, const char *email, fputs(env_hint, stderr); die("empty ident name (for <%s>) not allowed", email); } - pw = xgetpwuid_self(); + pw = xgetpwuid_self(NULL); name = pw->pw_name; } + if (want_name && strict && + name == git_default_name.buf && default_name_is_bogus) { + fputs(env_hint, stderr); + die("unable to auto-detect name (got '%s')", name); + } + if (strict && email == git_default_email.buf && default_email_is_bogus) { fputs(env_hint, stderr); die("unable to auto-detect email address (got '%s')", email); -- cgit v0.10.2-6-g49f6