mailmap: support reading mailmap from blobs
In a bare repository, there isn't a simple way to respect an in-tree mailmap without extracting it to a temporary file. This patch provides a config variable, similar to mailmap.file, which reads the mailmap from a blob in the repository. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Dec 12, 2012 at 06:04 UTC
086109006f695166daf2934417a20681b0c94ab8
5 files changed
+129
-2
Documentation/config.txt
+6
@@ -1517,6 +1517,12 @@ mailmap.file::
1517
subdirectory, or somewhere outside of the repository itself.
1518
See linkgit:git-shortlog[1] and linkgit:git-blame[1].
1519
1520
+mailmap.blob::
1521
+ Like `mailmap.file`, but consider the value as a reference to a
1522
+ blob in the repository (e.g., `HEAD:.mailmap`). If both
1523
+ `mailmap.file` and `mailmap.blob` are given, both are parsed,
1524
+ with entries from `mailmap.file` taking precedence.
1525
+
1526
man.viewer::
1527
Specify the programs that may be used to display help in the
1528
'man' format. See linkgit:git-help[1].
cache.h
+1
@@ -1155,6 +1155,7 @@ extern int author_ident_sufficiently_given(void);
1155
extern const char *git_commit_encoding;
1156
extern const char *git_log_output_encoding;
1157
extern const char *git_mailmap_file;
1158
+extern const char *git_mailmap_blob;
1159
1160
/* IO helper functions */
1161
extern void maybe_flush_or_die(FILE *, const char *);
config.c
+2
@@ -839,6 +839,8 @@ static int git_default_mailmap_config(const char *var, const char *value)
839
{
840
if (!strcmp(var, "mailmap.file"))
841
return git_config_string(&git_mailmap_file, var, value);
842
+ if (!strcmp(var, "mailmap.blob"))
843
+ return git_config_string(&git_mailmap_blob, var, value);
844
845
/* Add other config variables here and to Documentation/config.txt. */
846
return 0;
mailmap.c
+47
-2
@@ -10,6 +10,7 @@ static inline void debug_mm(const char *format, ...) {}
10
#endif
11
12
const char *git_mailmap_file;
13
+const char *git_mailmap_blob;
14
15
struct mailmap_info {
16
char *name;
@@ -177,12 +178,56 @@ static int read_mailmap_file(struct string_list *map, const char *filename,
178
return 0;
179
}
180
181
+static void read_mailmap_buf(struct string_list *map,
182
+ const char *buf, unsigned long len,
183
+ char **repo_abbrev)
184
+{
185
+ while (len) {
186
+ const char *end = strchrnul(buf, '\n');
187
+ unsigned long linelen = end - buf + 1;
188
+ char *line = xmemdupz(buf, linelen);
189
+
190
+ read_mailmap_line(map, line, repo_abbrev);
191
+
192
+ free(line);
193
+ buf += linelen;
194
+ len -= linelen;
195
+ }
196
+}
197
+
198
+static int read_mailmap_blob(struct string_list *map,
199
+ const char *name,
200
+ char **repo_abbrev)
201
+{
202
+ unsigned char sha1[20];
203
+ char *buf;
204
+ unsigned long size;
205
+ enum object_type type;
206
+
207
+ if (!name)
208
+ return 1;
209
+ if (get_sha1(name, sha1) < 0)
210
+ return 1;
211
+
212
+ buf = read_sha1_file(sha1, &type, &size);
213
+ if (!buf)
214
+ return 1;
215
+ if (type != OBJ_BLOB)
216
+ return 1;
217
+
218
+ read_mailmap_buf(map, buf, size, repo_abbrev);
219
+
220
+ free(buf);
221
+ return 0;
222
+}
223
+
224
int read_mailmap(struct string_list *map, char **repo_abbrev)
225
{
226
map->strdup_strings = 1;
183
- /* each failure returns 1, so >1 means both calls failed */
227
+ /* each failure returns 1, so >2 means all calls failed */
228
return read_mailmap_file(map, ".mailmap", repo_abbrev) +
185
- read_mailmap_file(map, git_mailmap_file, repo_abbrev) > 1;
229
+ read_mailmap_blob(map, git_mailmap_blob, repo_abbrev) +
230
+ read_mailmap_file(map, git_mailmap_file, repo_abbrev) > 2;
231
}
232
233
void clear_mailmap(struct string_list *map)
t/t4203-mailmap.sh
+73
@@ -149,6 +149,79 @@ test_expect_success 'No mailmap files, but configured' '
149
test_cmp expect actual
150
'
151
152
+test_expect_success 'setup mailmap blob tests' '
153
+ git checkout -b map &&
154
+ test_when_finished "git checkout master" &&
155
+ cat >just-bugs <<-\EOF &&
156
+ Blob Guy <bugs@company.xx>
157
+ EOF
158
+ cat >both <<-\EOF &&
159
+ Blob Guy <author@example.com>
160
+ Blob Guy <bugs@company.xx>
161
+ EOF
162
+ git add just-bugs both &&
163
+ git commit -m "my mailmaps" &&
164
+ echo "Repo Guy <author@example.com>" >.mailmap &&
165
+ echo "Internal Guy <author@example.com>" >internal.map
166
+'
167
+
168
+test_expect_success 'mailmap.blob set' '
169
+ cat >expect <<-\EOF &&
170
+ Blob Guy (1):
171
+ second
172
+
173
+ Repo Guy (1):
174
+ initial
175
+
176
+ EOF
177
+ git -c mailmap.blob=map:just-bugs shortlog HEAD >actual &&
178
+ test_cmp expect actual
179
+'
180
+
181
+test_expect_success 'mailmap.blob overrides .mailmap' '
182
+ cat >expect <<-\EOF &&
183
+ Blob Guy (2):
184
+ initial
185
+ second
186
+
187
+ EOF
188
+ git -c mailmap.blob=map:both shortlog HEAD >actual &&
189
+ test_cmp expect actual
190
+'
191
+
192
+test_expect_success 'mailmap.file overrides mailmap.blob' '
193
+ cat >expect <<-\EOF &&
194
+ Blob Guy (1):
195
+ second
196
+
197
+ Internal Guy (1):
198
+ initial
199
+
200
+ EOF
201
+ git \
202
+ -c mailmap.blob=map:both \
203
+ -c mailmap.file=internal.map \
204
+ shortlog HEAD >actual &&
205
+ test_cmp expect actual
206
+'
207
+
208
+test_expect_success 'mailmap.blob can be missing' '
209
+ cat >expect <<-\EOF &&
210
+ Repo Guy (1):
211
+ initial
212
+
213
+ nick1 (1):
214
+ second
215
+
216
+ EOF
217
+ git -c mailmap.blob=map:nonexistent shortlog HEAD >actual &&
218
+ test_cmp expect actual
219
+'
220
+
221
+test_expect_success 'cleanup after mailmap.blob tests' '
222
+ rm -f .mailmap
223
+'
224
+
225
# Extended mailmap configurations should give us the following output for shortlog
226
cat >expect <<\EOF
227
A U Thor <author@example.com> (1):