Revert clock-skew based attempt to optimize tag --contains traversal
[git] / builtin / tag.c
1 /*
2  * Builtin "git tag"
3  *
4  * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>,
5  *                    Carlos Rica <jasampler@gmail.com>
6  * Based on git-tag.sh and mktag.c by Linus Torvalds.
7  */
8
9 #include "cache.h"
10 #include "builtin.h"
11 #include "refs.h"
12 #include "tag.h"
13 #include "run-command.h"
14 #include "parse-options.h"
15 #include "diff.h"
16 #include "revision.h"
17
18 static const char * const git_tag_usage[] = {
19         "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
20         "git tag -d <tagname>...",
21         "git tag -l [-n[<num>]] [<pattern>]",
22         "git tag -v <tagname>...",
23         NULL
24 };
25
26 static char signingkey[1000];
27
28 struct tag_filter {
29         const char *pattern;
30         int lines;
31         struct commit_list *with_commit;
32 };
33
34 #define PGP_SIGNATURE "-----BEGIN PGP SIGNATURE-----"
35
36 static int in_commit_list(const struct commit_list *want, struct commit *c)
37 {
38         for (; want; want = want->next)
39                 if (!hashcmp(want->item->object.sha1, c->object.sha1))
40                         return 1;
41         return 0;
42 }
43
44 static int contains_recurse(struct commit *candidate,
45                             const struct commit_list *want)
46 {
47         struct commit_list *p;
48
49         /* was it previously marked as containing a want commit? */
50         if (candidate->object.flags & TMP_MARK)
51                 return 1;
52         /* or marked as not possibly containing a want commit? */
53         if (candidate->object.flags & UNINTERESTING)
54                 return 0;
55         /* or are we it? */
56         if (in_commit_list(want, candidate))
57                 return 1;
58
59         if (parse_commit(candidate) < 0)
60                 return 0;
61
62         /* Otherwise recurse and mark ourselves for future traversals. */
63         for (p = candidate->parents; p; p = p->next) {
64                 if (contains_recurse(p->item, want)) {
65                         candidate->object.flags |= TMP_MARK;
66                         return 1;
67                 }
68         }
69         candidate->object.flags |= UNINTERESTING;
70         return 0;
71 }
72
73 static int contains(struct commit *candidate, const struct commit_list *want)
74 {
75         return contains_recurse(candidate, want);
76 }
77
78 static int show_reference(const char *refname, const unsigned char *sha1,
79                           int flag, void *cb_data)
80 {
81         struct tag_filter *filter = cb_data;
82
83         if (!fnmatch(filter->pattern, refname, 0)) {
84                 int i;
85                 unsigned long size;
86                 enum object_type type;
87                 char *buf, *sp, *eol;
88                 size_t len;
89
90                 if (filter->with_commit) {
91                         struct commit *commit;
92
93                         commit = lookup_commit_reference_gently(sha1, 1);
94                         if (!commit)
95                                 return 0;
96                         if (!contains(commit, filter->with_commit))
97                                 return 0;
98                 }
99
100                 if (!filter->lines) {
101                         printf("%s\n", refname);
102                         return 0;
103                 }
104                 printf("%-15s ", refname);
105
106                 buf = read_sha1_file(sha1, &type, &size);
107                 if (!buf || !size)
108                         return 0;
109
110                 /* skip header */
111                 sp = strstr(buf, "\n\n");
112                 if (!sp) {
113                         free(buf);
114                         return 0;
115                 }
116                 /* only take up to "lines" lines, and strip the signature */
117                 for (i = 0, sp += 2;
118                                 i < filter->lines && sp < buf + size &&
119                                 prefixcmp(sp, PGP_SIGNATURE "\n");
120                                 i++) {
121                         if (i)
122                                 printf("\n    ");
123                         eol = memchr(sp, '\n', size - (sp - buf));
124                         len = eol ? eol - sp : size - (sp - buf);
125                         fwrite(sp, len, 1, stdout);
126                         if (!eol)
127                                 break;
128                         sp = eol + 1;
129                 }
130                 putchar('\n');
131                 free(buf);
132         }
133
134         return 0;
135 }
136
137 static int list_tags(const char *pattern, int lines,
138                         struct commit_list *with_commit)
139 {
140         struct tag_filter filter;
141
142         if (pattern == NULL)
143                 pattern = "*";
144
145         filter.pattern = pattern;
146         filter.lines = lines;
147         filter.with_commit = with_commit;
148
149         for_each_tag_ref(show_reference, (void *) &filter);
150
151         return 0;
152 }
153
154 typedef int (*each_tag_name_fn)(const char *name, const char *ref,
155                                 const unsigned char *sha1);
156
157 static int for_each_tag_name(const char **argv, each_tag_name_fn fn)
158 {
159         const char **p;
160         char ref[PATH_MAX];
161         int had_error = 0;
162         unsigned char sha1[20];
163
164         for (p = argv; *p; p++) {
165                 if (snprintf(ref, sizeof(ref), "refs/tags/%s", *p)
166                                         >= sizeof(ref)) {
167                         error("tag name too long: %.*s...", 50, *p);
168                         had_error = 1;
169                         continue;
170                 }
171                 if (!resolve_ref(ref, sha1, 1, NULL)) {
172                         error("tag '%s' not found.", *p);
173                         had_error = 1;
174                         continue;
175                 }
176                 if (fn(*p, ref, sha1))
177                         had_error = 1;
178         }
179         return had_error;
180 }
181
182 static int delete_tag(const char *name, const char *ref,
183                                 const unsigned char *sha1)
184 {
185         if (delete_ref(ref, sha1, 0))
186                 return 1;
187         printf("Deleted tag '%s' (was %s)\n", name, find_unique_abbrev(sha1, DEFAULT_ABBREV));
188         return 0;
189 }
190
191 static int verify_tag(const char *name, const char *ref,
192                                 const unsigned char *sha1)
193 {
194         const char *argv_verify_tag[] = {"verify-tag",
195                                         "-v", "SHA1_HEX", NULL};
196         argv_verify_tag[2] = sha1_to_hex(sha1);
197
198         if (run_command_v_opt(argv_verify_tag, RUN_GIT_CMD))
199                 return error("could not verify the tag '%s'", name);
200         return 0;
201 }
202
203 static int do_sign(struct strbuf *buffer)
204 {
205         struct child_process gpg;
206         const char *args[4];
207         char *bracket;
208         int len;
209         int i, j;
210
211         if (!*signingkey) {
212                 if (strlcpy(signingkey, git_committer_info(IDENT_ERROR_ON_NO_NAME),
213                                 sizeof(signingkey)) > sizeof(signingkey) - 1)
214                         return error("committer info too long.");
215                 bracket = strchr(signingkey, '>');
216                 if (bracket)
217                         bracket[1] = '\0';
218         }
219
220         /* When the username signingkey is bad, program could be terminated
221          * because gpg exits without reading and then write gets SIGPIPE. */
222         signal(SIGPIPE, SIG_IGN);
223
224         memset(&gpg, 0, sizeof(gpg));
225         gpg.argv = args;
226         gpg.in = -1;
227         gpg.out = -1;
228         args[0] = "gpg";
229         args[1] = "-bsau";
230         args[2] = signingkey;
231         args[3] = NULL;
232
233         if (start_command(&gpg))
234                 return error("could not run gpg.");
235
236         if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {
237                 close(gpg.in);
238                 close(gpg.out);
239                 finish_command(&gpg);
240                 return error("gpg did not accept the tag data");
241         }
242         close(gpg.in);
243         len = strbuf_read(buffer, gpg.out, 1024);
244         close(gpg.out);
245
246         if (finish_command(&gpg) || !len || len < 0)
247                 return error("gpg failed to sign the tag");
248
249         /* Strip CR from the line endings, in case we are on Windows. */
250         for (i = j = 0; i < buffer->len; i++)
251                 if (buffer->buf[i] != '\r') {
252                         if (i != j)
253                                 buffer->buf[j] = buffer->buf[i];
254                         j++;
255                 }
256         strbuf_setlen(buffer, j);
257
258         return 0;
259 }
260
261 static const char tag_template[] =
262         "\n"
263         "#\n"
264         "# Write a tag message\n"
265         "#\n";
266
267 static void set_signingkey(const char *value)
268 {
269         if (strlcpy(signingkey, value, sizeof(signingkey)) >= sizeof(signingkey))
270                 die("signing key value too long (%.10s...)", value);
271 }
272
273 static int git_tag_config(const char *var, const char *value, void *cb)
274 {
275         if (!strcmp(var, "user.signingkey")) {
276                 if (!value)
277                         return config_error_nonbool(var);
278                 set_signingkey(value);
279                 return 0;
280         }
281
282         return git_default_config(var, value, cb);
283 }
284
285 static void write_tag_body(int fd, const unsigned char *sha1)
286 {
287         unsigned long size;
288         enum object_type type;
289         char *buf, *sp, *eob;
290         size_t len;
291
292         buf = read_sha1_file(sha1, &type, &size);
293         if (!buf)
294                 return;
295         /* skip header */
296         sp = strstr(buf, "\n\n");
297
298         if (!sp || !size || type != OBJ_TAG) {
299                 free(buf);
300                 return;
301         }
302         sp += 2; /* skip the 2 LFs */
303         eob = strstr(sp, "\n" PGP_SIGNATURE "\n");
304         if (eob)
305                 len = eob - sp;
306         else
307                 len = buf + size - sp;
308         write_or_die(fd, sp, len);
309
310         free(buf);
311 }
312
313 static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
314 {
315         if (sign && do_sign(buf) < 0)
316                 return error("unable to sign the tag");
317         if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
318                 return error("unable to write tag file");
319         return 0;
320 }
321
322 static void create_tag(const unsigned char *object, const char *tag,
323                        struct strbuf *buf, int message, int sign,
324                        unsigned char *prev, unsigned char *result)
325 {
326         enum object_type type;
327         char header_buf[1024];
328         int header_len;
329         char *path = NULL;
330
331         type = sha1_object_info(object, NULL);
332         if (type <= OBJ_NONE)
333             die("bad object type.");
334
335         header_len = snprintf(header_buf, sizeof(header_buf),
336                           "object %s\n"
337                           "type %s\n"
338                           "tag %s\n"
339                           "tagger %s\n\n",
340                           sha1_to_hex(object),
341                           typename(type),
342                           tag,
343                           git_committer_info(IDENT_ERROR_ON_NO_NAME));
344
345         if (header_len > sizeof(header_buf) - 1)
346                 die("tag header too big.");
347
348         if (!message) {
349                 int fd;
350
351                 /* write the template message before editing: */
352                 path = git_pathdup("TAG_EDITMSG");
353                 fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
354                 if (fd < 0)
355                         die_errno("could not create file '%s'", path);
356
357                 if (!is_null_sha1(prev))
358                         write_tag_body(fd, prev);
359                 else
360                         write_or_die(fd, tag_template, strlen(tag_template));
361                 close(fd);
362
363                 if (launch_editor(path, buf, NULL)) {
364                         fprintf(stderr,
365                         "Please supply the message using either -m or -F option.\n");
366                         exit(1);
367                 }
368         }
369
370         stripspace(buf, 1);
371
372         if (!message && !buf->len)
373                 die("no tag message?");
374
375         strbuf_insert(buf, 0, header_buf, header_len);
376
377         if (build_tag_object(buf, sign, result) < 0) {
378                 if (path)
379                         fprintf(stderr, "The tag message has been left in %s\n",
380                                 path);
381                 exit(128);
382         }
383         if (path) {
384                 unlink_or_warn(path);
385                 free(path);
386         }
387 }
388
389 struct msg_arg {
390         int given;
391         struct strbuf buf;
392 };
393
394 static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
395 {
396         struct msg_arg *msg = opt->value;
397
398         if (!arg)
399                 return -1;
400         if (msg->buf.len)
401                 strbuf_addstr(&(msg->buf), "\n\n");
402         strbuf_addstr(&(msg->buf), arg);
403         msg->given = 1;
404         return 0;
405 }
406
407 int cmd_tag(int argc, const char **argv, const char *prefix)
408 {
409         struct strbuf buf = STRBUF_INIT;
410         unsigned char object[20], prev[20];
411         char ref[PATH_MAX];
412         const char *object_ref, *tag;
413         struct ref_lock *lock;
414
415         int annotate = 0, sign = 0, force = 0, lines = -1,
416                 list = 0, delete = 0, verify = 0;
417         const char *msgfile = NULL, *keyid = NULL;
418         struct msg_arg msg = { 0, STRBUF_INIT };
419         struct commit_list *with_commit = NULL;
420         struct option options[] = {
421                 OPT_BOOLEAN('l', NULL, &list, "list tag names"),
422                 { OPTION_INTEGER, 'n', NULL, &lines, "n",
423                                 "print <n> lines of each tag message",
424                                 PARSE_OPT_OPTARG, NULL, 1 },
425                 OPT_BOOLEAN('d', NULL, &delete, "delete tags"),
426                 OPT_BOOLEAN('v', NULL, &verify, "verify tags"),
427
428                 OPT_GROUP("Tag creation options"),
429                 OPT_BOOLEAN('a', NULL, &annotate,
430                                         "annotated tag, needs a message"),
431                 OPT_CALLBACK('m', NULL, &msg, "msg",
432                              "message for the tag", parse_msg_arg),
433                 OPT_FILENAME('F', NULL, &msgfile, "message in a file"),
434                 OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
435                 OPT_STRING('u', NULL, &keyid, "key-id",
436                                         "use another key to sign the tag"),
437                 OPT_BOOLEAN('f', "force", &force, "replace the tag if exists"),
438
439                 OPT_GROUP("Tag listing options"),
440                 {
441                         OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
442                         "print only tags that contain the commit",
443                         PARSE_OPT_LASTARG_DEFAULT,
444                         parse_opt_with_commit, (intptr_t)"HEAD",
445                 },
446                 OPT_END()
447         };
448
449         git_config(git_tag_config, NULL);
450
451         argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
452
453         if (keyid) {
454                 sign = 1;
455                 set_signingkey(keyid);
456         }
457         if (sign)
458                 annotate = 1;
459         if (argc == 0 && !(delete || verify))
460                 list = 1;
461
462         if ((annotate || msg.given || msgfile || force) &&
463             (list || delete || verify))
464                 usage_with_options(git_tag_usage, options);
465
466         if (list + delete + verify > 1)
467                 usage_with_options(git_tag_usage, options);
468         if (list)
469                 return list_tags(argv[0], lines == -1 ? 0 : lines,
470                                  with_commit);
471         if (lines != -1)
472                 die("-n option is only allowed with -l.");
473         if (with_commit)
474                 die("--contains option is only allowed with -l.");
475         if (delete)
476                 return for_each_tag_name(argv, delete_tag);
477         if (verify)
478                 return for_each_tag_name(argv, verify_tag);
479
480         if (msg.given || msgfile) {
481                 if (msg.given && msgfile)
482                         die("only one -F or -m option is allowed.");
483                 annotate = 1;
484                 if (msg.given)
485                         strbuf_addbuf(&buf, &(msg.buf));
486                 else {
487                         if (!strcmp(msgfile, "-")) {
488                                 if (strbuf_read(&buf, 0, 1024) < 0)
489                                         die_errno("cannot read '%s'", msgfile);
490                         } else {
491                                 if (strbuf_read_file(&buf, msgfile, 1024) < 0)
492                                         die_errno("could not open or read '%s'",
493                                                 msgfile);
494                         }
495                 }
496         }
497
498         tag = argv[0];
499
500         object_ref = argc == 2 ? argv[1] : "HEAD";
501         if (argc > 2)
502                 die("too many params");
503
504         if (get_sha1(object_ref, object))
505                 die("Failed to resolve '%s' as a valid ref.", object_ref);
506
507         if (snprintf(ref, sizeof(ref), "refs/tags/%s", tag) > sizeof(ref) - 1)
508                 die("tag name too long: %.*s...", 50, tag);
509         if (check_ref_format(ref))
510                 die("'%s' is not a valid tag name.", tag);
511
512         if (!resolve_ref(ref, prev, 1, NULL))
513                 hashclr(prev);
514         else if (!force)
515                 die("tag '%s' already exists", tag);
516
517         if (annotate)
518                 create_tag(object, tag, &buf, msg.given || msgfile,
519                            sign, prev, object);
520
521         lock = lock_any_ref_for_update(ref, prev, 0);
522         if (!lock)
523                 die("%s: cannot lock the ref", ref);
524         if (write_ref_sha1(lock, object, NULL) < 0)
525                 die("%s: cannot update the ref", ref);
526         if (force && hashcmp(prev, object))
527                 printf("Updated tag '%s' (was %s)\n", tag, find_unique_abbrev(prev, DEFAULT_ABBREV));
528
529         strbuf_release(&buf);
530         return 0;
531 }