{"thread":{"id":"40924","subject":"git-clone fails when current user is not in /etc/passwd","startedAt":"2015-12-02T20:10:42Z","lastAt":"2015-12-14T15:07:29Z","messageCount":20,"participants":["Taylor Braun-Jones","Duy Nguyen","Jeff King","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"273935","messageId":"CAKfKJYsyHn7FUOu65AqbvjZD-wAyRScjqUL6kgGDCVzG1myZTQ@mail.gmail.com","threadId":"40924","inReplyTo":null,"subject":"git-clone fails when current user is not in /etc/passwd","fromName":"Taylor Braun-Jones","fromEmail":"taylor@braun-jones.org","sentAt":"2015-12-02T20:10:42Z","receivedAt":"2015-12-02T20:10:42Z","isPatch":false,"sender":{"key":"taylor@braun-jones.org","avatar":"https://gravatar.com/avatar/91c2af014ddf9c0cb1aa6401f22d7b210d1be6df84e17997031e4994570dcdf9?d=mp&s=160"},"body":"My use case it running git clone inside a docker container with\n`docker run --user $(id -u):$(id -g) --volume /foo:/foo ...`. I want\nall /foo/* file creation/access from inside the Docker container to be\ndone as the current uid/gid of the host system.\n\nSteps to reproduce:\n\nmkdir /tmp/docker-git\ncat > /tmp/docker-git/Dockerfile <<EOF\nFROM ubuntu\nRUN apt-get update && apt-get install -y git-core\nEOF\ndocker build -t git /tmp/docker-git/\ndocker run --user $(id -u):$(id -g) git git clone\nhttps://github.com/git/git.git /tmp/git\n# fatal: unable to look up current user in the passwd file: no such user\necho $? # 128\n\nMy current workaround is:\n\ncat >> /tmp/docker-git/Dockerfile <<EOF\nRUN git config --system user.name Docker && git config --system\nuser.email docker@localhost\nEOF\n\nBut I don't see why this should be necessary just to clone a repo. I\nrun complex build jobs inside a docker container using this approach\nand git-clone is the first command to fail due to the lack of a passwd\nfile entry for the current user. Some complain to stderr, but still\nsucceed.\n\nRegards,\nTaylor\n"},{"id":"274207","messageId":"CAKfKJYu1frw5QLkkkZo-F1kxbkLREpyudFiCST6h7hSS=LPdmw@mail.gmail.com","threadId":"40924","inReplyTo":"CAKfKJYsyHn7FUOu65AqbvjZD-wAyRScjqUL6kgGDCVzG1myZTQ@mail.gmail.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Taylor Braun-Jones","fromEmail":"taylor@braun-jones.org","sentAt":"2015-12-09T15:23:17Z","receivedAt":"2015-12-09T15:23:17Z","isPatch":false,"sender":{"key":"taylor@braun-jones.org","avatar":"https://gravatar.com/avatar/91c2af014ddf9c0cb1aa6401f22d7b210d1be6df84e17997031e4994570dcdf9?d=mp&s=160"},"body":"What's the feeling on this one? If there's agreement in principle that\ngit-clone should not fail when the current UID cannot be found in\n/etc/passwd then I'm happy to submit a patch to fix it.\n\nThanks,\nTaylor\n\nOn Wed, Dec 2, 2015 at 3:10 PM, Taylor Braun-Jones\n<taylor@braun-jones.org> wrote:\n> My use case it running git clone inside a docker container with\n> `docker run --user $(id -u):$(id -g) --volume /foo:/foo ...`. I want\n> all /foo/* file creation/access from inside the Docker container to be\n> done as the current uid/gid of the host system.\n>\n> Steps to reproduce:\n>\n> mkdir /tmp/docker-git\n> cat > /tmp/docker-git/Dockerfile <<EOF\n> FROM ubuntu\n> RUN apt-get update && apt-get install -y git-core\n> EOF\n> docker build -t git /tmp/docker-git/\n> docker run --user $(id -u):$(id -g) git git clone\n> https://github.com/git/git.git /tmp/git\n> # fatal: unable to look up current user in the passwd file: no such user\n> echo $? # 128\n>\n> My current workaround is:\n>\n> cat >> /tmp/docker-git/Dockerfile <<EOF\n> RUN git config --system user.name Docker && git config --system\n> user.email docker@localhost\n> EOF\n>\n> But I don't see why this should be necessary just to clone a repo. I\n> run complex build jobs inside a docker container using this approach\n> and git-clone is the first command to fail due to the lack of a passwd\n> file entry for the current user. Some complain to stderr, but still\n> succeed.\n>\n> Regards,\n> Taylor\n"},{"id":"274208","messageId":"CACsJy8AQFSvcxKqSdWfvGArV60RA96WcvvofpfJ4EuG+q_=t0Q@mail.gmail.com","threadId":"40924","inReplyTo":"CAKfKJYsyHn7FUOu65AqbvjZD-wAyRScjqUL6kgGDCVzG1myZTQ@mail.gmail.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2015-12-09T16:08:27Z","receivedAt":"2015-12-09T16:08:27Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Dec 2, 2015 at 9:10 PM, Taylor Braun-Jones\n<taylor@braun-jones.org> wrote:\n> My use case it running git clone inside a docker container with\n> `docker run --user $(id -u):$(id -g) --volume /foo:/foo ...`. I want\n> all /foo/* file creation/access from inside the Docker container to be\n> done as the current uid/gid of the host system.\n>\n> Steps to reproduce:\n>\n> mkdir /tmp/docker-git\n> cat > /tmp/docker-git/Dockerfile <<EOF\n> FROM ubuntu\n> RUN apt-get update && apt-get install -y git-core\n> EOF\n> docker build -t git /tmp/docker-git/\n> docker run --user $(id -u):$(id -g) git git clone\n> https://github.com/git/git.git /tmp/git\n> # fatal: unable to look up current user in the passwd file: no such user\n\nIt probably helps if you could get the stack trace to this message\n(printed from function xgetpwuid_self). I haven't checked if my\npersonal laptop has docker to reproduce this.. In general we won't ask\npasswd if the user specifies name/email in the config file. But I\nstill don't see why git-clone needs that info in the first place.\n-- \nDuy\n"},{"id":"274211","messageId":"CACsJy8Dc3Lsqa2zccoqH7UkDitqDbOTX3EXsUCcN9OHY=LfaKw@mail.gmail.com","threadId":"40924","inReplyTo":"CACsJy8AQFSvcxKqSdWfvGArV60RA96WcvvofpfJ4EuG+q_=t0Q@mail.gmail.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2015-12-09T18:24:13Z","receivedAt":"2015-12-09T18:24:13Z","isPatch":false,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Dec 9, 2015 at 5:08 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> On Wed, Dec 2, 2015 at 9:10 PM, Taylor Braun-Jones\n> <taylor@braun-jones.org> wrote:\n>> My use case it running git clone inside a docker container with\n>> `docker run --user $(id -u):$(id -g) --volume /foo:/foo ...`. I want\n>> all /foo/* file creation/access from inside the Docker container to be\n>> done as the current uid/gid of the host system.\n>>\n>> Steps to reproduce:\n>>\n>> mkdir /tmp/docker-git\n>> cat > /tmp/docker-git/Dockerfile <<EOF\n>> FROM ubuntu\n>> RUN apt-get update && apt-get install -y git-core\n>> EOF\n>> docker build -t git /tmp/docker-git/\n>> docker run --user $(id -u):$(id -g) git git clone\n>> https://github.com/git/git.git /tmp/git\n>> # fatal: unable to look up current user in the passwd file: no such user\n>\n> It probably helps if you could get the stack trace to this message\n> (printed from function xgetpwuid_self). I haven't checked if my\n> personal laptop has docker to reproduce this.. In general we won't ask\n> passwd if the user specifies name/email in the config file. But I\n> still don't see why git-clone needs that info in the first place.\n\nWell.. reflog needs it. So either you disable reflog at clone time or\ndefine name/email via config file. I don't see anything wrong with\nthis behavior. Stack trace\n\n(gdb) bt\n#0  0x0000000000585aaf in xgetpwuid_self () at wrapper.c:608\n#1  0x00000000004ef2c4 in ident_default_name () at ident.c:108\n#2  0x00000000004ef851 in fmt_ident (name=0x0, email=0x0,\ndate_str=0x0, flag=0) at ident.c:300\n#3  0x00000000004efb25 in git_committer_info (flag=0) at ident.c:366\n#4  0x000000000052fc6f in log_ref_write_1 (refname=0x16236c0\n\"refs/remotes/origin/HEAD\", old_sha1=0x7ffc91e44190 \"\",\nnew_sha1=0x7ffc91e44170\n\"\\355\\025\\033\\215p{o\\177V\\234qX\\212j?!v|}D\\177\", msg=0x1620e50 \"clone:\nfrom https://github.com/rswier/c4.git\", logfile=0x7ffc91e44100,\nflags=0, err=0x7ffc91e44150) at refs.c:3403\n#5  0x000000000052fd85 in log_ref_write (refname=0x16236c0\n\"refs/remotes/origin/HEAD\", old_sha1=0x7ffc91e44190 \"\",\nnew_sha1=0x7ffc91e44170\n\"\\355\\025\\033\\215p{o\\177V\\234qX\\212j?!v|}D\\177\", msg=0x1620e50 \"clone:\nfrom https://github.com/rswier/c4.git\", flags=0, err=0x7ffc91e44150)\nat refs.c:3424\n#6  0x00000000005304af in create_symref (ref_target=0x16236c0\n\"refs/remotes/origin/HEAD\", refs_heads_master=0x1624cc0\n\"refs/remotes/origin/master\", logmsg=0x1620e50 \"clone: from\nhttps://github.com/rswier/c4.git\") at refs.c:3592\n#7  0x000000000042e50c in update_remote_refs (refs=0x1622d40,\nmapped_refs=0x1622cc0, remote_head_points_at=0x1624bc0,\nbranch_top=0x1621ca0 \"refs/remotes/origin/\", msg=0x1620e50 \"clone:\nfrom https://github.com/rswier/c4.git\", transport=0x1622960,\ncheck_connectivity=1) at builtin/clone.c:639\n#8  0x000000000042f80c in cmd_clone (argc=2, argv=0x7ffc91e44ab8,\nprefix=0x0) at builtin/clone.c:1066\n#9  0x0000000000405fda in run_builtin (p=0x825948 <commands+456>,\nargc=5, argv=0x7ffc91e44ab8) at git.c:352\n#10 0x00000000004061d0 in handle_builtin (argc=5, argv=0x7ffc91e44ab8)\nat git.c:542\n#11 0x00000000004062ec in run_argv (argcp=0x7ffc91e4498c,\nargv=0x7ffc91e449a0) at git.c:588\n#12 0x00000000004064df in main (argc=5, av=0x7ffc91e44aa8) at git.c:695\n-- \nDuy\n"},{"id":"274219","messageId":"CAKfKJYuP1E5aC7SPO91j-KS-P41pYaM7NkTJ9uG6b=VvxbOBwg@mail.gmail.com","threadId":"40924","inReplyTo":"CACsJy8Dc3Lsqa2zccoqH7UkDitqDbOTX3EXsUCcN9OHY=LfaKw@mail.gmail.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Taylor Braun-Jones","fromEmail":"taylor@braun-jones.org","sentAt":"2015-12-09T22:35:52Z","receivedAt":"2015-12-09T22:35:52Z","isPatch":false,"sender":{"key":"taylor@braun-jones.org","avatar":"https://gravatar.com/avatar/91c2af014ddf9c0cb1aa6401f22d7b210d1be6df84e17997031e4994570dcdf9?d=mp&s=160"},"body":"On Wed, Dec 9, 2015 at 1:24 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> On Wed, Dec 9, 2015 at 5:08 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n>> On Wed, Dec 2, 2015 at 9:10 PM, Taylor Braun-Jones\n>> <taylor@braun-jones.org> wrote:\n>>> My use case it running git clone inside a docker container with\n>>> `docker run --user $(id -u):$(id -g) --volume /foo:/foo ...`. I want\n>>> all /foo/* file creation/access from inside the Docker container to be\n>>> done as the current uid/gid of the host system.\n>>>\n>>> Steps to reproduce:\n>>>\n>>> mkdir /tmp/docker-git\n>>> cat > /tmp/docker-git/Dockerfile <<EOF\n>>> FROM ubuntu\n>>> RUN apt-get update && apt-get install -y git-core\n>>> EOF\n>>> docker build -t git /tmp/docker-git/\n>>> docker run --user $(id -u):$(id -g) git git clone\n>>> https://github.com/git/git.git /tmp/git\n>>> # fatal: unable to look up current user in the passwd file: no such user\n>>\n>> It probably helps if you could get the stack trace to this message\n>> (printed from function xgetpwuid_self). I haven't checked if my\n>> personal laptop has docker to reproduce this.. In general we won't ask\n>> passwd if the user specifies name/email in the config file. But I\n>> still don't see why git-clone needs that info in the first place.\n>\n> Well.. reflog needs it. So either you disable reflog at clone time or\n> define name/email via config file. I don't see anything wrong with\n> this behavior.\n\nCan't git just use \"unknown\" and \"unknown@localhost\" if the name or\nemail can not be determined from xgetpwuid? This seems to be the way\nthat Mercurial behaves.\n"},{"id":"274234","messageId":"CAKfKJYtuY7kYV9zNysCFpJ2CwVy=Eo-yJk=eYYooOAy1eZLxJA@mail.gmail.com","threadId":"40924","inReplyTo":"CAKfKJYuP1E5aC7SPO91j-KS-P41pYaM7NkTJ9uG6b=VvxbOBwg@mail.gmail.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Taylor Braun-Jones","fromEmail":"taylor@braun-jones.org","sentAt":"2015-12-10T18:33:26Z","receivedAt":"2015-12-10T18:33:26Z","isPatch":false,"sender":{"key":"taylor@braun-jones.org","avatar":"https://gravatar.com/avatar/91c2af014ddf9c0cb1aa6401f22d7b210d1be6df84e17997031e4994570dcdf9?d=mp&s=160"},"body":"On Wed, Dec 9, 2015 at 5:35 PM, Taylor Braun-Jones\n<taylor@braun-jones.org> wrote:\n>\n> On Wed, Dec 9, 2015 at 1:24 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> > On Wed, Dec 9, 2015 at 5:08 PM, Duy Nguyen <pclouds@gmail.com> wrote:\n> >> On Wed, Dec 2, 2015 at 9:10 PM, Taylor Braun-Jones\n> >> <taylor@braun-jones.org> wrote:\n> >>> My use case it running git clone inside a docker container with\n> >>> `docker run --user $(id -u):$(id -g) --volume /foo:/foo ...`. I want\n> >>> all /foo/* file creation/access from inside the Docker container to be\n> >>> done as the current uid/gid of the host system.\n> >>>\n> >>> Steps to reproduce:\n> >>>\n> >>> mkdir /tmp/docker-git\n> >>> cat > /tmp/docker-git/Dockerfile <<EOF\n> >>> FROM ubuntu\n> >>> RUN apt-get update && apt-get install -y git-core\n> >>> EOF\n> >>> docker build -t git /tmp/docker-git/\n> >>> docker run --user $(id -u):$(id -g) git git clone\n> >>> https://github.com/git/git.git /tmp/git\n> >>> # fatal: unable to look up current user in the passwd file: no such user\n> >>\n> >> It probably helps if you could get the stack trace to this message\n> >> (printed from function xgetpwuid_self). I haven't checked if my\n> >> personal laptop has docker to reproduce this.. In general we won't ask\n> >> passwd if the user specifies name/email in the config file. But I\n> >> still don't see why git-clone needs that info in the first place.\n> >\n> > Well.. reflog needs it. So either you disable reflog at clone time or\n> > define name/email via config file. I don't see anything wrong with\n> > this behavior.\n>\n> Can't git just use \"unknown\" and \"unknown@localhost\" if the name or\n> email can not be determined from xgetpwuid? This seems to be the way\n> that Mercurial behaves.\n\nSee attached patch for an implementation of the fallback-to-unknown\nidea. With this, I'm able to clone a repository under a UID that does\nnot exist in /etc/passwd and do everything that I'd expect to do with\na local git repository. Is there something that I've missed?\n\nTaylor\n\n\nFrom dd5c2ccf5df4104e677f8488fbb4be98ff1831c7 Mon Sep 17 00:00:00 2001\nFrom: Taylor Braun-Jones <taylor@braun-jones.org>\nDate: Thu, 10 Dec 2015 13:21:25 -0500\nSubject: [PATCH] Warn (not die) when unable to look up current user in the\n passwd file\n\n---\n wrapper.c | 22 ++++++++++++++++++----\n 1 file changed, 18 insertions(+), 4 deletions(-)\n\ndiff --git a/wrapper.c b/wrapper.c\nindex 6fcaa4d..8119068 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -604,12 +604,26 @@ int access_or_die(const char *path, int mode, unsigned flag)\n struct passwd *xgetpwuid_self(void)\n {\n \tstruct passwd *pw;\n+\tstatic struct passwd pw_unknown = {0};\n \n+\tuid_t uid = getuid();\n \terrno = 0;\n-\tpw = getpwuid(getuid());\n-\tif (!pw)\n-\t\tdie(_(\"unable to look up current user in the passwd file: %s\"),\n-\t\t    errno ? strerror(errno) : _(\"no such user\"));\n+\tpw = getpwuid(uid);\n+\tif (!pw) {\n+\t\twarning(_(\"unable to look up current user in the passwd file: %s\"),\n+\t\t        errno ? strerror(errno) : _(\"no such user\"));\n+\t\tpw_unknown.pw_name = \"unknown\";\n+\t\tpw_unknown.pw_passwd = NULL;\n+\t\tpw_unknown.pw_uid = uid;\n+\t\tpw_unknown.pw_gid = getgid();\n+\t\tpw_unknown.pw_dir = NULL;\n+\t\tpw_unknown.pw_shell = NULL;\n+ #ifndef NO_GECOS_IN_PWENT\n+\t\tpw_unknown.pw_gecos = NULL;\n+ #endif\n+\t\tpw = &pw_unknown;\n+\t}\n+\n \treturn pw;\n }\n \n-- \n2.6.3\n\n"},{"id":"274235","messageId":"20151210183426.GA27609@sigill.intra.peff.net","threadId":"40924","inReplyTo":"CAKfKJYuP1E5aC7SPO91j-KS-P41pYaM7NkTJ9uG6b=VvxbOBwg@mail.gmail.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-10T18:34:26Z","receivedAt":"2015-12-10T18:34:26Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Dec 09, 2015 at 05:35:52PM -0500, Taylor Braun-Jones wrote:\n\n> > Well.. reflog needs it. So either you disable reflog at clone time or\n> > define name/email via config file. I don't see anything wrong with\n> > this behavior.\n> \n> Can't git just use \"unknown\" and \"unknown@localhost\" if the name or\n> email can not be determined from xgetpwuid? This seems to be the way\n> that Mercurial behaves.\n\nYeah, I think there is a mismatch here in the ident code. When we are\nmaking a commit (which is likely to get published and is set in stone),\nwe ask for \"IDENT_STRICT\", which will barf if we can't come up with\nsomething sensible. For reflogs, we are OK putting whatever\nauto-generated crap in there we can come up with.\n\nBut before we even hit the strict-check, we call xgetpwuid_self(), which\nunconditionally dies on failure. I think that function needs to be\ntaught a \"gently\" form which we use for non-strict ident lookups.\nUnfortunately it's a little non-trivial because the strictness will need\nto get passed all the way down to ident_default_name() (and we need to\nmake sure that a non-strict check followed by a strict one does not\nfail; i.e., that the first does not pollute the contents of\ngit_default_name).\n\n-Peff\n"},{"id":"274237","messageId":"xmqqoadyi1q2.fsf@gitster.mtv.corp.google.com","threadId":"40924","inReplyTo":"CACsJy8Dc3Lsqa2zccoqH7UkDitqDbOTX3EXsUCcN9OHY=LfaKw@mail.gmail.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-12-10T18:43:17Z","receivedAt":"2015-12-10T18:43:17Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Duy Nguyen <pclouds@gmail.com> writes:\n\n> Well.. reflog needs it. So either you disable reflog at clone time or\n> define name/email via config file. I don't see anything wrong with\n> this behavior.\n\nHmm, I am not quite sure about that.\n\nIn the codepath that computes ident_default_email(), which is one\nhalf of what the \"reflog\" code you cite wants to do, copy_email()\ncalls copy_email() which in turn calls add_domainname().  If your\ngetpwuid() gave you some username, but your gethostname() gave you a\nNULL, we do not barf but add \"(none)\" as and then issue a warning.\n\nPerhaps we can do the same by returning a structure with members set\nto a set of fake values.  Because we already have checks in places\nthat really matter to the recorded history (read: not reflog) in the\nform of *_ident_sufficiently_given() functions, potential damage due\nto having phoney names returned from here would not be too bad.\n\nTotally untested...\n\n ident.c   | 13 ++++++++++---\n wrapper.c |  4 ----\n 2 files changed, 10 insertions(+), 7 deletions(-)\n\ndiff --git a/ident.c b/ident.c\nindex 4e7f99d..2ccae2c 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -31,7 +31,7 @@ static void copy_gecos(const struct passwd *w, struct strbuf *name)\n \t * with commas.  Also & stands for capitalized form of the login name.\n \t */\n \n-\tfor (src = get_gecos(w); *src && *src != ','; src++) {\n+\tfor (src = w ? get_gecos(w) : \"&\"; *src && *src != ','; src++) {\n \t\tint ch = *src;\n \t\tif (ch != '&')\n \t\t\tstrbuf_addch(name, ch);\n@@ -117,7 +117,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email)\n \t * Make up a fake email address\n \t * (name + '@' + hostname [+ '.' + domainname])\n \t */\n-\tstrbuf_addstr(email, pw->pw_name);\n+\tstrbuf_addstr(email, pw ? pw->pw_name : \"unknown\");\n \tstrbuf_addch(email, '@');\n \n \tif (!add_mailname_host(email))\n@@ -332,8 +332,15 @@ const char *fmt_ident(const char *name, const char *email,\n \t\t\t\tfputs(env_hint, stderr);\n \t\t\tdie(\"empty ident name (for <%s>) not allowed\", email);\n \t\t}\n+\t\terrno = 0;\n \t\tpw = xgetpwuid_self();\n-\t\tname = pw->pw_name;\n+\t\tif (!pw) {\n+\t\t\twarning(_(\"unable to look up current user: %s\"),\n+\t\t\t\terrno ? strerror(errno) : _(\"no such user\"));\n+\t\t\tname = \"unknown\";\n+\t\t} else {\n+\t\t\tname = pw->pw_name;\n+\t\t}\n \t}\n \n \tif (strict && email == git_default_email.buf &&\ndiff --git a/wrapper.c b/wrapper.c\nindex 6fcaa4d..16ab45f 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -605,11 +605,7 @@ struct passwd *xgetpwuid_self(void)\n {\n \tstruct passwd *pw;\n \n-\terrno = 0;\n \tpw = getpwuid(getuid());\n-\tif (!pw)\n-\t\tdie(_(\"unable to look up current user in the passwd file: %s\"),\n-\t\t    errno ? strerror(errno) : _(\"no such user\"));\n \treturn pw;\n }\n \n"},{"id":"274239","messageId":"CAKfKJYt__uD_=E=NBxsVSbv6TO4E7-GvsCdFnSuPPv8n-owhJA@mail.gmail.com","threadId":"40924","inReplyTo":"xmqqoadyi1q2.fsf@gitster.mtv.corp.google.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Taylor Braun-Jones","fromEmail":"taylor@braun-jones.org","sentAt":"2015-12-10T18:52:30Z","receivedAt":"2015-12-10T18:52:30Z","isPatch":false,"sender":{"key":"taylor@braun-jones.org","avatar":"https://gravatar.com/avatar/91c2af014ddf9c0cb1aa6401f22d7b210d1be6df84e17997031e4994570dcdf9?d=mp&s=160"},"body":"On Thu, Dec 10, 2015 at 1:43 PM, Junio C Hamano <gitster@pobox.com> wrote:\n> Duy Nguyen <pclouds@gmail.com> writes:\n>\n>> Well.. reflog needs it. So either you disable reflog at clone time or\n>> define name/email via config file. I don't see anything wrong with\n>> this behavior.\n>\n> Hmm, I am not quite sure about that.\n>\n> In the codepath that computes ident_default_email(), which is one\n> half of what the \"reflog\" code you cite wants to do, copy_email()\n> calls copy_email() which in turn calls add_domainname().  If your\n> getpwuid() gave you some username, but your gethostname() gave you a\n> NULL, we do not barf but add \"(none)\" as and then issue a warning.\n>\n> Perhaps we can do the same by returning a structure with members set\n> to a set of fake values.  Because we already have checks in places\n> that really matter to the recorded history (read: not reflog) in the\n> form of *_ident_sufficiently_given() functions, potential damage due\n> to having phoney names returned from here would not be too bad.\n>\n> Totally untested...\n>\n>  ident.c   | 13 ++++++++++---\n>  wrapper.c |  4 ----\n>  2 files changed, 10 insertions(+), 7 deletions(-)\n>\n> diff --git a/ident.c b/ident.c\n> index 4e7f99d..2ccae2c 100644\n> --- a/ident.c\n> +++ b/ident.c\n> @@ -31,7 +31,7 @@ static void copy_gecos(const struct passwd *w, struct strbuf *name)\n>          * with commas.  Also & stands for capitalized form of the login name.\n>          */\n>\n> -       for (src = get_gecos(w); *src && *src != ','; src++) {\n> +       for (src = w ? get_gecos(w) : \"&\"; *src && *src != ','; src++) {\n>                 int ch = *src;\n>                 if (ch != '&')\n>                         strbuf_addch(name, ch);\n> @@ -117,7 +117,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email)\n>          * Make up a fake email address\n>          * (name + '@' + hostname [+ '.' + domainname])\n>          */\n> -       strbuf_addstr(email, pw->pw_name);\n> +       strbuf_addstr(email, pw ? pw->pw_name : \"unknown\");\n>         strbuf_addch(email, '@');\n>\n>         if (!add_mailname_host(email))\n> @@ -332,8 +332,15 @@ const char *fmt_ident(const char *name, const char *email,\n>                                 fputs(env_hint, stderr);\n>                         die(\"empty ident name (for <%s>) not allowed\", email);\n>                 }\n> +               errno = 0;\n>                 pw = xgetpwuid_self();\n> -               name = pw->pw_name;\n> +               if (!pw) {\n> +                       warning(_(\"unable to look up current user: %s\"),\n> +                               errno ? strerror(errno) : _(\"no such user\"));\n> +                       name = \"unknown\";\n> +               } else {\n> +                       name = pw->pw_name;\n> +               }\n>         }\n>\n>         if (strict && email == git_default_email.buf &&\n> diff --git a/wrapper.c b/wrapper.c\n> index 6fcaa4d..16ab45f 100644\n> --- a/wrapper.c\n> +++ b/wrapper.c\n> @@ -605,11 +605,7 @@ struct passwd *xgetpwuid_self(void)\n>  {\n>         struct passwd *pw;\n>\n> -       errno = 0;\n>         pw = getpwuid(getuid());\n> -       if (!pw)\n> -               die(_(\"unable to look up current user in the passwd file: %s\"),\n> -                   errno ? strerror(errno) : _(\"no such user\"));\n>         return pw;\n>  }\n>\n\nYes, this looks better.\n\n+1\n"},{"id":"274244","messageId":"xmqqtwnqgjpm.fsf@gitster.mtv.corp.google.com","threadId":"40924","inReplyTo":"20151210183426.GA27609@sigill.intra.peff.net","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-12-10T19:57:41Z","receivedAt":"2015-12-10T19:57:41Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> But before we even hit the strict-check, we call xgetpwuid_self(), which\n> unconditionally dies on failure. I think that function needs to be\n> taught a \"gently\" form which we use for non-strict ident lookups.\n> Unfortunately it's a little non-trivial because the strictness will need\n> to get passed all the way down to ident_default_name() (and we need to\n> make sure that a non-strict check followed by a strict one does not\n> fail; i.e., that the first does not pollute the contents of\n> git_default_name).\n\nAll true.  The adding of \"(none)\" in add_domainname() I used as an\nexcuse to make the function stop barfing is a symptom coming from\nthe above.  That one should die when asked to do a strict thing\n(there is a corresponding kludge to do strstr \"(none)\" to cover it\nup, which is even uglier X-<).\n"},{"id":"274245","messageId":"20151210204034.GA29055@sigill.intra.peff.net","threadId":"40924","inReplyTo":"xmqqtwnqgjpm.fsf@gitster.mtv.corp.google.com","subject":"Re: git-clone fails when current user is not in /etc/passwd","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-10T20:40:35Z","receivedAt":"2015-12-10T20:40:35Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Dec 10, 2015 at 11:57:41AM -0800, Junio C Hamano wrote:\n\n> Jeff King <peff@peff.net> writes:\n> \n> > But before we even hit the strict-check, we call xgetpwuid_self(), which\n> > unconditionally dies on failure. I think that function needs to be\n> > taught a \"gently\" form which we use for non-strict ident lookups.\n> > Unfortunately it's a little non-trivial because the strictness will need\n> > to get passed all the way down to ident_default_name() (and we need to\n> > make sure that a non-strict check followed by a strict one does not\n> > fail; i.e., that the first does not pollute the contents of\n> > git_default_name).\n> \n> All true.  The adding of \"(none)\" in add_domainname() I used as an\n> excuse to make the function stop barfing is a symptom coming from\n> the above.  That one should die when asked to do a strict thing\n> (there is a corresponding kludge to do strstr \"(none)\" to cover it\n> up, which is even uglier X-<).\n\nYes, I have always hated that. It seems like we should just be able to\ncarry a \"strict\" flag (both from xgetpwuid() and from the \"(none)\" hack)\nalong with ident_default_*, and barf at the right time if it is not set.\n\n-Peff\n"},{"id":"274246","messageId":"20151210213228.GB29055@sigill.intra.peff.net","threadId":"40924","inReplyTo":"20151210204034.GA29055@sigill.intra.peff.net","subject":"[PATCH 0/3] git-clone fails when current user is not in /etc/passwd","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-10T21:32:28Z","receivedAt":"2015-12-10T21:32:28Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Dec 10, 2015 at 03:40:35PM -0500, Jeff King wrote:\n\n> > All true.  The adding of \"(none)\" in add_domainname() I used as an\n> > excuse to make the function stop barfing is a symptom coming from\n> > the above.  That one should die when asked to do a strict thing\n> > (there is a corresponding kludge to do strstr \"(none)\" to cover it\n> > up, which is even uglier X-<).\n> \n> Yes, I have always hated that. It seems like we should just be able to\n> carry a \"strict\" flag (both from xgetpwuid() and from the \"(none)\" hack)\n> along with ident_default_*, and barf at the right time if it is not set.\n\nI don't think we want to pass down a \"be strict\" flag to the low-level\ncode filling in default_{name,email}. We might be strict in one call,\nand non-strict in another within the same program. Worse, we actually\ncall ident_default_name() even when we don't actually want the name (we\ncould fix that, too, but it just adds more cases to the code).\n\nSo here's my solution, which instead carries the \"is it bogus\" flag\nalong with the default strings.\n\n  [1/3]: ident: make xgetpwuid_self() a static local helper\n  [2/3]: ident: keep a flag for bogus default_email\n  [3/3]: ident: loosen getpwuid error in non-strict mode\n\n-Peff\n"},{"id":"274247","messageId":"20151210213304.GA8374@sigill.intra.peff.net","threadId":"40924","inReplyTo":"20151210213228.GB29055@sigill.intra.peff.net","subject":"[PATCH 1/3] ident: make xgetpwuid_self() a static local helper","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-10T21:33:05Z","receivedAt":"2015-12-10T21:33:05Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"This function is defined in wrapper.c, but nobody besides\nident.c uses it. And nobody is likely to in the future,\neither, as anything that cares about the user's name should\nbe going through the ident code.\n\nMoving it here is a cleanup of the global namespace, but it\nwill also enable further cleanups inside ident.c.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n git-compat-util.h |  3 ---\n ident.c           | 12 ++++++++++++\n wrapper.c         | 12 ------------\n 3 files changed, 12 insertions(+), 15 deletions(-)\n\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 8e39867..2da0a75 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -929,9 +929,6 @@ int access_or_die(const char *path, int mode, unsigned flag);\n /* Warn on an inaccessible file that ought to be accessible */\n void warn_on_inaccessible(const char *path);\n \n-/* Get the passwd entry for the UID of the current process. */\n-struct passwd *xgetpwuid_self(void);\n-\n #ifdef GMTIME_UNRELIABLE_ERRORS\n struct tm *git_gmtime(const time_t *);\n struct tm *git_gmtime_r(const time_t *, struct tm *);\ndiff --git a/ident.c b/ident.c\nindex 5ff1aad..d7c70e2 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -23,6 +23,18 @@ static int author_ident_explicitly_given;\n #define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos)\n #endif\n \n+static struct passwd *xgetpwuid_self(void)\n+{\n+\tstruct passwd *pw;\n+\n+\terrno = 0;\n+\tpw = getpwuid(getuid());\n+\tif (!pw)\n+\t\tdie(_(\"unable to look up current user in the passwd file: %s\"),\n+\t\t    errno ? strerror(errno) : _(\"no such user\"));\n+\treturn pw;\n+}\n+\n static void copy_gecos(const struct passwd *w, struct strbuf *name)\n {\n \tchar *src;\ndiff --git a/wrapper.c b/wrapper.c\nindex 6fcaa4d..c95e290 100644\n--- a/wrapper.c\n+++ b/wrapper.c\n@@ -601,18 +601,6 @@ int access_or_die(const char *path, int mode, unsigned flag)\n \treturn ret;\n }\n \n-struct passwd *xgetpwuid_self(void)\n-{\n-\tstruct passwd *pw;\n-\n-\terrno = 0;\n-\tpw = getpwuid(getuid());\n-\tif (!pw)\n-\t\tdie(_(\"unable to look up current user in the passwd file: %s\"),\n-\t\t    errno ? strerror(errno) : _(\"no such user\"));\n-\treturn pw;\n-}\n-\n char *xgetcwd(void)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n-- \n2.6.3.636.g1460207\n"},{"id":"274248","messageId":"20151210213535.GB8374@sigill.intra.peff.net","threadId":"40924","inReplyTo":"20151210213228.GB29055@sigill.intra.peff.net","subject":"[PATCH 2/3] ident: keep a flag for bogus default_email","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-10T21:35:36Z","receivedAt":"2015-12-10T21:35:36Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"If we have to deduce the user's email address and can't come\nup with something plausible for the hostname, we simply\nwrite \"(none)\" or \".(none)\" in the hostname.\n\nLater, our strict-check is forced to use strstr to look for\nthis magic string. This is probably not a problem in\npractice, but it's rather ugly. Let's keep an extra flag\nthat tells us the email is bogus, and check that instead.\n\nWe could get away with simply setting the global in\nadd_domainname(); it only gets called to write into\ngit_default_email. However, let's make the code a little\nmore obvious to future readers by actually passing a pointer\nto our \"bogus\" flag down the call-chain.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nI waffled on the \"passing it around\" thing. The patch is a lot smaller\nif we just set the global directly, and I doubt these static helpers\nwill ever get reused for anything else. But the pattern does get reused\nin the next patch, which sets the \"email\" and \"name\" flags separately\ndepending on context.\n\nI was also tempted to have a single \"default_ident_is_flaky\", but that\ndoes get some corner cases wrong (e.g., you have a bogus auto-guessed\nname, an OK auto-guessed email, and set GIT_COMMITTER_NAME but not\nGIT_COMMITTER_EMAIL). I doubt those come up in practice, but it's not\nthat hard to do the right thing.\n\n ident.c | 19 ++++++++++++-------\n 1 file changed, 12 insertions(+), 7 deletions(-)\n\ndiff --git a/ident.c b/ident.c\nindex d7c70e2..085cfbe 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -10,6 +10,7 @@\n static struct strbuf git_default_name = STRBUF_INIT;\n static struct strbuf git_default_email = STRBUF_INIT;\n static struct strbuf git_default_date = STRBUF_INIT;\n+static int default_email_is_bogus;\n \n #define IDENT_NAME_GIVEN 01\n #define IDENT_MAIL_GIVEN 02\n@@ -82,7 +83,7 @@ static int add_mailname_host(struct strbuf *buf)\n \treturn 0;\n }\n \n-static void add_domainname(struct strbuf *out)\n+static void add_domainname(struct strbuf *out, int *is_bogus)\n {\n \tchar buf[1024];\n \tstruct hostent *he;\n@@ -90,17 +91,21 @@ static void add_domainname(struct strbuf *out)\n \tif (gethostname(buf, sizeof(buf))) {\n \t\twarning(\"cannot get host name: %s\", strerror(errno));\n \t\tstrbuf_addstr(out, \"(none)\");\n+\t\t*is_bogus = 1;\n \t\treturn;\n \t}\n \tif (strchr(buf, '.'))\n \t\tstrbuf_addstr(out, buf);\n \telse if ((he = gethostbyname(buf)) && strchr(he->h_name, '.'))\n \t\tstrbuf_addstr(out, he->h_name);\n-\telse\n+\telse {\n \t\tstrbuf_addf(out, \"%s.(none)\", buf);\n+\t\t*is_bogus = 1;\n+\t}\n }\n \n-static void copy_email(const struct passwd *pw, struct strbuf *email)\n+static void copy_email(const struct passwd *pw, struct strbuf *email,\n+\t\t       int *is_bogus)\n {\n \t/*\n \t * Make up a fake email address\n@@ -111,7 +116,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email)\n \n \tif (!add_mailname_host(email))\n \t\treturn;\t/* read from \"/etc/mailname\" (Debian) */\n-\tadd_domainname(email);\n+\tadd_domainname(email, is_bogus);\n }\n \n const char *ident_default_name(void)\n@@ -133,7 +138,8 @@ const char *ident_default_email(void)\n \t\t\tcommitter_ident_explicitly_given |= IDENT_MAIL_GIVEN;\n \t\t\tauthor_ident_explicitly_given |= IDENT_MAIL_GIVEN;\n \t\t} else\n-\t\t\tcopy_email(xgetpwuid_self(), &git_default_email);\n+\t\t\tcopy_email(xgetpwuid_self(), &git_default_email,\n+\t\t\t\t   &default_email_is_bogus);\n \t\tstrbuf_trim(&git_default_email);\n \t}\n \treturn git_default_email.buf;\n@@ -325,8 +331,7 @@ const char *fmt_ident(const char *name, const char *email,\n \t\tname = pw->pw_name;\n \t}\n \n-\tif (strict && email == git_default_email.buf &&\n-\t    strstr(email, \"(none)\")) {\n+\tif (strict && email == git_default_email.buf && default_email_is_bogus) {\n \t\tfputs(env_hint, stderr);\n \t\tdie(\"unable to auto-detect email address (got '%s')\", email);\n \t}\n-- \n2.6.3.636.g1460207\n"},{"id":"274249","messageId":"20151210214129.GC8374@sigill.intra.peff.net","threadId":"40924","inReplyTo":"20151210213228.GB29055@sigill.intra.peff.net","subject":"[PATCH 3/3] ident: loosen getpwuid error in non-strict mode","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-10T21:41:29Z","receivedAt":"2015-12-10T21:41:29Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"If the user has not specified an identity and we have to\nturn to getpwuid() to find the username or gecos field, we\ndie immediately when getpwuid fails (e.g., because the user\ndoes not exist). This is OK for making a commit, where we\nhave set IDENT_STRICT and would want to bail on bogus input.\n\nBut for something like a reflog, where the ident is \"best\neffort\", it can be pain. For instance, even running \"git\nclone\" with a UID that is not in /etc/passwd will result in\ngit barfing, just because we can't find an ident to put in\nthe reflog.\n\nInstead of dying in xgetpwuid_self, we can instead return a\nfallback value, and set a \"bogus\" flag. For the username in\nan email, we already have a \"default_email_is_bogus\" flag.\nFor the name field, we introduce (and check) a matching\n\"default_name_is_bogus\" flag. As a bonus, this means you now\nget the usual \"tell me who you are\" advice instead of just a\n\"no such user\" error.\n\nNo tests, as this is dependent on configuration outside of\ngit's control. However, I did confirm that it behaves\nsensibly when I delete myself from the local /etc/passwd\n(reflogs get written, and commits complain).\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\nI dislike #ifdefs in the middle of functions like the one below, but I\ncouldn't come up with an elegant way to avoid it. We're reusing \"struct\npasswd\" for our fallback, so we need to know whether we have that field\nto set or not.\n\nAn obvious alternative would be to always return our own\n\n  struct git_passwd_struct {\n\tconst char *name;\n\tconst char *gecos;\n  };\n\nand translate the existing getpwuid() on the fly. That still needs an\n#ifdef, but we could then get rid of the #ifdef for the get_gecos()\nmacro.\n\nYet another alternative is to simply zero the fallback passwd struct,\nand pw->pw_gecos will either not exist, or will be NULL. But then the\ncallers have to do something sane with the NULL, and the whole point of\nthis exercise was to avoid callers having to deal with the error cases\ndirectly, so...\n\n ident.c | 30 ++++++++++++++++++++++--------\n 1 file changed, 22 insertions(+), 8 deletions(-)\n\ndiff --git a/ident.c b/ident.c\nindex 085cfbe..2d5b876 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -11,6 +11,7 @@ static struct strbuf git_default_name = STRBUF_INIT;\n static struct strbuf git_default_email = STRBUF_INIT;\n static struct strbuf git_default_date = STRBUF_INIT;\n static int default_email_is_bogus;\n+static int default_name_is_bogus;\n \n #define IDENT_NAME_GIVEN 01\n #define IDENT_MAIL_GIVEN 02\n@@ -24,15 +25,22 @@ static int author_ident_explicitly_given;\n #define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos)\n #endif\n \n-static struct passwd *xgetpwuid_self(void)\n+static struct passwd *xgetpwuid_self(int *is_bogus)\n {\n \tstruct passwd *pw;\n \n \terrno = 0;\n \tpw = getpwuid(getuid());\n-\tif (!pw)\n-\t\tdie(_(\"unable to look up current user in the passwd file: %s\"),\n-\t\t    errno ? strerror(errno) : _(\"no such user\"));\n+\tif (!pw) {\n+\t\tstruct passwd fallback;\n+\t\tfallback.pw_name = \"unknown\";\n+#ifndef NO_GECOS_IN_PWENT\n+\t\tfallback.pw_gecos = \"Unknown\";\n+#endif\n+\t\tpw = &fallback;\n+\t\tif (is_bogus)\n+\t\t\t*is_bogus = 1;\n+\t}\n \treturn pw;\n }\n \n@@ -122,7 +130,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email,\n const char *ident_default_name(void)\n {\n \tif (!git_default_name.len) {\n-\t\tcopy_gecos(xgetpwuid_self(), &git_default_name);\n+\t\tcopy_gecos(xgetpwuid_self(&default_name_is_bogus), &git_default_name);\n \t\tstrbuf_trim(&git_default_name);\n \t}\n \treturn git_default_name.buf;\n@@ -138,8 +146,8 @@ const char *ident_default_email(void)\n \t\t\tcommitter_ident_explicitly_given |= IDENT_MAIL_GIVEN;\n \t\t\tauthor_ident_explicitly_given |= IDENT_MAIL_GIVEN;\n \t\t} else\n-\t\t\tcopy_email(xgetpwuid_self(), &git_default_email,\n-\t\t\t\t   &default_email_is_bogus);\n+\t\t\tcopy_email(xgetpwuid_self(&default_email_is_bogus),\n+\t\t\t\t   &git_default_email, &default_email_is_bogus);\n \t\tstrbuf_trim(&git_default_email);\n \t}\n \treturn git_default_email.buf;\n@@ -327,10 +335,16 @@ const char *fmt_ident(const char *name, const char *email,\n \t\t\t\tfputs(env_hint, stderr);\n \t\t\tdie(\"empty ident name (for <%s>) not allowed\", email);\n \t\t}\n-\t\tpw = xgetpwuid_self();\n+\t\tpw = xgetpwuid_self(NULL);\n \t\tname = pw->pw_name;\n \t}\n \n+\tif (want_name && strict &&\n+\t    name == git_default_name.buf && default_name_is_bogus) {\n+\t\tfputs(env_hint, stderr);\n+\t\tdie(\"unable to auto-detect name (got '%s')\", name);\n+\t}\n+\n \tif (strict && email == git_default_email.buf && default_email_is_bogus) {\n \t\tfputs(env_hint, stderr);\n \t\tdie(\"unable to auto-detect email address (got '%s')\", email);\n-- \n2.6.3.636.g1460207\n"},{"id":"274252","messageId":"20151210225416.GA1648@sigill.intra.peff.net","threadId":"40924","inReplyTo":"20151210213535.GB8374@sigill.intra.peff.net","subject":"Re: [PATCH 2/3] ident: keep a flag for bogus default_email","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-10T22:54:16Z","receivedAt":"2015-12-10T22:54:16Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Dec 10, 2015 at 04:35:35PM -0500, Jeff King wrote:\n\n> @@ -82,7 +83,7 @@ static int add_mailname_host(struct strbuf *buf)\n>  \treturn 0;\n>  }\n>  \n> -static void add_domainname(struct strbuf *out)\n> +static void add_domainname(struct strbuf *out, int *is_bogus)\n>  {\n>  \tchar buf[1024];\n>  \tstruct hostent *he;\n> @@ -90,17 +91,21 @@ static void add_domainname(struct strbuf *out)\n>  \tif (gethostname(buf, sizeof(buf))) {\n>  \t\twarning(\"cannot get host name: %s\", strerror(errno));\n>  \t\tstrbuf_addstr(out, \"(none)\");\n> +\t\t*is_bogus = 1;\n>  \t\treturn;\n>  \t}\n>  \tif (strchr(buf, '.'))\n>  \t\tstrbuf_addstr(out, buf);\n>  \telse if ((he = gethostbyname(buf)) && strchr(he->h_name, '.'))\n>  \t\tstrbuf_addstr(out, he->h_name);\n> -\telse\n> +\telse {\n>  \t\tstrbuf_addf(out, \"%s.(none)\", buf);\n> +\t\t*is_bogus = 1;\n> +\t}\n\nThis hunk has some minor conflicts with ep/ident-with-getaddrinfo, which\ngraduated to master in the tips you just pushed out.\n\nHere's a rebased version on top of the current master (the other patches\ncan remain the same).\n\n-- >8 --\nSubject: [PATCH] ident: keep a flag for bogus default_email\n\nIf we have to deduce the user's email address and can't come\nup with something plausible for the hostname, we simply\nwrite \"(none)\" or \".(none)\" in the hostname.\n\nLater, our strict-check is forced to use strstr to look for\nthis magic string. This is probably not a problem in\npractice, but it's rather ugly. Let's keep an extra flag\nthat tells us the email is bogus, and check that instead.\n\nWe could get away with simply setting the global in\nadd_domainname(); it only gets called to write into\ngit_default_email. However, let's make the code a little\nmore obvious to future readers by actually passing a pointer\nto our \"bogus\" flag down the call-chain.\n\nSigned-off-by: Jeff King <peff@peff.net>\n---\n ident.c | 19 ++++++++++++-------\n 1 file changed, 12 insertions(+), 7 deletions(-)\n\ndiff --git a/ident.c b/ident.c\nindex 140dd63..fde3244 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -10,6 +10,7 @@\n static struct strbuf git_default_name = STRBUF_INIT;\n static struct strbuf git_default_email = STRBUF_INIT;\n static struct strbuf git_default_date = STRBUF_INIT;\n+static int default_email_is_bogus;\n \n #define IDENT_NAME_GIVEN 01\n #define IDENT_MAIL_GIVEN 02\n@@ -108,22 +109,26 @@ static int canonical_name(const char *host, struct strbuf *out)\n \treturn status;\n }\n \n-static void add_domainname(struct strbuf *out)\n+static void add_domainname(struct strbuf *out, int *is_bogus)\n {\n \tchar buf[1024];\n \n \tif (gethostname(buf, sizeof(buf))) {\n \t\twarning(\"cannot get host name: %s\", strerror(errno));\n \t\tstrbuf_addstr(out, \"(none)\");\n+\t\t*is_bogus = 1;\n \t\treturn;\n \t}\n \tif (strchr(buf, '.'))\n \t\tstrbuf_addstr(out, buf);\n-\telse if (canonical_name(buf, out) < 0)\n+\telse if (canonical_name(buf, out) < 0) {\n \t\tstrbuf_addf(out, \"%s.(none)\", buf);\n+\t\t*is_bogus = 1;\n+\t}\n }\n \n-static void copy_email(const struct passwd *pw, struct strbuf *email)\n+static void copy_email(const struct passwd *pw, struct strbuf *email,\n+\t\t       int *is_bogus)\n {\n \t/*\n \t * Make up a fake email address\n@@ -134,7 +139,7 @@ static void copy_email(const struct passwd *pw, struct strbuf *email)\n \n \tif (!add_mailname_host(email))\n \t\treturn;\t/* read from \"/etc/mailname\" (Debian) */\n-\tadd_domainname(email);\n+\tadd_domainname(email, is_bogus);\n }\n \n const char *ident_default_name(void)\n@@ -156,7 +161,8 @@ const char *ident_default_email(void)\n \t\t\tcommitter_ident_explicitly_given |= IDENT_MAIL_GIVEN;\n \t\t\tauthor_ident_explicitly_given |= IDENT_MAIL_GIVEN;\n \t\t} else\n-\t\t\tcopy_email(xgetpwuid_self(), &git_default_email);\n+\t\t\tcopy_email(xgetpwuid_self(), &git_default_email,\n+\t\t\t\t   &default_email_is_bogus);\n \t\tstrbuf_trim(&git_default_email);\n \t}\n \treturn git_default_email.buf;\n@@ -348,8 +354,7 @@ const char *fmt_ident(const char *name, const char *email,\n \t\tname = pw->pw_name;\n \t}\n \n-\tif (strict && email == git_default_email.buf &&\n-\t    strstr(email, \"(none)\")) {\n+\tif (strict && email == git_default_email.buf && default_email_is_bogus) {\n \t\tfputs(env_hint, stderr);\n \t\tdie(\"unable to auto-detect email address (got '%s')\", email);\n \t}\n-- \n2.6.3.636.g1460207\n"},{"id":"274258","messageId":"xmqq4mfpho0n.fsf@gitster.mtv.corp.google.com","threadId":"40924","inReplyTo":"20151210213304.GA8374@sigill.intra.peff.net","subject":"Re: [PATCH 1/3] ident: make xgetpwuid_self() a static local helper","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-12-10T23:39:20Z","receivedAt":"2015-12-10T23:39:20Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Makes tons of sense (even without patches 2 and 3).  Thanks.\n"},{"id":"274260","messageId":"xmqqzixhg96v.fsf@gitster.mtv.corp.google.com","threadId":"40924","inReplyTo":"20151210213228.GB29055@sigill.intra.peff.net","subject":"Re: [PATCH 0/3] git-clone fails when current user is not in /etc/passwd","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2015-12-10T23:44:56Z","receivedAt":"2015-12-10T23:44:56Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> I don't think we want to pass down a \"be strict\" flag to the low-level\n> code filling in default_{name,email}. We might be strict in one call,\n> and non-strict in another within the same program. Worse, we actually\n> call ident_default_name() even when we don't actually want the name (we\n> could fix that, too, but it just adds more cases to the code).\n>\n> So here's my solution, which instead carries the \"is it bogus\" flag\n> along with the default strings.\n>\n>   [1/3]: ident: make xgetpwuid_self() a static local helper\n>   [2/3]: ident: keep a flag for bogus default_email\n>   [3/3]: ident: loosen getpwuid error in non-strict mode\n\nThanks.  Looks sensible.\n"},{"id":"274264","messageId":"CAKfKJYvXfW+hOFcC=TUybLhkVbRm9dznaTAiHCO+RM14nGPbDw@mail.gmail.com","threadId":"40924","inReplyTo":"20151210213228.GB29055@sigill.intra.peff.net","subject":"Re: [PATCH 0/3] git-clone fails when current user is not in /etc/passwd","fromName":"Taylor Braun-Jones","fromEmail":"taylor@braun-jones.org","sentAt":"2015-12-11T02:20:55Z","receivedAt":"2015-12-11T02:20:55Z","isPatch":true,"sender":{"key":"taylor@braun-jones.org","avatar":"https://gravatar.com/avatar/91c2af014ddf9c0cb1aa6401f22d7b210d1be6df84e17997031e4994570dcdf9?d=mp&s=160"},"body":"On Thu, Dec 10, 2015 at 4:32 PM, Jeff King <peff@peff.net> wrote:\n\n> So here's my solution, which instead carries the \"is it bogus\" flag\n> along with the default strings.\n>\n>   [1/3]: ident: make xgetpwuid_self() a static local helper\n>   [2/3]: ident: keep a flag for bogus default_email\n>   [3/3]: ident: loosen getpwuid error in non-strict mode\n\n1 definitely makes sense to me. As a newcomer to the git code base, I\nwas wondering why it wasn't this way already.\n\n2 and 3 solve my original problem - thanks!\n\nTaylor\n"},{"id":"274373","messageId":"20151214150729.GA21415@sigill.intra.peff.net","threadId":"40924","inReplyTo":"20151210214129.GC8374@sigill.intra.peff.net","subject":"Re: [PATCH 3/3] ident: loosen getpwuid error in non-strict mode","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2015-12-14T15:07:29Z","receivedAt":"2015-12-14T15:07:29Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Thu, Dec 10, 2015 at 04:41:29PM -0500, Jeff King wrote:\n\n> -static struct passwd *xgetpwuid_self(void)\n> +static struct passwd *xgetpwuid_self(int *is_bogus)\n>  {\n>  \tstruct passwd *pw;\n>  \n>  \terrno = 0;\n>  \tpw = getpwuid(getuid());\n> -\tif (!pw)\n> -\t\tdie(_(\"unable to look up current user in the passwd file: %s\"),\n> -\t\t    errno ? strerror(errno) : _(\"no such user\"));\n> +\tif (!pw) {\n> +\t\tstruct passwd fallback;\n> +\t\tfallback.pw_name = \"unknown\";\n> +#ifndef NO_GECOS_IN_PWENT\n> +\t\tfallback.pw_gecos = \"Unknown\";\n> +#endif\n> +\t\tpw = &fallback;\n> +\t\tif (is_bogus)\n> +\t\t\t*is_bogus = 1;\n> +\t}\n>  \treturn pw;\n\nUgh. The fallback struct should be static, of course, as we are\nreturning its address from the function.\n\nAnybody have a brown paper bag I can borrow?\n\ndiff --git a/ident.c b/ident.c\nindex 74de079..831072c 100644\n--- a/ident.c\n+++ b/ident.c\n@@ -32,7 +32,7 @@ static struct passwd *xgetpwuid_self(int *is_bogus)\n \terrno = 0;\n \tpw = getpwuid(getuid());\n \tif (!pw) {\n-\t\tstruct passwd fallback;\n+\t\tstatic struct passwd fallback;\n \t\tfallback.pw_name = \"unknown\";\n #ifndef NO_GECOS_IN_PWENT\n \t\tfallback.pw_gecos = \"Unknown\";\n\n-Peff\n"}]}