archive-tar: unindent write_tar_entry by one level
[gitweb.git] / ident.c
diff --git a/ident.c b/ident.c
index edb4314494c421278f5d69bf69df5f7efde8e68a..87c697c2b09692ec8a36d557aa0c73de38223492 100644 (file)
--- a/ident.c
+++ b/ident.c
@@ -117,19 +117,21 @@ static void copy_email(const struct passwd *pw)
                        sizeof(git_default_email) - len);
 }
 
-static void setup_ident(void)
+static void setup_ident(const char **name, const char **emailp)
 {
        struct passwd *pw = NULL;
 
        /* Get the name ("gecos") */
-       if (!git_default_name[0]) {
+       if (!*name && !git_default_name[0]) {
                pw = getpwuid(getuid());
                if (!pw)
                        die("You don't exist. Go away!");
                copy_gecos(pw, git_default_name, sizeof(git_default_name));
        }
+       if (!*name)
+               *name = git_default_name;
 
-       if (!git_default_email[0]) {
+       if (!*emailp && !git_default_email[0]) {
                const char *email = getenv("EMAIL");
 
                if (email && email[0]) {
@@ -144,6 +146,8 @@ static void setup_ident(void)
                        copy_email(pw);
                }
        }
+       if (!*emailp)
+               *emailp = git_default_email;
 
        /* And set the default date */
        if (!git_default_date[0])
@@ -216,6 +220,74 @@ static int copy(char *buf, size_t size, int offset, const char *src)
        return offset;
 }
 
+/*
+ * 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;
+}
+
 static const char *env_hint =
 "\n"
 "*** Please tell me who you are.\n"
@@ -239,11 +311,7 @@ const char *fmt_ident(const char *name, const char *email,
        int warn_on_no_name = (flag & IDENT_WARN_ON_NO_NAME);
        int name_addr_only = (flag & IDENT_NO_DATE);
 
-       setup_ident();
-       if (!name)
-               name = git_default_name;
-       if (!email)
-               email = git_default_email;
+       setup_ident(&name, &email);
 
        if (!*name) {
                struct passwd *pw;