2005-07-13 02:49:27 +08:00
|
|
|
/*
|
|
|
|
* ident.c
|
|
|
|
*
|
|
|
|
* create git identifier lines of the form "name <email> date"
|
|
|
|
*
|
|
|
|
* Copyright (C) 2005 Linus Torvalds
|
|
|
|
*/
|
|
|
|
#include "cache.h"
|
|
|
|
|
2012-05-22 07:10:17 +08:00
|
|
|
static struct strbuf git_default_name = STRBUF_INIT;
|
|
|
|
static struct strbuf git_default_email = STRBUF_INIT;
|
2005-10-12 09:47:34 +08:00
|
|
|
static char git_default_date[50];
|
2012-05-22 07:09:57 +08:00
|
|
|
int user_ident_explicitly_given;
|
2005-07-13 02:49:27 +08:00
|
|
|
|
2011-05-19 19:37:55 +08:00
|
|
|
#ifdef NO_GECOS_IN_PWENT
|
|
|
|
#define get_gecos(ignored) "&"
|
|
|
|
#else
|
|
|
|
#define get_gecos(struct_passwd) ((struct_passwd)->pw_gecos)
|
|
|
|
#endif
|
|
|
|
|
2012-05-22 07:10:17 +08:00
|
|
|
static void copy_gecos(const struct passwd *w, struct strbuf *name)
|
2005-09-20 07:06:56 +08:00
|
|
|
{
|
2012-05-22 07:10:17 +08:00
|
|
|
char *src;
|
2005-09-20 07:06:56 +08:00
|
|
|
|
|
|
|
/* Traditionally GECOS field had office phone numbers etc, separated
|
|
|
|
* with commas. Also & stands for capitalized form of the login name.
|
|
|
|
*/
|
|
|
|
|
2012-05-22 07:10:17 +08:00
|
|
|
for (src = get_gecos(w); *src && *src != ','; src++) {
|
2005-09-20 07:06:56 +08:00
|
|
|
int ch = *src;
|
2012-05-22 07:10:17 +08:00
|
|
|
if (ch != '&')
|
|
|
|
strbuf_addch(name, ch);
|
|
|
|
else {
|
2005-09-20 07:06:56 +08:00
|
|
|
/* Sorry, Mr. McDonald... */
|
2012-05-22 07:10:17 +08:00
|
|
|
strbuf_addch(name, toupper(*w->pw_name));
|
|
|
|
strbuf_addstr(name, w->pw_name + 1);
|
2005-09-20 07:06:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-22 07:10:17 +08:00
|
|
|
static int add_mailname_host(struct strbuf *buf)
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
{
|
|
|
|
FILE *mailname;
|
|
|
|
|
|
|
|
mailname = fopen("/etc/mailname", "r");
|
|
|
|
if (!mailname) {
|
|
|
|
if (errno != ENOENT)
|
|
|
|
warning("cannot open /etc/mailname: %s",
|
|
|
|
strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
2012-05-22 07:10:17 +08:00
|
|
|
if (strbuf_getline(buf, mailname, '\n') == EOF) {
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
if (ferror(mailname))
|
|
|
|
warning("cannot read /etc/mailname: %s",
|
|
|
|
strerror(errno));
|
|
|
|
fclose(mailname);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* success! */
|
|
|
|
fclose(mailname);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-22 07:10:17 +08:00
|
|
|
static void add_domainname(struct strbuf *out)
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
{
|
2012-05-22 07:10:17 +08:00
|
|
|
char buf[1024];
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
struct hostent *he;
|
|
|
|
|
2012-05-22 07:10:17 +08:00
|
|
|
if (gethostname(buf, sizeof(buf))) {
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
warning("cannot get host name: %s", strerror(errno));
|
2012-05-22 07:10:17 +08:00
|
|
|
strbuf_addstr(out, "(none)");
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
return;
|
|
|
|
}
|
2012-05-22 07:10:17 +08:00
|
|
|
if (strchr(buf, '.'))
|
2012-05-22 07:10:23 +08:00
|
|
|
strbuf_addstr(out, buf);
|
|
|
|
else if ((he = gethostbyname(buf)) && strchr(he->h_name, '.'))
|
|
|
|
strbuf_addstr(out, he->h_name);
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
else
|
2012-05-22 07:10:23 +08:00
|
|
|
strbuf_addf(out, "%s.(none)", buf);
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
}
|
|
|
|
|
2012-05-22 07:10:17 +08:00
|
|
|
static void copy_email(const struct passwd *pw, struct strbuf *email)
|
2005-07-13 02:49:27 +08:00
|
|
|
{
|
2007-01-28 16:50:53 +08:00
|
|
|
/*
|
|
|
|
* Make up a fake email address
|
|
|
|
* (name + '@' + hostname [+ '.' + domainname])
|
|
|
|
*/
|
2012-05-22 07:10:17 +08:00
|
|
|
strbuf_addstr(email, pw->pw_name);
|
|
|
|
strbuf_addch(email, '@');
|
|
|
|
|
|
|
|
if (!add_mailname_host(email))
|
ident: check /etc/mailname if email is unknown
Before falling back to gethostname(), check /etc/mailname if
GIT_AUTHOR_EMAIL is not set in the environment or through config
files. Only fall back if /etc/mailname cannot be opened or read.
The /etc/mailname convention comes from Debian policy section 11.6
("mail transport, delivery and user agents"), though maybe it could be
useful sometimes on other machines, too. The lack of this support was
noticed by various people in different ways:
- Ian observed that git was choosing the address
'ian@anarres.relativity.greenend.org.uk' rather than
'ian@davenant.greenend.org.uk' as it should have done.
- Jonathan noticed that operations like "git commit" were needlessly
slow when using a resolver that was slow to handle reverse DNS
lookups.
Alas, after this patch, if /etc/mailname is set up and the [user] name
and email configuration aren't, the committer email will not provide a
charming reminder of which machine commits were made on any more. But
I think it's worth it.
Mechanics: the functionality of reading mailname goes in its own
function, so people who care about other distros can easily add an
implementation to a similar location without making copy_email() too
long and losing clarity. While at it, we split out the fallback
default logic that does gethostname(), too (rearranging it a little
and adding a check for errors from gethostname while at it).
Based on a patch by Gerrit Pape <pape@smarden.org>.
Requested-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
Improved-by: Junio C Hamano <gitster@pobox.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-03 14:16:33 +08:00
|
|
|
return; /* read from "/etc/mailname" (Debian) */
|
2012-05-22 07:10:17 +08:00
|
|
|
add_domainname(email);
|
2007-01-28 16:50:53 +08:00
|
|
|
}
|
|
|
|
|
2012-05-22 07:09:43 +08:00
|
|
|
const char *ident_default_name(void)
|
2007-01-28 16:50:53 +08:00
|
|
|
{
|
2012-05-22 07:10:29 +08:00
|
|
|
if (!git_default_name.len) {
|
2012-05-22 07:10:20 +08:00
|
|
|
copy_gecos(xgetpwuid_self(), &git_default_name);
|
2012-05-22 07:10:29 +08:00
|
|
|
strbuf_trim(&git_default_name);
|
|
|
|
}
|
2012-05-22 07:10:17 +08:00
|
|
|
return git_default_name.buf;
|
2012-05-22 07:09:43 +08:00
|
|
|
}
|
2007-01-28 16:50:53 +08:00
|
|
|
|
2012-05-22 07:09:43 +08:00
|
|
|
const char *ident_default_email(void)
|
|
|
|
{
|
2012-05-22 07:10:17 +08:00
|
|
|
if (!git_default_email.len) {
|
2007-07-06 08:29:41 +08:00
|
|
|
const char *email = getenv("EMAIL");
|
|
|
|
|
2010-01-09 00:01:10 +08:00
|
|
|
if (email && email[0]) {
|
2012-05-22 07:10:17 +08:00
|
|
|
strbuf_addstr(&git_default_email, email);
|
2010-01-09 00:01:10 +08:00
|
|
|
user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
2012-05-22 07:10:20 +08:00
|
|
|
} else
|
|
|
|
copy_email(xgetpwuid_self(), &git_default_email);
|
2012-05-22 07:10:29 +08:00
|
|
|
strbuf_trim(&git_default_email);
|
2007-01-28 16:50:53 +08:00
|
|
|
}
|
2012-05-22 07:10:17 +08:00
|
|
|
return git_default_email.buf;
|
2012-05-22 07:09:43 +08:00
|
|
|
}
|
2007-01-28 16:50:53 +08:00
|
|
|
|
2012-05-22 07:09:43 +08:00
|
|
|
const char *ident_default_date(void)
|
|
|
|
{
|
2007-01-28 16:50:53 +08:00
|
|
|
if (!git_default_date[0])
|
|
|
|
datestamp(git_default_date, sizeof(git_default_date));
|
2012-05-22 07:09:43 +08:00
|
|
|
return git_default_date;
|
2005-07-13 02:49:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int crud(unsigned char c)
|
|
|
|
{
|
2007-12-04 03:11:43 +08:00
|
|
|
return c <= 32 ||
|
|
|
|
c == '.' ||
|
|
|
|
c == ',' ||
|
|
|
|
c == ':' ||
|
|
|
|
c == ';' ||
|
|
|
|
c == '<' ||
|
|
|
|
c == '>' ||
|
|
|
|
c == '"' ||
|
2008-12-02 00:41:50 +08:00
|
|
|
c == '\\' ||
|
2007-12-04 03:11:43 +08:00
|
|
|
c == '\'';
|
2005-07-13 02:49:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy over a string to the destination, but avoid special
|
|
|
|
* characters ('\n', '<' and '>') and remove crud at the end
|
|
|
|
*/
|
2012-05-22 07:10:26 +08:00
|
|
|
static void strbuf_addstr_without_crud(struct strbuf *sb, const char *src)
|
2005-07-13 02:49:27 +08:00
|
|
|
{
|
2007-04-16 02:51:29 +08:00
|
|
|
size_t i, len;
|
2005-07-13 02:49:27 +08:00
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
/* Remove crud from the beginning.. */
|
|
|
|
while ((c = *src) != 0) {
|
|
|
|
if (!crud(c))
|
|
|
|
break;
|
|
|
|
src++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove crud from the end.. */
|
|
|
|
len = strlen(src);
|
|
|
|
while (len > 0) {
|
|
|
|
c = src[len-1];
|
|
|
|
if (!crud(c))
|
|
|
|
break;
|
|
|
|
--len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the rest to the buffer, but avoid the special
|
2005-12-29 17:30:08 +08:00
|
|
|
* characters '\n' '<' and '>' that act as delimiters on
|
2012-05-22 07:10:26 +08:00
|
|
|
* an identification line. We can only remove crud, never add it,
|
|
|
|
* so 'len' is our maximum.
|
2005-07-13 02:49:27 +08:00
|
|
|
*/
|
2012-05-22 07:10:26 +08:00
|
|
|
strbuf_grow(sb, len);
|
2005-07-13 02:49:27 +08:00
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
c = *src++;
|
|
|
|
switch (c) {
|
|
|
|
case '\n': case '<': case '>':
|
|
|
|
continue;
|
|
|
|
}
|
2012-05-22 07:10:26 +08:00
|
|
|
sb->buf[sb->len++] = c;
|
2005-07-13 02:49:27 +08:00
|
|
|
}
|
2012-05-22 07:10:26 +08:00
|
|
|
sb->buf[sb->len] = '\0';
|
2005-07-13 02:49:27 +08:00
|
|
|
}
|
|
|
|
|
2012-03-11 17:25:43 +08:00
|
|
|
/*
|
|
|
|
* Reverse of fmt_ident(); given an ident line, split the fields
|
|
|
|
* to allow the caller to parse it.
|
|
|
|
* Signal a success by returning 0, but date/tz fields of the result
|
|
|
|
* can still be NULL if the input line only has the name/email part
|
|
|
|
* (e.g. reading from a reflog entry).
|
|
|
|
*/
|
|
|
|
int split_ident_line(struct ident_split *split, const char *line, int len)
|
|
|
|
{
|
|
|
|
const char *cp;
|
|
|
|
size_t span;
|
|
|
|
int status = -1;
|
|
|
|
|
|
|
|
memset(split, 0, sizeof(*split));
|
|
|
|
|
|
|
|
split->name_begin = line;
|
|
|
|
for (cp = line; *cp && cp < line + len; cp++)
|
|
|
|
if (*cp == '<') {
|
|
|
|
split->mail_begin = cp + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!split->mail_begin)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
for (cp = split->mail_begin - 2; line < cp; cp--)
|
|
|
|
if (!isspace(*cp)) {
|
|
|
|
split->name_end = cp + 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!split->name_end)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
for (cp = split->mail_begin; cp < line + len; cp++)
|
|
|
|
if (*cp == '>') {
|
|
|
|
split->mail_end = cp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!split->mail_end)
|
|
|
|
return status;
|
|
|
|
|
|
|
|
for (cp = split->mail_end + 1; cp < line + len && isspace(*cp); cp++)
|
|
|
|
;
|
|
|
|
if (line + len <= cp)
|
|
|
|
goto person_only;
|
|
|
|
split->date_begin = cp;
|
|
|
|
span = strspn(cp, "0123456789");
|
|
|
|
if (!span)
|
|
|
|
goto person_only;
|
|
|
|
split->date_end = split->date_begin + span;
|
|
|
|
for (cp = split->date_end; cp < line + len && isspace(*cp); cp++)
|
|
|
|
;
|
|
|
|
if (line + len <= cp || (*cp != '+' && *cp != '-'))
|
|
|
|
goto person_only;
|
|
|
|
split->tz_begin = cp;
|
|
|
|
span = strspn(cp + 1, "0123456789");
|
|
|
|
if (!span)
|
|
|
|
goto person_only;
|
|
|
|
split->tz_end = split->tz_begin + 1 + span;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
person_only:
|
|
|
|
split->date_begin = NULL;
|
|
|
|
split->date_end = NULL;
|
|
|
|
split->tz_begin = NULL;
|
|
|
|
split->tz_end = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-02-19 12:31:05 +08:00
|
|
|
static const char *env_hint =
|
2006-11-28 18:27:39 +08:00
|
|
|
"\n"
|
2008-03-08 19:30:04 +08:00
|
|
|
"*** Please tell me who you are.\n"
|
2006-11-28 18:27:39 +08:00
|
|
|
"\n"
|
|
|
|
"Run\n"
|
|
|
|
"\n"
|
2007-12-07 07:36:45 +08:00
|
|
|
" git config --global user.email \"you@example.com\"\n"
|
2007-08-14 06:05:50 +08:00
|
|
|
" git config --global user.name \"Your Name\"\n"
|
2006-11-28 18:27:39 +08:00
|
|
|
"\n"
|
2007-08-14 06:05:50 +08:00
|
|
|
"to set your account\'s default identity.\n"
|
|
|
|
"Omit --global to set the identity only in this repository.\n"
|
2006-11-28 18:27:39 +08:00
|
|
|
"\n";
|
2006-02-19 12:31:05 +08:00
|
|
|
|
2007-12-09 09:32:08 +08:00
|
|
|
const char *fmt_ident(const char *name, const char *email,
|
|
|
|
const char *date_str, int flag)
|
2005-07-13 02:49:27 +08:00
|
|
|
{
|
2012-05-22 07:10:26 +08:00
|
|
|
static struct strbuf ident = STRBUF_INIT;
|
2005-07-13 02:49:27 +08:00
|
|
|
char date[50];
|
2007-12-09 09:32:08 +08:00
|
|
|
int error_on_no_name = (flag & IDENT_ERROR_ON_NO_NAME);
|
|
|
|
int name_addr_only = (flag & IDENT_NO_DATE);
|
2005-07-13 02:49:27 +08:00
|
|
|
|
2012-05-22 07:09:43 +08:00
|
|
|
if (!name)
|
|
|
|
name = ident_default_name();
|
|
|
|
if (!email)
|
|
|
|
email = ident_default_email();
|
2006-02-08 05:19:10 +08:00
|
|
|
|
2006-02-19 12:31:05 +08:00
|
|
|
if (!*name) {
|
Allow non-developer to clone, checkout and fetch more easily.
The code that uses committer_info() in reflog can barf and die
whenever it is asked to update a ref. And I do not think
calling ignore_missing_committer_name() upfront like recent
receive-pack did in the aplication is a reasonable workaround.
What the patch does.
- git_committer_info() takes one parameter. It used to be "if
this is true, then die() if the name is not available due to
bad GECOS, otherwise issue a warning once but leave the name
empty". The reason was because we wanted to prevent bad
commits from being made by git-commit-tree (and its
callers). The value 0 is only used by "git var -l".
Now it takes -1, 0 or 1. When set to -1, it does not
complain but uses the pw->pw_name when name is not
available. Existing 0 and 1 values mean the same thing as
they used to mean before. 0 means issue warnings and leave
it empty, 1 means barf and die.
- ignore_missing_committer_name() and its existing caller
(receive-pack, to set the reflog) have been removed.
- git-format-patch, to come up with the phoney message ID when
asked to thread, now passes -1 to git_committer_info(). This
codepath uses only the e-mail part, ignoring the name. It
used to barf and die. The other call in the same program
when asked to add signed-off-by line based on committer
identity still passes 1 to make sure it barfs instead of
adding a bogus s-o-b line.
- log_ref_write in refs.c, to come up with the name to record
who initiated the ref update in the reflog, passes -1. It
used to barf and die.
The last change means that git-update-ref, git-branch, and
commit walker backends can now be used in a repository with
reflog by somebody who does not have the user identity required
to make a commit. They all used to barf and die.
I've run tests and all of them seem to pass, and also tried "git
clone" as a user whose GECOS is empty -- git clone works again
now (it was broken when reflog was enabled by default).
But this definitely needs extra sets of eyeballs.
Signed-off-by: Junio C Hamano <junkio@cox.net>
2007-01-26 11:05:01 +08:00
|
|
|
struct passwd *pw;
|
|
|
|
|
2012-05-22 07:10:11 +08:00
|
|
|
if (error_on_no_name) {
|
2012-05-22 07:10:17 +08:00
|
|
|
if (name == git_default_name.buf)
|
2012-05-22 07:10:11 +08:00
|
|
|
fputs(env_hint, stderr);
|
2006-02-19 12:31:05 +08:00
|
|
|
die("empty ident %s <%s> not allowed", name, email);
|
2012-05-22 07:10:11 +08:00
|
|
|
}
|
2012-05-22 07:10:20 +08:00
|
|
|
pw = xgetpwuid_self();
|
ident: don't write fallback username into git_default_name
The fmt_ident function gets a flag that tells us whether to
die if the name field is blank. If it is blank and we don't
die, then we fall back to the username from the passwd file.
The current code writes the value into git_default_name.
However, that's not necessarily correct, as the empty value
might have come from git_default_name, or it might have been
passed in. This leads to two potential problems:
1. If we are overriding an empty name in the passed-in
value, then we may be overwriting a perfectly good name
(from gitconfig or gecos) in the git_default_name
buffer. Later calls to fmt_ident will end up using the
fallback name, even though a better name was available.
2. If we override an empty gecos name, we end up with the
fallback name in git_default_name. A later call that
uses IDENT_ERROR_ON_NO_NAME will see the fallback name
and think that it is a good name, instead of producing
an error. In other words, a blank gecos name would
cause an error with this code:
git_committer_info(IDENT_ERROR_ON_NO_NAME);
but not this:
git_committer_info(0);
git_committer_info(IDENT_ERROR_ON_NO_NAME);
because in the latter case, the first call has polluted
the name buffer.
Instead, let's make the fallback a per-invocation variable.
We can just use the pw->pw_name string directly, since it
only needs to persist through the rest of the function (and
we don't do any other getpwent calls).
Note that while this solves (1) for future invocations of
fmt_indent, the current invocation might use the fallback
when it could in theory load a better value from
git_default_name. However, by not passing
IDENT_ERROR_ON_NO_NAME, the caller is indicating that it
does not care too much about the name, anyway, so we don't
bother; this is primarily about protecting future callers
who do care.
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-05-22 07:10:14 +08:00
|
|
|
name = pw->pw_name;
|
2006-02-19 12:31:05 +08:00
|
|
|
}
|
2006-02-08 05:19:10 +08:00
|
|
|
|
2012-05-22 07:09:43 +08:00
|
|
|
strcpy(date, ident_default_date());
|
2010-12-14 01:02:25 +08:00
|
|
|
if (!name_addr_only && date_str && date_str[0]) {
|
|
|
|
if (parse_date(date_str, date, sizeof(date)) < 0)
|
|
|
|
die("invalid date format: %s", date_str);
|
|
|
|
}
|
2005-07-13 02:49:27 +08:00
|
|
|
|
2012-05-22 07:10:26 +08:00
|
|
|
strbuf_reset(&ident);
|
|
|
|
strbuf_addstr_without_crud(&ident, name);
|
|
|
|
strbuf_addstr(&ident, " <");
|
|
|
|
strbuf_addstr_without_crud(&ident, email);
|
|
|
|
strbuf_addch(&ident, '>');
|
2007-12-03 05:43:34 +08:00
|
|
|
if (!name_addr_only) {
|
2012-05-22 07:10:26 +08:00
|
|
|
strbuf_addch(&ident, ' ');
|
|
|
|
strbuf_addstr_without_crud(&ident, date);
|
2007-12-03 05:43:34 +08:00
|
|
|
}
|
2012-05-22 07:10:26 +08:00
|
|
|
return ident.buf;
|
2005-07-13 02:49:27 +08:00
|
|
|
}
|
2005-07-15 08:50:33 +08:00
|
|
|
|
2007-12-03 05:43:34 +08:00
|
|
|
const char *fmt_name(const char *name, const char *email)
|
|
|
|
{
|
2007-12-09 09:32:08 +08:00
|
|
|
return fmt_ident(name, email, NULL, IDENT_ERROR_ON_NO_NAME | IDENT_NO_DATE);
|
2007-12-03 05:43:34 +08:00
|
|
|
}
|
|
|
|
|
2007-12-09 09:32:08 +08:00
|
|
|
const char *git_author_info(int flag)
|
2005-07-15 08:50:33 +08:00
|
|
|
{
|
2007-02-05 09:50:14 +08:00
|
|
|
return fmt_ident(getenv("GIT_AUTHOR_NAME"),
|
2005-11-22 15:44:35 +08:00
|
|
|
getenv("GIT_AUTHOR_EMAIL"),
|
2006-02-19 12:31:05 +08:00
|
|
|
getenv("GIT_AUTHOR_DATE"),
|
2007-12-09 09:32:08 +08:00
|
|
|
flag);
|
2005-07-15 08:50:33 +08:00
|
|
|
}
|
|
|
|
|
2007-12-09 09:32:08 +08:00
|
|
|
const char *git_committer_info(int flag)
|
2005-07-15 08:50:33 +08:00
|
|
|
{
|
2010-01-08 23:39:11 +08:00
|
|
|
if (getenv("GIT_COMMITTER_NAME"))
|
|
|
|
user_ident_explicitly_given |= IDENT_NAME_GIVEN;
|
|
|
|
if (getenv("GIT_COMMITTER_EMAIL"))
|
|
|
|
user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
2007-02-05 09:50:14 +08:00
|
|
|
return fmt_ident(getenv("GIT_COMMITTER_NAME"),
|
2005-11-22 15:44:35 +08:00
|
|
|
getenv("GIT_COMMITTER_EMAIL"),
|
2006-02-19 12:31:05 +08:00
|
|
|
getenv("GIT_COMMITTER_DATE"),
|
2007-12-09 09:32:08 +08:00
|
|
|
flag);
|
2005-07-15 08:50:33 +08:00
|
|
|
}
|
2010-01-18 05:54:28 +08:00
|
|
|
|
|
|
|
int user_ident_sufficiently_given(void)
|
|
|
|
{
|
|
|
|
#ifndef WINDOWS
|
|
|
|
return (user_ident_explicitly_given & IDENT_MAIL_GIVEN);
|
|
|
|
#else
|
|
|
|
return (user_ident_explicitly_given == IDENT_ALL_GIVEN);
|
|
|
|
#endif
|
|
|
|
}
|
2012-05-22 07:09:54 +08:00
|
|
|
|
|
|
|
int git_ident_config(const char *var, const char *value, void *data)
|
|
|
|
{
|
|
|
|
if (!strcmp(var, "user.name")) {
|
|
|
|
if (!value)
|
|
|
|
return config_error_nonbool(var);
|
2012-05-22 07:10:17 +08:00
|
|
|
strbuf_reset(&git_default_name);
|
|
|
|
strbuf_addstr(&git_default_name, value);
|
2012-05-22 07:09:54 +08:00
|
|
|
user_ident_explicitly_given |= IDENT_NAME_GIVEN;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strcmp(var, "user.email")) {
|
|
|
|
if (!value)
|
|
|
|
return config_error_nonbool(var);
|
2012-05-22 07:10:17 +08:00
|
|
|
strbuf_reset(&git_default_email);
|
|
|
|
strbuf_addstr(&git_default_email, value);
|
2012-05-22 07:09:54 +08:00
|
|
|
user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|