config: read (but not write) from $XDG_CONFIG_HOME/git/config file
[gitweb.git] / ident.c
diff --git a/ident.c b/ident.c
index 73a06a11fa22d5901fd17f2fa76b66f59c96742f..443c0751bd1f63c059649f9f7f9174349cc1d270 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -65,23 +65,18 @@ static void add_domainname(struct strbuf *out)
 {
        char buf[1024];
        struct hostent *he;
-       const char *domainname;
 
        if (gethostname(buf, sizeof(buf))) {
                warning("cannot get host name: %s", strerror(errno));
                strbuf_addstr(out, "(none)");
                return;
        }
-       strbuf_addstr(out, buf);
        if (strchr(buf, '.'))
-               return;
-
-       he = gethostbyname(buf);
-       strbuf_addch(out, '.');
-       if (he && (domainname = strchr(he->h_name, '.')))
-               strbuf_addstr(out, domainname + 1);
+               strbuf_addstr(out, buf);
+       else if ((he = gethostbyname(buf)) && strchr(he->h_name, '.'))
+               strbuf_addstr(out, he->h_name);
        else
-               strbuf_addstr(out, "(none)");
+               strbuf_addf(out, "%s.(none)", buf);
 }
 
 static void copy_email(const struct passwd *pw, struct strbuf *email)
@@ -101,10 +96,8 @@ static void copy_email(const struct passwd *pw, struct strbuf *email)
 const char *ident_default_name(void)
 {
        if (!git_default_name.len) {
-               struct passwd *pw = getpwuid(getuid());
-               if (!pw)
-                       die("You don't exist. Go away!");
-               copy_gecos(pw, &git_default_name);
+               copy_gecos(xgetpwuid_self(), &git_default_name);
+               strbuf_trim(&git_default_name);
        }
        return git_default_name.buf;
 }
@@ -117,12 +110,9 @@ const char *ident_default_email(void)
                if (email && email[0]) {
                        strbuf_addstr(&git_default_email, email);
                        user_ident_explicitly_given |= IDENT_MAIL_GIVEN;
-               } else {
-                       struct passwd *pw = getpwuid(getuid());
-                       if (!pw)
-                               die("You don't exist. Go away!");
-                       copy_email(pw, &git_default_email);
-               }
+               } else
+                       copy_email(xgetpwuid_self(), &git_default_email);
+               strbuf_trim(&git_default_email);
        }
        return git_default_email.buf;
 }
@@ -134,15 +124,6 @@ const char *ident_default_date(void)
        return git_default_date;
 }
 
-static int add_raw(char *buf, size_t size, int offset, const char *str)
-{
-       size_t len = strlen(str);
-       if (offset + len > size)
-               return size;
-       memcpy(buf + offset, str, len);
-       return offset + len;
-}
-
 static int crud(unsigned char c)
 {
        return  c <= 32  ||
@@ -161,7 +142,7 @@ static int crud(unsigned char c)
  * Copy over a string to the destination, but avoid special
  * characters ('\n', '<' and '>') and remove crud at the end
  */
-static int copy(char *buf, size_t size, int offset, const char *src)
+static void strbuf_addstr_without_crud(struct strbuf *sb, const char *src)
 {
        size_t i, len;
        unsigned char c;
@@ -185,19 +166,19 @@ static int copy(char *buf, size_t size, int offset, const char *src)
        /*
         * Copy the rest to the buffer, but avoid the special
         * characters '\n' '<' and '>' that act as delimiters on
-        * an identification line
+        * an identification line. We can only remove crud, never add it,
+        * so 'len' is our maximum.
         */
+       strbuf_grow(sb, len);
        for (i = 0; i < len; i++) {
                c = *src++;
                switch (c) {
                case '\n': case '<': case '>':
                        continue;
                }
-               if (offset >= size)
-                       return size;
-               buf[offset++] = c;
+               sb->buf[sb->len++] = c;
        }
-       return offset;
+       sb->buf[sb->len] = '\0';
 }
 
 /*
@@ -224,7 +205,7 @@ int split_ident_line(struct ident_split *split, const char *line, int len)
        if (!split->mail_begin)
                return status;
 
-       for (cp = split->mail_begin - 2; line < cp; cp--)
+       for (cp = split->mail_begin - 2; line <= cp; cp--)
                if (!isspace(*cp)) {
                        split->name_end = cp + 1;
                        break;
@@ -284,55 +265,62 @@ static const char *env_hint =
 const char *fmt_ident(const char *name, const char *email,
                      const char *date_str, int flag)
 {
-       static char buffer[1000];
+       static struct strbuf ident = STRBUF_INIT;
        char date[50];
-       int i;
-       int error_on_no_name = (flag & IDENT_ERROR_ON_NO_NAME);
-       int name_addr_only = (flag & IDENT_NO_DATE);
+       int strict = (flag & IDENT_STRICT);
+       int want_date = !(flag & IDENT_NO_DATE);
+       int want_name = !(flag & IDENT_NO_NAME);
 
-       if (!name)
+       if (want_name && !name)
                name = ident_default_name();
        if (!email)
                email = ident_default_email();
 
-       if (!*name) {
+       if (want_name && !*name) {
                struct passwd *pw;
 
-               if (error_on_no_name) {
+               if (strict) {
                        if (name == git_default_name.buf)
                                fputs(env_hint, stderr);
-                       die("empty ident %s <%s> not allowed", name, email);
+                       die("empty ident name (for <%s>) not allowed", email);
                }
-               pw = getpwuid(getuid());
-               if (!pw)
-                       die("You don't exist. Go away!");
+               pw = xgetpwuid_self();
                name = pw->pw_name;
        }
 
-       strcpy(date, ident_default_date());
-       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);
+       if (strict && email == git_default_email.buf &&
+           strstr(email, "(none)")) {
+               fputs(env_hint, stderr);
+               die("unable to auto-detect email address (got '%s')", email);
        }
 
-       i = copy(buffer, sizeof(buffer), 0, name);
-       i = add_raw(buffer, sizeof(buffer), i, " <");
-       i = copy(buffer, sizeof(buffer), i, email);
-       if (!name_addr_only) {
-               i = add_raw(buffer, sizeof(buffer), i,  "> ");
-               i = copy(buffer, sizeof(buffer), i, date);
-       } else {
-               i = add_raw(buffer, sizeof(buffer), i, ">");
+       if (want_date) {
+               if (date_str && date_str[0]) {
+                       if (parse_date(date_str, date, sizeof(date)) < 0)
+                               die("invalid date format: %s", date_str);
+               }
+               else
+                       strcpy(date, ident_default_date());
+       }
+
+       strbuf_reset(&ident);
+       if (want_name) {
+               strbuf_addstr_without_crud(&ident, name);
+               strbuf_addstr(&ident, " <");
+       }
+       strbuf_addstr_without_crud(&ident, email);
+       if (want_name)
+                       strbuf_addch(&ident, '>');
+       if (want_date) {
+               strbuf_addch(&ident, ' ');
+               strbuf_addstr_without_crud(&ident, date);
        }
-       if (i >= sizeof(buffer))
-               die("Impossibly long personal identifier");
-       buffer[i] = 0;
-       return buffer;
+       return ident.buf;
 }
 
 const char *fmt_name(const char *name, const char *email)
 {
-       return fmt_ident(name, email, NULL, IDENT_ERROR_ON_NO_NAME | IDENT_NO_DATE);
+       return fmt_ident(name, email, NULL, IDENT_STRICT | IDENT_NO_DATE);
 }
 
 const char *git_author_info(int flag)