Merge with gitk.
[git] / ident.c
1 /*
2  * ident.c
3  *
4  * create git identifier lines of the form "name <email> date"
5  *
6  * Copyright (C) 2005 Linus Torvalds
7  */
8 #include "cache.h"
9
10 #include <pwd.h>
11 #include <time.h>
12 #include <ctype.h>
13
14 static char real_email[1000];
15 static char real_name[1000];
16 static char real_date[50];
17
18 int setup_ident(void)
19 {
20         int len;
21         struct passwd *pw = getpwuid(getuid());
22
23         if (!pw)
24                 die("You don't exist. Go away!");
25
26         /* Get the name ("gecos") */
27         len = strlen(pw->pw_gecos);
28         if (len >= sizeof(real_name))
29                 die("Your parents must have hated you!");
30         memcpy(real_name, pw->pw_gecos, len+1);
31
32         /* Make up a fake email address (name + '@' + hostname [+ '.' + domainname]) */
33         len = strlen(pw->pw_name);
34         if (len > sizeof(real_email)/2)
35                 die("Your sysadmin must hate you!");
36         memcpy(real_email, pw->pw_name, len);
37         real_email[len++] = '@';
38         gethostname(real_email + len, sizeof(real_email) - len);
39         if (!strchr(real_email+len, '.')) {
40                 len = strlen(real_email);
41                 real_email[len++] = '.';
42                 getdomainname(real_email+len, sizeof(real_email)-len);
43         }
44
45         /* And set the default date */
46         datestamp(real_date, sizeof(real_date));
47         return 0;
48 }
49
50 static int add_raw(char *buf, int size, int offset, const char *str)
51 {
52         int len = strlen(str);
53         if (offset + len > size)
54                 return size;
55         memcpy(buf + offset, str, len);
56         return offset + len;
57 }
58
59 static int crud(unsigned char c)
60 {
61         static const char crud_array[256] = {
62                 [0 ... 31] = 1,
63                 [' '] = 1,
64                 ['.'] = 1, [','] = 1,
65                 [':'] = 1, [';'] = 1,
66                 ['<'] = 1, ['>'] = 1,
67                 ['"'] = 1, ['\''] = 1,
68         };
69         return crud_array[c];
70 }
71
72 /*
73  * Copy over a string to the destination, but avoid special
74  * characters ('\n', '<' and '>') and remove crud at the end
75  */
76 static int copy(char *buf, int size, int offset, const char *src)
77 {
78         int i, len;
79         unsigned char c;
80
81         /* Remove crud from the beginning.. */
82         while ((c = *src) != 0) {
83                 if (!crud(c))
84                         break;
85                 src++;
86         }
87
88         /* Remove crud from the end.. */
89         len = strlen(src);
90         while (len > 0) {
91                 c = src[len-1];
92                 if (!crud(c))
93                         break;
94                 --len;
95         }
96
97         /*
98          * Copy the rest to the buffer, but avoid the special
99          * characters '\n' '<' and '>' that act as delimeters on
100          * a identification line
101          */
102         for (i = 0; i < len; i++) {
103                 c = *src++;
104                 switch (c) {
105                 case '\n': case '<': case '>':
106                         continue;
107                 }
108                 if (offset >= size)
109                         return size;
110                 buf[offset++] = c;
111         }
112         return offset;
113 }
114
115 char *get_ident(const char *name, const char *email, const char *date_str)
116 {
117         static char buffer[1000];
118         char date[50];
119         int i;
120
121         if (!name)
122                 name = real_name;
123         if (!email)
124                 email = real_email;
125         strcpy(date, real_date);
126         if (date_str)
127                 parse_date(date_str, date, sizeof(date));
128
129         i = copy(buffer, sizeof(buffer), 0, name);
130         i = add_raw(buffer, sizeof(buffer), i, " <");
131         i = copy(buffer, sizeof(buffer), i, email);
132         i = add_raw(buffer, sizeof(buffer), i, "> ");
133         i = copy(buffer, sizeof(buffer), i, date);
134         if (i >= sizeof(buffer))
135                 die("Impossibly long personal identifier");
136         buffer[i] = 0;
137         return buffer;
138 }
139
140 char *git_author_info(void)
141 {
142         return get_ident(gitenv("GIT_AUTHOR_NAME"), gitenv("GIT_AUTHOR_EMAIL"), gitenv("GIT_AUTHOR_DATE"));
143 }
144
145 char *git_committer_info(void)
146 {
147         return get_ident(gitenv("GIT_COMMITTER_NAME"), gitenv("GIT_COMMITTER_EMAIL"), gitenv("GIT_COMMITTER_DATE"));
148 }