Code

add technical documentation about ref iteration
[git.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  */
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"
16 static const char * const git_tag_usage[] = {
17         "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
18         "git tag -d <tagname>...",
19         "git tag -l [-n[<num>]] [<pattern>...]",
20         "git tag -v <tagname>...",
21         NULL
22 };
24 static char signingkey[1000];
26 struct tag_filter {
27         const char **patterns;
28         int lines;
29         struct commit_list *with_commit;
30 };
32 static int match_pattern(const char **patterns, const char *ref)
33 {
34         /* no pattern means match everything */
35         if (!*patterns)
36                 return 1;
37         for (; *patterns; patterns++)
38                 if (!fnmatch(*patterns, ref, 0))
39                         return 1;
40         return 0;
41 }
43 static int show_reference(const char *refname, const unsigned char *sha1,
44                           int flag, void *cb_data)
45 {
46         struct tag_filter *filter = cb_data;
48         if (match_pattern(filter->patterns, refname)) {
49                 int i;
50                 unsigned long size;
51                 enum object_type type;
52                 char *buf, *sp, *eol;
53                 size_t len;
55                 if (filter->with_commit) {
56                         struct commit *commit;
58                         commit = lookup_commit_reference_gently(sha1, 1);
59                         if (!commit)
60                                 return 0;
61                         if (!is_descendant_of(commit, filter->with_commit))
62                                 return 0;
63                 }
65                 if (!filter->lines) {
66                         printf("%s\n", refname);
67                         return 0;
68                 }
69                 printf("%-15s ", refname);
71                 buf = read_sha1_file(sha1, &type, &size);
72                 if (!buf || !size)
73                         return 0;
75                 /* skip header */
76                 sp = strstr(buf, "\n\n");
77                 if (!sp) {
78                         free(buf);
79                         return 0;
80                 }
81                 /* only take up to "lines" lines, and strip the signature */
82                 size = parse_signature(buf, size);
83                 for (i = 0, sp += 2;
84                                 i < filter->lines && sp < buf + size;
85                                 i++) {
86                         if (i)
87                                 printf("\n    ");
88                         eol = memchr(sp, '\n', size - (sp - buf));
89                         len = eol ? eol - sp : size - (sp - buf);
90                         fwrite(sp, len, 1, stdout);
91                         if (!eol)
92                                 break;
93                         sp = eol + 1;
94                 }
95                 putchar('\n');
96                 free(buf);
97         }
99         return 0;
102 static int list_tags(const char **patterns, int lines,
103                         struct commit_list *with_commit)
105         struct tag_filter filter;
107         filter.patterns = patterns;
108         filter.lines = lines;
109         filter.with_commit = with_commit;
111         for_each_tag_ref(show_reference, (void *) &filter);
113         return 0;
116 typedef int (*each_tag_name_fn)(const char *name, const char *ref,
117                                 const unsigned char *sha1);
119 static int for_each_tag_name(const char **argv, each_tag_name_fn fn)
121         const char **p;
122         char ref[PATH_MAX];
123         int had_error = 0;
124         unsigned char sha1[20];
126         for (p = argv; *p; p++) {
127                 if (snprintf(ref, sizeof(ref), "refs/tags/%s", *p)
128                                         >= sizeof(ref)) {
129                         error(_("tag name too long: %.*s..."), 50, *p);
130                         had_error = 1;
131                         continue;
132                 }
133                 if (!resolve_ref(ref, sha1, 1, NULL)) {
134                         error(_("tag '%s' not found."), *p);
135                         had_error = 1;
136                         continue;
137                 }
138                 if (fn(*p, ref, sha1))
139                         had_error = 1;
140         }
141         return had_error;
144 static int delete_tag(const char *name, const char *ref,
145                                 const unsigned char *sha1)
147         if (delete_ref(ref, sha1, 0))
148                 return 1;
149         printf(_("Deleted tag '%s' (was %s)\n"), name, find_unique_abbrev(sha1, DEFAULT_ABBREV));
150         return 0;
153 static int verify_tag(const char *name, const char *ref,
154                                 const unsigned char *sha1)
156         const char *argv_verify_tag[] = {"verify-tag",
157                                         "-v", "SHA1_HEX", NULL};
158         argv_verify_tag[2] = sha1_to_hex(sha1);
160         if (run_command_v_opt(argv_verify_tag, RUN_GIT_CMD))
161                 return error(_("could not verify the tag '%s'"), name);
162         return 0;
165 static int do_sign(struct strbuf *buffer)
167         struct child_process gpg;
168         const char *args[4];
169         char *bracket;
170         int len;
171         int i, j;
173         if (!*signingkey) {
174                 if (strlcpy(signingkey, git_committer_info(IDENT_ERROR_ON_NO_NAME),
175                                 sizeof(signingkey)) > sizeof(signingkey) - 1)
176                         return error(_("committer info too long."));
177                 bracket = strchr(signingkey, '>');
178                 if (bracket)
179                         bracket[1] = '\0';
180         }
182         /* When the username signingkey is bad, program could be terminated
183          * because gpg exits without reading and then write gets SIGPIPE. */
184         signal(SIGPIPE, SIG_IGN);
186         memset(&gpg, 0, sizeof(gpg));
187         gpg.argv = args;
188         gpg.in = -1;
189         gpg.out = -1;
190         args[0] = "gpg";
191         args[1] = "-bsau";
192         args[2] = signingkey;
193         args[3] = NULL;
195         if (start_command(&gpg))
196                 return error(_("could not run gpg."));
198         if (write_in_full(gpg.in, buffer->buf, buffer->len) != buffer->len) {
199                 close(gpg.in);
200                 close(gpg.out);
201                 finish_command(&gpg);
202                 return error(_("gpg did not accept the tag data"));
203         }
204         close(gpg.in);
205         len = strbuf_read(buffer, gpg.out, 1024);
206         close(gpg.out);
208         if (finish_command(&gpg) || !len || len < 0)
209                 return error(_("gpg failed to sign the tag"));
211         /* Strip CR from the line endings, in case we are on Windows. */
212         for (i = j = 0; i < buffer->len; i++)
213                 if (buffer->buf[i] != '\r') {
214                         if (i != j)
215                                 buffer->buf[j] = buffer->buf[i];
216                         j++;
217                 }
218         strbuf_setlen(buffer, j);
220         return 0;
223 static const char tag_template[] =
224         N_("\n"
225         "#\n"
226         "# Write a tag message\n"
227         "#\n");
229 static void set_signingkey(const char *value)
231         if (strlcpy(signingkey, value, sizeof(signingkey)) >= sizeof(signingkey))
232                 die(_("signing key value too long (%.10s...)"), value);
235 static int git_tag_config(const char *var, const char *value, void *cb)
237         if (!strcmp(var, "user.signingkey")) {
238                 if (!value)
239                         return config_error_nonbool(var);
240                 set_signingkey(value);
241                 return 0;
242         }
244         return git_default_config(var, value, cb);
247 static void write_tag_body(int fd, const unsigned char *sha1)
249         unsigned long size;
250         enum object_type type;
251         char *buf, *sp;
253         buf = read_sha1_file(sha1, &type, &size);
254         if (!buf)
255                 return;
256         /* skip header */
257         sp = strstr(buf, "\n\n");
259         if (!sp || !size || type != OBJ_TAG) {
260                 free(buf);
261                 return;
262         }
263         sp += 2; /* skip the 2 LFs */
264         write_or_die(fd, sp, parse_signature(sp, buf + size - sp));
266         free(buf);
269 static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
271         if (sign && do_sign(buf) < 0)
272                 return error(_("unable to sign the tag"));
273         if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
274                 return error(_("unable to write tag file"));
275         return 0;
278 static void create_tag(const unsigned char *object, const char *tag,
279                        struct strbuf *buf, int message, int sign,
280                        unsigned char *prev, unsigned char *result)
282         enum object_type type;
283         char header_buf[1024];
284         int header_len;
285         char *path = NULL;
287         type = sha1_object_info(object, NULL);
288         if (type <= OBJ_NONE)
289             die(_("bad object type."));
291         header_len = snprintf(header_buf, sizeof(header_buf),
292                           "object %s\n"
293                           "type %s\n"
294                           "tag %s\n"
295                           "tagger %s\n\n",
296                           sha1_to_hex(object),
297                           typename(type),
298                           tag,
299                           git_committer_info(IDENT_ERROR_ON_NO_NAME));
301         if (header_len > sizeof(header_buf) - 1)
302                 die(_("tag header too big."));
304         if (!message) {
305                 int fd;
307                 /* write the template message before editing: */
308                 path = git_pathdup("TAG_EDITMSG");
309                 fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600);
310                 if (fd < 0)
311                         die_errno(_("could not create file '%s'"), path);
313                 if (!is_null_sha1(prev))
314                         write_tag_body(fd, prev);
315                 else
316                         write_or_die(fd, _(tag_template), strlen(_(tag_template)));
317                 close(fd);
319                 if (launch_editor(path, buf, NULL)) {
320                         fprintf(stderr,
321                         _("Please supply the message using either -m or -F option.\n"));
322                         exit(1);
323                 }
324         }
326         stripspace(buf, 1);
328         if (!message && !buf->len)
329                 die(_("no tag message?"));
331         strbuf_insert(buf, 0, header_buf, header_len);
333         if (build_tag_object(buf, sign, result) < 0) {
334                 if (path)
335                         fprintf(stderr, _("The tag message has been left in %s\n"),
336                                 path);
337                 exit(128);
338         }
339         if (path) {
340                 unlink_or_warn(path);
341                 free(path);
342         }
345 struct msg_arg {
346         int given;
347         struct strbuf buf;
348 };
350 static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
352         struct msg_arg *msg = opt->value;
354         if (!arg)
355                 return -1;
356         if (msg->buf.len)
357                 strbuf_addstr(&(msg->buf), "\n\n");
358         strbuf_addstr(&(msg->buf), arg);
359         msg->given = 1;
360         return 0;
363 static int strbuf_check_tag_ref(struct strbuf *sb, const char *name)
365         if (name[0] == '-')
366                 return CHECK_REF_FORMAT_ERROR;
368         strbuf_reset(sb);
369         strbuf_addf(sb, "refs/tags/%s", name);
371         return check_ref_format(sb->buf);
374 int cmd_tag(int argc, const char **argv, const char *prefix)
376         struct strbuf buf = STRBUF_INIT;
377         struct strbuf ref = STRBUF_INIT;
378         unsigned char object[20], prev[20];
379         const char *object_ref, *tag;
380         struct ref_lock *lock;
382         int annotate = 0, sign = 0, force = 0, lines = -1,
383                 list = 0, delete = 0, verify = 0;
384         const char *msgfile = NULL, *keyid = NULL;
385         struct msg_arg msg = { 0, STRBUF_INIT };
386         struct commit_list *with_commit = NULL;
387         struct option options[] = {
388                 OPT_BOOLEAN('l', NULL, &list, "list tag names"),
389                 { OPTION_INTEGER, 'n', NULL, &lines, "n",
390                                 "print <n> lines of each tag message",
391                                 PARSE_OPT_OPTARG, NULL, 1 },
392                 OPT_BOOLEAN('d', NULL, &delete, "delete tags"),
393                 OPT_BOOLEAN('v', NULL, &verify, "verify tags"),
395                 OPT_GROUP("Tag creation options"),
396                 OPT_BOOLEAN('a', NULL, &annotate,
397                                         "annotated tag, needs a message"),
398                 OPT_CALLBACK('m', NULL, &msg, "message",
399                              "tag message", parse_msg_arg),
400                 OPT_FILENAME('F', NULL, &msgfile, "read message from file"),
401                 OPT_BOOLEAN('s', NULL, &sign, "annotated and GPG-signed tag"),
402                 OPT_STRING('u', NULL, &keyid, "key-id",
403                                         "use another key to sign the tag"),
404                 OPT__FORCE(&force, "replace the tag if exists"),
406                 OPT_GROUP("Tag listing options"),
407                 {
408                         OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
409                         "print only tags that contain the commit",
410                         PARSE_OPT_LASTARG_DEFAULT,
411                         parse_opt_with_commit, (intptr_t)"HEAD",
412                 },
413                 OPT_END()
414         };
416         git_config(git_tag_config, NULL);
418         argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
420         if (keyid) {
421                 sign = 1;
422                 set_signingkey(keyid);
423         }
424         if (sign)
425                 annotate = 1;
426         if (argc == 0 && !(delete || verify))
427                 list = 1;
429         if ((annotate || msg.given || msgfile || force) &&
430             (list || delete || verify))
431                 usage_with_options(git_tag_usage, options);
433         if (list + delete + verify > 1)
434                 usage_with_options(git_tag_usage, options);
435         if (list)
436                 return list_tags(argv, lines == -1 ? 0 : lines,
437                                  with_commit);
438         if (lines != -1)
439                 die(_("-n option is only allowed with -l."));
440         if (with_commit)
441                 die(_("--contains option is only allowed with -l."));
442         if (delete)
443                 return for_each_tag_name(argv, delete_tag);
444         if (verify)
445                 return for_each_tag_name(argv, verify_tag);
447         if (msg.given || msgfile) {
448                 if (msg.given && msgfile)
449                         die(_("only one -F or -m option is allowed."));
450                 annotate = 1;
451                 if (msg.given)
452                         strbuf_addbuf(&buf, &(msg.buf));
453                 else {
454                         if (!strcmp(msgfile, "-")) {
455                                 if (strbuf_read(&buf, 0, 1024) < 0)
456                                         die_errno(_("cannot read '%s'"), msgfile);
457                         } else {
458                                 if (strbuf_read_file(&buf, msgfile, 1024) < 0)
459                                         die_errno(_("could not open or read '%s'"),
460                                                 msgfile);
461                         }
462                 }
463         }
465         tag = argv[0];
467         object_ref = argc == 2 ? argv[1] : "HEAD";
468         if (argc > 2)
469                 die(_("too many params"));
471         if (get_sha1(object_ref, object))
472                 die(_("Failed to resolve '%s' as a valid ref."), object_ref);
474         if (strbuf_check_tag_ref(&ref, tag))
475                 die(_("'%s' is not a valid tag name."), tag);
477         if (!resolve_ref(ref.buf, prev, 1, NULL))
478                 hashclr(prev);
479         else if (!force)
480                 die(_("tag '%s' already exists"), tag);
482         if (annotate)
483                 create_tag(object, tag, &buf, msg.given || msgfile,
484                            sign, prev, object);
486         lock = lock_any_ref_for_update(ref.buf, prev, 0);
487         if (!lock)
488                 die(_("%s: cannot lock the ref"), ref.buf);
489         if (write_ref_sha1(lock, object, NULL) < 0)
490                 die(_("%s: cannot update the ref"), ref.buf);
491         if (force && hashcmp(prev, object))
492                 printf(_("Updated tag '%s' (was %s)\n"), tag, find_unique_abbrev(prev, DEFAULT_ABBREV));
494         strbuf_release(&buf);
495         strbuf_release(&ref);
496         return 0;