real_path_internal(): add comment explaining use of cwd
[gitweb.git] / builtin / tag.c
index e377706e6d362792055b5e2a67efc12edd972e52..9c3e0673d5bd4e011c877c4d3a17975498265e22 100644 (file)
 #include "revision.h"
 #include "gpg-interface.h"
 #include "sha1-array.h"
+#include "column.h"
 
 static const char * const git_tag_usage[] = {
-       "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]",
-       "git tag -d <tagname>...",
-       "git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] "
-               "\n\t\t[<pattern>...]",
-       "git tag -v <tagname>...",
+       N_("git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]"),
+       N_("git tag -d <tagname>..."),
+       N_("git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] "
+               "\n\t\t[<pattern>...]"),
+       N_("git tag -v <tagname>..."),
        NULL
 };
 
@@ -33,6 +34,7 @@ struct tag_filter {
 };
 
 static struct sha1_array points_at;
+static unsigned int colopts;
 
 static int match_pattern(const char **patterns, const char *ref)
 {
@@ -105,18 +107,51 @@ static int contains(struct commit *candidate, const struct commit_list *want)
        return contains_recurse(candidate, want);
 }
 
+static void show_tag_lines(const unsigned char *sha1, int lines)
+{
+       int i;
+       unsigned long size;
+       enum object_type type;
+       char *buf, *sp, *eol;
+       size_t len;
+
+       buf = read_sha1_file(sha1, &type, &size);
+       if (!buf)
+               die_errno("unable to read object %s", sha1_to_hex(sha1));
+       if (type != OBJ_COMMIT && type != OBJ_TAG)
+               goto free_return;
+       if (!size)
+               die("an empty %s object %s?",
+                   typename(type), sha1_to_hex(sha1));
+
+       /* skip header */
+       sp = strstr(buf, "\n\n");
+       if (!sp)
+               goto free_return;
+
+       /* only take up to "lines" lines, and strip the signature from a tag */
+       if (type == OBJ_TAG)
+               size = parse_signature(buf, size);
+       for (i = 0, sp += 2; i < lines && sp < buf + size; i++) {
+               if (i)
+                       printf("\n    ");
+               eol = memchr(sp, '\n', size - (sp - buf));
+               len = eol ? eol - sp : size - (sp - buf);
+               fwrite(sp, len, 1, stdout);
+               if (!eol)
+                       break;
+               sp = eol + 1;
+       }
+free_return:
+       free(buf);
+}
+
 static int show_reference(const char *refname, const unsigned char *sha1,
                          int flag, void *cb_data)
 {
        struct tag_filter *filter = cb_data;
 
        if (match_pattern(filter->patterns, refname)) {
-               int i;
-               unsigned long size;
-               enum object_type type;
-               char *buf, *sp, *eol;
-               size_t len;
-
                if (filter->with_commit) {
                        struct commit *commit;
 
@@ -135,33 +170,8 @@ static int show_reference(const char *refname, const unsigned char *sha1,
                        return 0;
                }
                printf("%-15s ", refname);
-
-               buf = read_sha1_file(sha1, &type, &size);
-               if (!buf || !size)
-                       return 0;
-
-               /* skip header */
-               sp = strstr(buf, "\n\n");
-               if (!sp) {
-                       free(buf);
-                       return 0;
-               }
-               /* only take up to "lines" lines, and strip the signature */
-               size = parse_signature(buf, size);
-               for (i = 0, sp += 2;
-                               i < filter->lines && sp < buf + size;
-                               i++) {
-                       if (i)
-                               printf("\n    ");
-                       eol = memchr(sp, '\n', size - (sp - buf));
-                       len = eol ? eol - sp : size - (sp - buf);
-                       fwrite(sp, len, 1, stdout);
-                       if (!eol)
-                               break;
-                       sp = eol + 1;
-               }
+               show_tag_lines(sha1, filter->lines);
                putchar('\n');
-               free(buf);
        }
 
        return 0;
@@ -255,6 +265,8 @@ static int git_tag_config(const char *var, const char *value, void *cb)
        int status = git_gpg_config(var, value, cb);
        if (status)
                return status;
+       if (!prefixcmp(var, "column."))
+               return git_column_config(var, value, "tag", &colopts);
        return git_default_config(var, value, cb);
 }
 
@@ -320,7 +332,7 @@ static void create_tag(const unsigned char *object, const char *tag,
                          sha1_to_hex(object),
                          typename(type),
                          tag,
-                         git_committer_info(IDENT_ERROR_ON_NO_NAME));
+                         git_committer_info(IDENT_STRICT));
 
        if (header_len > sizeof(header_buf) - 1)
                die(_("tag header too big."));
@@ -432,36 +444,37 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
        struct msg_arg msg = { 0, STRBUF_INIT };
        struct commit_list *with_commit = NULL;
        struct option options[] = {
-               OPT_BOOLEAN('l', "list", &list, "list tag names"),
-               { OPTION_INTEGER, 'n', NULL, &lines, "n",
-                               "print <n> lines of each tag message",
+               OPT_BOOLEAN('l', "list", &list, N_("list tag names")),
+               { OPTION_INTEGER, 'n', NULL, &lines, N_("n"),
+                               N_("print <n> lines of each tag message"),
                                PARSE_OPT_OPTARG, NULL, 1 },
-               OPT_BOOLEAN('d', "delete", &delete, "delete tags"),
-               OPT_BOOLEAN('v', "verify", &verify, "verify tags"),
+               OPT_BOOLEAN('d', "delete", &delete, N_("delete tags")),
+               OPT_BOOLEAN('v', "verify", &verify, N_("verify tags")),
 
-               OPT_GROUP("Tag creation options"),
+               OPT_GROUP(N_("Tag creation options")),
                OPT_BOOLEAN('a', "annotate", &annotate,
-                                       "annotated tag, needs a message"),
-               OPT_CALLBACK('m', "message", &msg, "message",
-                            "tag message", parse_msg_arg),
-               OPT_FILENAME('F', "file", &msgfile, "read message from file"),
-               OPT_BOOLEAN('s', "sign", &opt.sign, "annotated and GPG-signed tag"),
-               OPT_STRING(0, "cleanup", &cleanup_arg, "mode",
-                       "how to strip spaces and #comments from message"),
-               OPT_STRING('u', "local-user", &keyid, "key-id",
-                                       "use another key to sign the tag"),
-               OPT__FORCE(&force, "replace the tag if exists"),
-
-               OPT_GROUP("Tag listing options"),
+                                       N_("annotated tag, needs a message")),
+               OPT_CALLBACK('m', "message", &msg, N_("message"),
+                            N_("tag message"), parse_msg_arg),
+               OPT_FILENAME('F', "file", &msgfile, N_("read message from file")),
+               OPT_BOOLEAN('s', "sign", &opt.sign, N_("annotated and GPG-signed tag")),
+               OPT_STRING(0, "cleanup", &cleanup_arg, N_("mode"),
+                       N_("how to strip spaces and #comments from message")),
+               OPT_STRING('u', "local-user", &keyid, N_("key id"),
+                                       N_("use another key to sign the tag")),
+               OPT__FORCE(&force, N_("replace the tag if exists")),
+               OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
+
+               OPT_GROUP(N_("Tag listing options")),
                {
-                       OPTION_CALLBACK, 0, "contains", &with_commit, "commit",
-                       "print only tags that contain the commit",
+                       OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
+                       N_("print only tags that contain the commit"),
                        PARSE_OPT_LASTARG_DEFAULT,
                        parse_opt_with_commit, (intptr_t)"HEAD",
                },
                {
-                       OPTION_CALLBACK, 0, "points-at", NULL, "object",
-                       "print only tags of the object", 0, parse_opt_points_at
+                       OPTION_CALLBACK, 0, "points-at", NULL, N_("object"),
+                       N_("print only tags of the object"), 0, parse_opt_points_at
                },
                OPT_END()
        };
@@ -487,9 +500,25 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 
        if (list + delete + verify > 1)
                usage_with_options(git_tag_usage, options);
-       if (list)
-               return list_tags(argv, lines == -1 ? 0 : lines,
-                                with_commit);
+       finalize_colopts(&colopts, -1);
+       if (list && lines != -1) {
+               if (explicitly_enable_column(colopts))
+                       die(_("--column and -n are incompatible"));
+               colopts = 0;
+       }
+       if (list) {
+               int ret;
+               if (column_active(colopts)) {
+                       struct column_options copts;
+                       memset(&copts, 0, sizeof(copts));
+                       copts.padding = 2;
+                       run_column_filter(colopts, &copts);
+               }
+               ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit);
+               if (column_active(colopts))
+                       stop_column_filter();
+               return ret;
+       }
        if (lines != -1)
                die(_("-n option is only allowed with -l."));
        if (with_commit)