git-tag: introduce --cleanup option

Normally git tag strips tag message lines starting with '#', trailing spaces from every line and empty lines from the beginning and end. --cleanup allows to select different cleanup modes for tag message. It provides the same interface as --cleanup option in git-commit. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Kirill A. Shutemov committed Dec 7, 2011 at 05:01 UTC d3e05983306537c8ec911fc52092697ba80830fa
2 files changed +60 -14
Documentation/git-tag.txt
+7
@@ -99,6 +99,13 @@ OPTIONS
99 Implies `-a` if none of `-a`, `-s`, or `-u <key-id>`
100 is given.
101
102 +--cleanup=<mode>::
103 + This option sets how the tag message is cleaned up.
104 + The '<mode>' can be one of 'verbatim', 'whitespace' and 'strip'. The
105 + 'strip' mode is default. The 'verbatim' mode does not change message at
106 + all, 'whitespace' removes just leading/trailing whitespace lines and
107 + 'strip' removes both whitespace and commentary.
108 +
109 <tagname>::
110 The name of the tag to create, delete, or describe.
111 The new tag name must pass all checks defined by
builtin/tag.c
+53 -14
@@ -268,6 +268,15 @@ static const char tag_template[] =
268 N_("\n"
269 "#\n"
270 "# Write a tag message\n"
271 + "# Lines starting with '#' will be ignored.\n"
272 + "#\n");
273 +
274 +static const char tag_template_nocleanup[] =
275 + N_("\n"
276 + "#\n"
277 + "# Write a tag message\n"
278 + "# Lines starting with '#' will be kept; you may remove them"
279 + " yourself if you want to.\n"
280 "#\n");
281
282 static void set_signingkey(const char *value)
@@ -319,8 +328,18 @@ static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
328 return 0;
329 }
330
331 +struct create_tag_options {
332 + unsigned int message_given:1;
333 + unsigned int sign;
334 + enum {
335 + CLEANUP_NONE,
336 + CLEANUP_SPACE,
337 + CLEANUP_ALL
338 + } cleanup_mode;
339 +};
340 +
341 static void create_tag(const unsigned char *object, const char *tag,
323 - struct strbuf *buf, int message, int sign,
342 + struct strbuf *buf, struct create_tag_options *opt,
343 unsigned char *prev, unsigned char *result)
344 {
345 enum object_type type;
@@ -345,7 +364,7 @@ static void create_tag(const unsigned char *object, const char *tag,
364 if (header_len > sizeof(header_buf) - 1)
365 die(_("tag header too big."));
366
348 - if (!message) {
367 + if (!opt->message_given) {
368 int fd;
369
370 /* write the template message before editing: */
@@ -356,8 +375,12 @@ static void create_tag(const unsigned char *object, const char *tag,
375
376 if (!is_null_sha1(prev))
377 write_tag_body(fd, prev);
378 + else if (opt->cleanup_mode == CLEANUP_ALL)
379 + write_or_die(fd, _(tag_template),
380 + strlen(_(tag_template)));
381 else
360 - write_or_die(fd, _(tag_template), strlen(_(tag_template)));
382 + write_or_die(fd, _(tag_template_nocleanup),
383 + strlen(_(tag_template_nocleanup)));
384 close(fd);
385
386 if (launch_editor(path, buf, NULL)) {
@@ -367,14 +390,15 @@ static void create_tag(const unsigned char *object, const char *tag,
390 }
391 }
392
370 - stripspace(buf, 1);
393 + if (opt->cleanup_mode != CLEANUP_NONE)
394 + stripspace(buf, opt->cleanup_mode == CLEANUP_ALL);
395
372 - if (!message && !buf->len)
396 + if (!opt->message_given && !buf->len)
397 die(_("no tag message?"));
398
399 strbuf_insert(buf, 0, header_buf, header_len);
400
377 - if (build_tag_object(buf, sign, result) < 0) {
401 + if (build_tag_object(buf, opt->sign, result) < 0) {
402 if (path)
403 fprintf(stderr, _("The tag message has been left in %s\n"),
404 path);
@@ -422,9 +446,10 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
446 unsigned char object[20], prev[20];
447 const char *object_ref, *tag;
448 struct ref_lock *lock;
425 -
426 - int annotate = 0, sign = 0, force = 0, lines = -1,
427 - list = 0, delete = 0, verify = 0;
449 + struct create_tag_options opt;
450 + char *cleanup_arg = NULL;
451 + int annotate = 0, force = 0, lines = -1, list = 0,
452 + delete = 0, verify = 0;
453 const char *msgfile = NULL, *keyid = NULL;
454 struct msg_arg msg = { 0, STRBUF_INIT };
455 struct commit_list *with_commit = NULL;
@@ -442,7 +467,9 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
467 OPT_CALLBACK('m', "message", &msg, "message",
468 "tag message", parse_msg_arg),
469 OPT_FILENAME('F', "file", &msgfile, "read message from file"),
445 - OPT_BOOLEAN('s', "sign", &sign, "annotated and GPG-signed tag"),
470 + OPT_BOOLEAN('s', "sign", &opt.sign, "annotated and GPG-signed tag"),
471 + OPT_STRING(0, "cleanup", &cleanup_arg, "mode",
472 + "how to strip spaces and #comments from message"),
473 OPT_STRING('u', "local-user", &keyid, "key-id",
474 "use another key to sign the tag"),
475 OPT__FORCE(&force, "replace the tag if exists"),
@@ -459,13 +486,15 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
486
487 git_config(git_tag_config, NULL);
488
489 + memset(&opt, 0, sizeof(opt));
490 +
491 argc = parse_options(argc, argv, prefix, options, git_tag_usage, 0);
492
493 if (keyid) {
465 - sign = 1;
494 + opt.sign = 1;
495 set_signingkey(keyid);
496 }
468 - if (sign)
497 + if (opt.sign)
498 annotate = 1;
499 if (argc == 0 && !(delete || verify))
500 list = 1;
@@ -523,9 +552,19 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
552 else if (!force)
553 die(_("tag '%s' already exists"), tag);
554
555 + opt.message_given = msg.given || msgfile;
556 +
557 + if (!cleanup_arg || !strcmp(cleanup_arg, "strip"))
558 + opt.cleanup_mode = CLEANUP_ALL;
559 + else if (!strcmp(cleanup_arg, "verbatim"))
560 + opt.cleanup_mode = CLEANUP_NONE;
561 + else if (!strcmp(cleanup_arg, "whitespace"))
562 + opt.cleanup_mode = CLEANUP_SPACE;
563 + else
564 + die(_("Invalid cleanup mode %s"), cleanup_arg);
565 +
566 if (annotate)
527 - create_tag(object, tag, &buf, msg.given || msgfile,
528 - sign, prev, object);
567 + create_tag(object, tag, &buf, &opt, prev, object);
568
569 lock = lock_any_ref_for_update(ref.buf, prev, 0);
570 if (!lock)