ident: report passwd errors with a more friendly message

When getpwuid fails, we give a cute but cryptic message. While it makes sense if you know that getpwuid or identity functions are being called, this code is triggered behind the scenes by quite a few git commands these days (e.g., receive-pack on a remote server might use it for a reflog; the current message is hard to distinguish from an authentication error). Let's switch to something that gives a little more context. While we're at it, we can factor out all of the cut-and-pastes of the "you don't exist" message into a wrapper function. Rather than provide xgetpwuid, let's make it even more specific to just getting the passwd entry for the current uid. That's the only way we use getpwuid anyway, and it lets us make an even more specific error message. The current message also fails to mention errno. While the usual cause for getpwuid failing is that the user does not exist, mentioning errno makes it easier to diagnose these problems. Note that POSIX specifies that errno remain untouched if the passwd entry does not exist (but will be set on actual errors), whereas some systems will return ENOENT or similar for a missing entry. We handle both cases in our wrapper. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed May 21, 2012 at 19:10 UTC 2f70587502b6b5a8cfda5a3eff54392f48e2db8d
5 files changed +20 -25
Documentation/git-commit-tree.txt
-5
@@ -88,11 +88,6 @@ for one to be entered and terminated with ^D.
88
89 include::date-formats.txt[]
90
91 -Diagnostics
92 ------------
93 -You don't exist. Go away!::
94 - The passwd(5) gecos field couldn't be read
95 -
91 Discussion
92 ----------
93
Documentation/git-var.txt
-5
@@ -59,11 +59,6 @@ ifdef::git-default-pager[]
59 The build you are using chose '{git-default-pager}' as the default.
60 endif::git-default-pager[]
61
62 -Diagnostics
63 ------------
64 -You don't exist. Go away!::
65 - The passwd(5) gecos field couldn't be read
66 -
62 SEE ALSO
63 --------
64 linkgit:git-commit-tree[1]
git-compat-util.h
+3
@@ -595,4 +595,7 @@ int rmdir_or_warn(const char *path);
595 */
596 int remove_or_warn(unsigned int mode, const char *path);
597
598 +/* Get the passwd entry for the UID of the current process. */
599 +struct passwd *xgetpwuid_self(void);
600 +
601 #endif
ident.c
+5 -15
@@ -100,12 +100,8 @@ static void copy_email(const struct passwd *pw, struct strbuf *email)
100
101 const char *ident_default_name(void)
102 {
103 - if (!git_default_name.len) {
104 - struct passwd *pw = getpwuid(getuid());
105 - if (!pw)
106 - die("You don't exist. Go away!");
107 - copy_gecos(pw, &git_default_name);
108 - }
103 + if (!git_default_name.len)
104 + copy_gecos(xgetpwuid_self(), &git_default_name);
105 return git_default_name.buf;
106 }
107
@@ -117,12 +113,8 @@ const char *ident_default_email(void)
113 if (email && email[0]) {
114 strbuf_addstr(&git_default_email, email);
115 user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
120 - } else {
121 - struct passwd *pw = getpwuid(getuid());
122 - if (!pw)
123 - die("You don't exist. Go away!");
124 - copy_email(pw, &git_default_email);
125 - }
116 + } else
117 + copy_email(xgetpwuid_self(), &git_default_email);
118 }
119 return git_default_email.buf;
120 }
@@ -303,9 +295,7 @@ const char *fmt_ident(const char *name, const char *email,
295 fputs(env_hint, stderr);
296 die("empty ident %s <%s> not allowed", name, email);
297 }
306 - pw = getpwuid(getuid());
307 - if (!pw)
308 - die("You don't exist. Go away!");
298 + pw = xgetpwuid_self();
299 name = pw->pw_name;
300 }
301
wrapper.c
+12
@@ -402,3 +402,15 @@ int remove_or_warn(unsigned int mode, const char *file)
402 {
403 return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
404 }
405 +
406 +struct passwd *xgetpwuid_self(void)
407 +{
408 + struct passwd *pw;
409 +
410 + errno = 0;
411 + pw = getpwuid(getuid());
412 + if (!pw)
413 + die(_("unable to look up current user in the passwd file: %s"),
414 + errno ? strerror(errno) : _("no such user"));
415 + return pw;
416 +}