{"thread":{"id":"8512","subject":"[PATCH] Port git-tag.sh to C.","startedAt":"2007-06-08T21:38:50Z","lastAt":"2007-06-08T22:39:20Z","messageCount":6,"participants":["Kristian Høgsberg","Johannes Schindelin","Carlos Rica","Matthijs Melchior"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"44382","messageId":"1181338730800-git-send-email-krh@redhat.com","threadId":"8512","inReplyTo":null,"subject":"[PATCH] Port git-tag.sh to C.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-06-08T21:38:50Z","receivedAt":"2007-06-08T21:38:50Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"A more or less straight-forward port of git-tag.sh to C.\n\nSigned-off-by: Kristian Høgsberg <krh@redhat.com>\n---\n\nThere's two behavioral changes here: git tag with no arguments behaves like\ngit branch with no arguments; it lists all tags.  The other change is\nan empty line in the tag message template to make it look more like the\ncommit message template.\n\ncheers,\nKristian\n \n\n Makefile      |    3 +-\n builtin-tag.c |  364 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n builtin.h     |    1 +\n git-tag.sh    |  183 -----------------------------\n git.c         |    1 +\n 5 files changed, 368 insertions(+), 184 deletions(-)\n create mode 100644 builtin-tag.c\n delete mode 100755 git-tag.sh\n\ndiff --git a/Makefile b/Makefile\nindex 0f75955..bb1bed1 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -205,7 +205,7 @@ SCRIPT_SH = \\\n \tgit-pull.sh git-rebase.sh \\\n \tgit-repack.sh git-request-pull.sh git-reset.sh \\\n \tgit-sh-setup.sh \\\n-\tgit-tag.sh git-verify-tag.sh \\\n+\tgit-verify-tag.sh \\\n \tgit-am.sh \\\n \tgit-merge.sh git-merge-stupid.sh git-merge-octopus.sh \\\n \tgit-merge-resolve.sh git-merge-ours.sh \\\n@@ -372,6 +372,7 @@ BUILTIN_OBJS = \\\n \tbuiltin-show-branch.o \\\n \tbuiltin-stripspace.o \\\n \tbuiltin-symbolic-ref.o \\\n+\tbuiltin-tag.o \\\n \tbuiltin-tar-tree.o \\\n \tbuiltin-unpack-objects.o \\\n \tbuiltin-update-index.o \\\ndiff --git a/builtin-tag.c b/builtin-tag.c\nnew file mode 100644\nindex 0000000..06eafc0\n--- /dev/null\n+++ b/builtin-tag.c\n@@ -0,0 +1,364 @@\n+/*\n+ * Builtin \"git tag\"\n+ *\n+ * Copyright (c) 2007 Kristian Høgsberg <krh@redhat.com>\n+ * Based on git-tag.sh and mktag.c by Linus Torvalds.\n+ */\n+\n+#include \"cache.h\"\n+#include \"refs.h\"\n+#include \"commit.h\"\n+#include \"builtin.h\"\n+#include \"tag.h\"\n+#include \"run-command.h\"\n+\n+static const char builtin_tag_usage[] =\n+  \"git-tag [-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg>] <tagname> [<head>]\";\n+\n+static char signingkey[1000];\n+\n+static int launch_editor(const char *path, const char *template,\n+\t\t\t  char *buffer, size_t size)\n+{\n+\tstruct child_process child;\n+\tconst char *editor;\n+\tconst char *args[3];\n+\tchar *eol;\n+\tint len, fd, blank_lines, i, j;\n+\n+\tfd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0644);\n+\tif (fd < 0)\n+\t\tdie(\"could not create file %s.\", path);\n+\n+\tlen = strlen(template);\n+\twrite_or_die(fd, template, len);\n+\tclose(fd);\n+\n+\teditor = getenv(\"VISUAL\");\n+\tif (!editor)\n+\t\teditor = getenv(\"EDITOR\");\n+\tif (!editor)\n+\t\teditor = \"vi\";\n+\t    \n+\tmemset(&child, 0, sizeof(child));\n+\tchild.argv = args;\n+\targs[0] = editor;\n+\targs[1] = path;\n+\targs[2] = NULL;\n+\n+\tif (run_command(&child))\n+\t\tdie(\"could not launch editor %s.\", editor);\n+\n+\tfd = open(path, O_RDONLY, 0644);\n+\tif (fd == -1)\n+\t\tdie(\"could not read %s.\", path);\n+\tlen = read_in_full(fd, buffer, size);\n+\tif (len < 0)\n+\t\tdie(\"failed to read '%s', %m\", path);\n+\tclose(fd);\n+\n+\tblank_lines = 1;\n+\tfor (i = 0, j = 0; i < len; i++) {\n+\t\tif (blank_lines > 0 && buffer[i] == '#') {\n+\t\t\teol = strchr(buffer + i, '\\n');\n+\t\t\tif (!eol)\n+\t\t\t\tbreak;\n+\n+\t\t\ti = eol - buffer;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (buffer[i] == '\\n') {\n+\t\t\tblank_lines++;\n+\t\t\tif (blank_lines > 1)\n+\t\t\t\tcontinue;\n+\t\t} else {\n+\t\t\tif (blank_lines > 2)\n+\t\t\t\tbuffer[j++] = '\\n';\n+\t\t\tblank_lines = 0;\n+\t\t}\n+\n+\t\tbuffer[j++] = buffer[i];\n+\t}\n+\n+\tif (buffer[j - 1] != '\\n')\n+\t\tbuffer[j++] = '\\n';\n+\n+\tunlink(path);\n+\n+\treturn j;\n+}\n+\n+static int show_reference(const char *refname, const unsigned char *sha1,\n+\t\t\t  int flag, void *cb_data)\n+{\n+\tconst char *pattern = cb_data;\n+\n+\tif (pattern == NULL || !fnmatch(pattern, refname, 0))\n+\t\tprintf(\"%s\\n\", refname);\n+\n+\treturn 0;\n+}\n+\n+static int list_tags(const char *pattern)\n+{\n+\tfor_each_tag_ref(show_reference, (void *) pattern);\n+\n+\treturn 0;\n+}\n+\n+\n+static int delete_tags(const char **argv)\n+{\n+\tconst char **p;\n+\tchar ref[PATH_MAX];\n+\tint had_error = 0;\n+\tunsigned char sha1[20];\n+\n+\tfor (p = argv; *p; p++) {\n+\t\tif (snprintf(ref, sizeof ref, \"refs/tags/%s\", *p) > sizeof ref)\n+\t\t\tdie(\"tag name '%s' too long.\", *p);\n+\t\tif (!resolve_ref(ref, sha1, 1, NULL)) {\n+\t\t\tfprintf(stderr, \"tag '%s' not found.\\n\", *p);\n+\t\t\thad_error = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (!delete_ref(ref, sha1))\n+\t\t\tprintf(\"Deleted tag '%s'\\n\", *p);\n+\t}\n+\t\t\t\n+\treturn had_error;\n+}\n+\n+static int verify_tags(const char **argv)\n+{\n+\tconst char **p;\n+\tchar ref[PATH_MAX];\n+\tint had_error = 0;\n+\tunsigned char sha1[20];\n+\n+\tfor (p = argv; *p; p++) {\n+\t\tif (snprintf(ref, sizeof ref, \"refs/tags/%s\", *p) > sizeof ref)\n+\t\t\tdie(\"tag name '%s' too long.\", *p);\n+\n+\t\tif (!resolve_ref(ref, sha1, 1, NULL)) {\n+\t\t\tfprintf(stderr, \"tag '%s' not found.\\n\", *p);\n+\t\t\thad_error = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tprintf(\"FIXME: verify tag '%s'\\n\", *p);\n+\t}\n+\n+\treturn had_error;\n+}\n+\n+static int do_sign(char *buffer, size_t size, size_t max)\n+{\n+\tstruct child_process gpg;\n+\tconst char *args[5];\n+\tchar *bracket;\n+\tint len;\n+\n+\tif (signingkey[0] == '\\0') {\n+\t\tstrlcpy(signingkey, git_committer_info(1), sizeof signingkey);\n+\t\tbracket = strchr(signingkey, '>');\n+\t\tif (bracket)\n+\t\t\tbracket[1] = '\\0';\n+\t}\n+\n+\tmemset(&gpg, 0, sizeof(gpg));\n+\tgpg.argv = args;\n+\tgpg.in = -1;\n+\tgpg.out = -1;\n+\targs[0] = \"gpg\";\n+\targs[1] = \"-bsa\";\n+\targs[2] = \"-u\";\n+\targs[3] = signingkey;\n+\targs[4] = NULL;\n+\t\t\n+\tif (start_command(&gpg))\n+\t\tdie(\"could not run gpg.\");\n+\n+\twrite_or_die(gpg.in, buffer, size);\n+\tclose(gpg.in);\n+\tgpg.close_in = 0;\n+\tlen = read_in_full(gpg.out, buffer + size, max - size);\n+\n+\tfinish_command(&gpg);\n+\n+\treturn size + len;\n+}\n+\n+static const char tag_template[] =\n+\t\"\\n\"\n+\t\"#\\n\"\n+\t\"# Write a tag message\\n\"\n+\t\"#\\n\";\n+\n+int git_tag_config(const char *var, const char *value)\n+{\n+\tif (!strcmp(var, \"user.signingkey\")) {\n+\t\tif (!value)\n+\t\t\tdie(\"user.signingkey without value\");\n+\t\tstrlcpy(signingkey, value, sizeof signingkey);\n+\t\treturn 0;\n+\t}\n+\n+\treturn git_default_config(var, value);\n+}\n+\n+int cmd_tag(int argc, const char **argv, const char *prefix)\n+{\n+\tchar buffer[4096];\n+\tunsigned char object[20], prev[20], result[20];\n+\tint annotate = 0, is_signed = 0, force = 0, lines = 0;\n+\tconst char *message = NULL;\n+\tchar ref[PATH_MAX];\n+\tconst char *object_ref, *tag;\n+\tint i, body, header, total, fd;\n+\tenum object_type type;\n+\tstruct ref_lock *lock;\n+\n+\tgit_config(git_tag_config);\n+\n+\tfor (i = 1; i < argc; i++) {\n+\t\tconst char *arg = argv[i];\n+\n+\t\tif (arg[0] != '-')\n+\t\t\tbreak;\n+\t\tif (!strcmp(arg, \"-a\")) {\n+\t\t\tannotate = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-s\")) {\n+\t\t\tannotate = 1;\n+\t\t\tis_signed = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-f\")) {\n+\t\t\tforce = 1;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-n\")) {\n+\t\t\tif (i + 1 == argc || *argv[i + 1] == '-')\n+\t\t\t\t/* no argument */\n+\t\t\t\tlines = 1;\n+\t\t\telse\n+\t\t\t\t/* FIXME, fallback to 1 on invalid integer */\n+\t\t\t\tlines = atoi(argv[i + 1]);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-m\")) {\n+\t\t\tannotate = 1;\n+\t\t\ti++;\n+\t\t\tif  (i == argc)\n+\t\t\t\tdie(\"option -m needs an argument.\");\n+\t\t\tmessage = argv[i];\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-F\")) {\n+\t\t\tannotate = 1;\n+\t\t\ti++;\n+\t\t\tif  (i == argc)\n+\t\t\t\tdie(\"option -F needs an argument.\");\n+\n+\t\t\tfd = open(argv[i], O_RDONLY);\n+\t\t\tif (fd < 0)\n+\t\t\t\tdie(\"cannot open %s\", argv[1]);\n+\n+\t\t\tmessage = xmalloc(4096);\n+\t\t\tif (read_in_full(fd, (char *) message, 4096) < 0)\n+\t\t\t\tdie(\"cannot read %s\", argv[1]);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-u\")) {\n+\t\t\tannotate = 1;\n+\t\t\tis_signed = 1;\n+\t\t\ti++;\n+\t\t\tif  (i == argc)\n+\t\t\t\tdie(\"option -u needs an argument.\");\n+\t\t\tstrlcpy(signingkey, argv[i], sizeof signingkey);\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (!strcmp(arg, \"-l\")) {\n+\t\t\treturn list_tags(argv[i + 1]);\n+\t\t}\n+\t\tif (!strcmp(arg, \"-d\")) {\n+\t\t\treturn delete_tags(argv + i + 1);\n+\t\t}\n+\t\tif (!strcmp(arg, \"-v\")) {\n+\t\t\treturn verify_tags(argv + i + 1);\n+\t\t}\n+\t\tusage(builtin_tag_usage);\n+\t}\n+\n+\tif (i == argc)\n+\t\treturn list_tags(NULL);\n+\ttag = argv[i++];\n+\n+\tif (i < argc)\n+\t\tobject_ref = argv[i];\n+\telse\n+\t\tobject_ref = \"HEAD\";\n+\n+\tif (get_sha1(object_ref, object))\n+\t\tdie(\"Failed to resolve '%s' as a valid ref.\", object_ref);\n+\n+\tif (snprintf(ref, sizeof ref, \"refs/tags/%s\", tag) > sizeof ref)\n+\t\tdie(\"tag '%s' too long.\", tag);\n+\tif (check_ref_format(ref))\n+\t\tdie(\"'%s' is not a valid tag name.\", tag);\n+\tif (resolve_ref(ref, prev, 1, NULL)) {\n+\t\tif (!force)\n+\t\t\tdie(\"tag '%s' already exists\", tag);\n+\t} else {\n+\t\thashclr(prev);\n+\t}\n+\n+\ttype = sha1_object_info(object, NULL);\n+\tif (type <= 0)\n+\t    die(\"bad object type.\");\n+\n+\theader = snprintf(buffer, sizeof buffer,\n+\t\t\t  \"object %s\\n\"\n+\t\t\t  \"type %s\\n\"\n+\t\t\t  \"tag %s\\n\"\n+\t\t\t  \"tagger %s\\n\\n\",\n+\t\t\t  sha1_to_hex(object),\n+\t\t\t  typename(type),\n+\t\t\t  tag,\n+\t\t\t  git_committer_info(1));\n+\n+\tif (annotate && message == NULL)\n+\t\tbody = launch_editor(git_path(\"TAGMSG\"), tag_template,\n+\t\t\t\t     buffer + header, sizeof buffer - header);\n+\telse if (annotate)\n+\t\tbody = snprintf(buffer + header, sizeof buffer - header,\n+\t\t\t\t\"%s\\n\", message);\n+\telse\n+\t\tbody = 0;\n+\n+\tif (annotate && body == 0)\n+\t\tdie(\"no tag message?\");\n+\n+\tif (header + body > sizeof buffer)\n+\t\tdie(\"tag message too big.\");\n+\n+\tif (is_signed)\n+\t\ttotal = do_sign(buffer, header + body, sizeof buffer);\n+\telse\n+\t\ttotal = header + body;\n+\n+\tif (write_sha1_file(buffer, total, tag_type, result) < 0)\n+\t\tdie(\"unable to write tag file\");\n+\n+\tlock = lock_any_ref_for_update(ref, prev, 0);\n+\tif (!lock)\n+\t\tdie(\"%s: cannot lock the ref\", ref);\n+\tif (write_ref_sha1(lock, result, NULL) < 0)\n+\t\tdie(\"%s: cannot update the ref\", ref);\n+\n+\treturn 0;\n+}\ndiff --git a/builtin.h b/builtin.h\nindex 39290d1..91166e1 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -72,6 +72,7 @@ extern int cmd_show(int argc, const char **argv, const char *prefix);\n extern int cmd_show_branch(int argc, const char **argv, const char *prefix);\n extern int cmd_stripspace(int argc, const char **argv, const char *prefix);\n extern int cmd_symbolic_ref(int argc, const char **argv, const char *prefix);\n+extern int cmd_tag(int argc, const char **argv, const char *prefix);\n extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);\n extern int cmd_unpack_objects(int argc, const char **argv, const char *prefix);\n extern int cmd_update_index(int argc, const char **argv, const char *prefix);\ndiff --git a/git-tag.sh b/git-tag.sh\ndeleted file mode 100755\nindex 37cee97..0000000\n--- a/git-tag.sh\n+++ /dev/null\n@@ -1,183 +0,0 @@\n-#!/bin/sh\n-# Copyright (c) 2005 Linus Torvalds\n-\n-USAGE='[-n [<num>]] -l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg>] <tagname> [<head>]'\n-SUBDIRECTORY_OK='Yes'\n-. git-sh-setup\n-\n-message_given=\n-annotate=\n-signed=\n-force=\n-message=\n-username=\n-list=\n-verify=\n-LINES=0\n-while case \"$#\" in 0) break ;; esac\n-do\n-    case \"$1\" in\n-    -a)\n-\tannotate=1\n-\t;;\n-    -s)\n-\tannotate=1\n-\tsigned=1\n-\t;;\n-    -f)\n-\tforce=1\n-\t;;\n-    -n)\n-        case $2 in\n-\t-*)\tLINES=1 \t# no argument\n-\t\t;;\n-\t*)\tshift\n-\t\tLINES=$(expr \"$1\" : '\\([0-9]*\\)')\n-\t\t[ -z \"$LINES\" ] && LINES=1 # 1 line is default when -n is used\n-\t\t;;\n-\tesac\n-\t;;\n-    -l)\n-\tlist=1\n-\tshift\n-\tPATTERN=\"$1\"\t# select tags by shell pattern, not re\n-\tgit rev-parse --symbolic --tags | sort |\n-\t    while read TAG\n-\t    do\n-\t        case \"$TAG\" in\n-\t\t*$PATTERN*) ;;\n-\t\t*)\t    continue ;;\n-\t\tesac\n-\t\t[ \"$LINES\" -le 0 ] && { echo \"$TAG\"; continue ;}\n-\t\tOBJTYPE=$(git cat-file -t \"$TAG\")\n-\t\tcase $OBJTYPE in\n-\t\ttag)\tANNOTATION=$(git cat-file tag \"$TAG\" |\n-\t\t\t\t       sed -e '1,/^$/d' \\\n-\t\t\t\t\t   -e '/^-----BEGIN PGP SIGNATURE-----$/Q' )\n-\t\t\tprintf \"%-15s %s\\n\" \"$TAG\" \"$ANNOTATION\" |\n-\t\t\t  sed -e '2,$s/^/    /' \\\n-\t\t\t      -e \"${LINES}q\"\n-\t\t\t;;\n-\t\t*)      echo \"$TAG\"\n-\t\t\t;;\n-\t\tesac\n-\t    done\n-\t;;\n-    -m)\n-    \tannotate=1\n-\tshift\n-\tmessage=\"$1\"\n-\tif test \"$#\" = \"0\"; then\n-\t    die \"error: option -m needs an argument\"\n-\telse\n-\t    message_given=1\n-\tfi\n-\t;;\n-    -F)\n-\tannotate=1\n-\tshift\n-\tif test \"$#\" = \"0\"; then\n-\t    die \"error: option -F needs an argument\"\n-\telse\n-\t    message=\"$(cat \"$1\")\"\n-\t    message_given=1\n-\tfi\n-\t;;\n-    -u)\n-\tannotate=1\n-\tsigned=1\n-\tshift\n-\tusername=\"$1\"\n-\t;;\n-    -d)\n-    \tshift\n-\thad_error=0\n-\tfor tag\n-\tdo\n-\t\tcur=$(git-show-ref --verify --hash -- \"refs/tags/$tag\") || {\n-\t\t\techo >&2 \"Seriously, what tag are you talking about?\"\n-\t\t\thad_error=1\n-\t\t\tcontinue\n-\t\t}\n-\t\tgit-update-ref -m 'tag: delete' -d \"refs/tags/$tag\" \"$cur\" || {\n-\t\t\thad_error=1\n-\t\t\tcontinue\n-\t\t}\n-\t\techo \"Deleted tag $tag.\"\n-\tdone\n-\texit $had_error\n-\t;;\n-    -v)\n-\tshift\n-\ttag_name=\"$1\"\n-\ttag=$(git-show-ref --verify --hash -- \"refs/tags/$tag_name\") ||\n-\t\tdie \"Seriously, what tag are you talking about?\"\n-\tgit-verify-tag -v \"$tag\"\n-\texit $?\n-\t;;\n-    -*)\n-        usage\n-\t;;\n-    *)\n-\tbreak\n-\t;;\n-    esac\n-    shift\n-done\n-\n-[ -n \"$list\" ] && exit 0\n-\n-name=\"$1\"\n-[ \"$name\" ] || usage\n-prev=0000000000000000000000000000000000000000\n-if git-show-ref --verify --quiet -- \"refs/tags/$name\"\n-then\n-    test -n \"$force\" || die \"tag '$name' already exists\"\n-    prev=`git rev-parse \"refs/tags/$name\"`\n-fi\n-shift\n-git-check-ref-format \"tags/$name\" ||\n-\tdie \"we do not like '$name' as a tag name.\"\n-\n-object=$(git-rev-parse --verify --default HEAD \"$@\") || exit 1\n-type=$(git-cat-file -t $object) || exit 1\n-tagger=$(git-var GIT_COMMITTER_IDENT) || exit 1\n-\n-test -n \"$username\" ||\n-\tusername=$(git-repo-config user.signingkey) ||\n-\tusername=$(expr \"z$tagger\" : 'z\\(.*>\\)')\n-\n-trap 'rm -f \"$GIT_DIR\"/TAG_TMP* \"$GIT_DIR\"/TAG_FINALMSG \"$GIT_DIR\"/TAG_EDITMSG' 0\n-\n-if [ \"$annotate\" ]; then\n-    if [ -z \"$message_given\" ]; then\n-        ( echo \"#\"\n-          echo \"# Write a tag message\"\n-          echo \"#\" ) > \"$GIT_DIR\"/TAG_EDITMSG\n-        ${VISUAL:-${EDITOR:-vi}} \"$GIT_DIR\"/TAG_EDITMSG || exit\n-    else\n-        printf '%s\\n' \"$message\" >\"$GIT_DIR\"/TAG_EDITMSG\n-    fi\n-\n-    grep -v '^#' <\"$GIT_DIR\"/TAG_EDITMSG |\n-    git-stripspace >\"$GIT_DIR\"/TAG_FINALMSG\n-\n-    [ -s \"$GIT_DIR\"/TAG_FINALMSG -o -n \"$message_given\" ] || {\n-\techo >&2 \"No tag message?\"\n-\texit 1\n-    }\n-\n-    ( printf 'object %s\\ntype %s\\ntag %s\\ntagger %s\\n\\n' \\\n-\t\"$object\" \"$type\" \"$name\" \"$tagger\";\n-      cat \"$GIT_DIR\"/TAG_FINALMSG ) >\"$GIT_DIR\"/TAG_TMP\n-    rm -f \"$GIT_DIR\"/TAG_TMP.asc \"$GIT_DIR\"/TAG_FINALMSG\n-    if [ \"$signed\" ]; then\n-\tgpg -bsa -u \"$username\" \"$GIT_DIR\"/TAG_TMP &&\n-\tcat \"$GIT_DIR\"/TAG_TMP.asc >>\"$GIT_DIR\"/TAG_TMP ||\n-\tdie \"failed to sign the tag with GPG.\"\n-    fi\n-    object=$(git-mktag < \"$GIT_DIR\"/TAG_TMP)\n-fi\n-\n-git update-ref \"refs/tags/$name\" \"$object\" \"$prev\"\n-\ndiff --git a/git.c b/git.c\nindex 29b55a1..c9c20fb 100644\n--- a/git.c\n+++ b/git.c\n@@ -285,6 +285,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)\n \t\t{ \"show\", cmd_show, RUN_SETUP | USE_PAGER },\n \t\t{ \"stripspace\", cmd_stripspace },\n \t\t{ \"symbolic-ref\", cmd_symbolic_ref, RUN_SETUP },\n+\t\t{ \"tag\", cmd_tag, RUN_SETUP },\n \t\t{ \"tar-tree\", cmd_tar_tree },\n \t\t{ \"unpack-objects\", cmd_unpack_objects, RUN_SETUP },\n \t\t{ \"update-index\", cmd_update_index, RUN_SETUP },\n-- \n1.5.2.1.134.g447c2\n"},{"id":"44383","messageId":"Pine.LNX.4.64.0706082249040.4059@racer.site","threadId":"8512","inReplyTo":"1181338730800-git-send-email-krh@redhat.com","subject":"Re: [PATCH] Port git-tag.sh to C.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-06-08T21:51:15Z","receivedAt":"2007-06-08T21:51:15Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 8 Jun 2007, Kristian Høgsberg wrote:\n\n> A more or less straight-forward port of git-tag.sh to C.\n\nIt is somewhat unfortunate that you did not say that you were working on \nthis stuff; we have a Google Summer of Code project going on, which tries \nto port many scripts to builtins.\n\nAs it happens, I am working with jasam on exactly the same script.\n\nPity,\nDscho\n"},{"id":"44385","messageId":"1181340320.30683.30.camel@hinata.boston.redhat.com","threadId":"8512","inReplyTo":"Pine.LNX.4.64.0706082249040.4059@racer.site","subject":"Re: [PATCH] Port git-tag.sh to C.","fromName":"Kristian Høgsberg","fromEmail":"krh@redhat.com","sentAt":"2007-06-08T22:05:20Z","receivedAt":"2007-06-08T22:05:20Z","isPatch":true,"sender":{"key":"krh@redhat.com","avatar":"https://gravatar.com/avatar/763dee6f9594ac474f725b137a39565792928e583ddf59b32befc2907409027e?d=mp&s=160"},"body":"On Fri, 2007-06-08 at 22:51 +0100, Johannes Schindelin wrote:\n> Hi,\n> \n> On Fri, 8 Jun 2007, Kristian Høgsberg wrote:\n> \n> > A more or less straight-forward port of git-tag.sh to C.\n> \n> It is somewhat unfortunate that you did not say that you were working on \n> this stuff; we have a Google Summer of Code project going on, which tries \n> to port many scripts to builtins.\n\nUgh, yeah... wasted effort...  I didn't see anything about the SoC\nproject on the list and I didn't pre-announce my work because I only\nspent little more than half a day...\n\n> As it happens, I am working with jasam on exactly the same script.\n\nHm... not sure how to resolve this.  FWIW, I'm going to send an updated\nversion of the patch that should also pass the test suite.  The previous\nversion always only creates annotated tags.\n\nKristian\n"},{"id":"44386","messageId":"Pine.LNX.4.64.0706082305490.4059@racer.site","threadId":"8512","inReplyTo":"1181340320.30683.30.camel@hinata.boston.redhat.com","subject":"Re: [PATCH] Port git-tag.sh to C.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-06-08T22:07:49Z","receivedAt":"2007-06-08T22:07:49Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 8 Jun 2007, Kristian H�gsberg wrote:\n\n> FWIW, I'm going to send an updated version of the patch that should also \n> pass the test suite.  The previous version always only creates annotated \n> tags.\n\nAs it happens, jasam also worked on a relatively extensive test script.\n\nYou might want to test it:\n\n\thttp://repo.or.cz/w/git/builtin-gsoc.git\n\nBranch is \"builtin-tag\", the test script is t/t7400-tag.sh.\n\nCiao,\nDscho\n\n"},{"id":"44390","messageId":"1b46aba20706081536p6511e561x9a3134b1af1cb0a@mail.gmail.com","threadId":"8512","inReplyTo":"1181340320.30683.30.camel@hinata.boston.redhat.com","subject":"Re: [PATCH] Port git-tag.sh to C.","fromName":"Carlos Rica","fromEmail":"jasampler@gmail.com","sentAt":"2007-06-08T22:36:38Z","receivedAt":"2007-06-08T22:36:38Z","isPatch":true,"sender":{"key":"jasampler@gmail.com","avatar":null},"body":"2007/6/9, Kristian Høgsberg <krh@redhat.com>:\n> Ugh, yeah... wasted effort...  I didn't see anything about the SoC\n> project on the list and I didn't pre-announce my work because I only\n> spent little more than half a day...\n\nSorry, it should have been announced before this could happen.\n\n> > As it happens, I am working with jasam on exactly the same script.\n\nWe were doing a conservative work to get exactly the same options\nand behaviour that git-tag.sh does. The work is now almost finished,\nso you could help us comparing the two versions to see how could\nend with a better git-tag. It would be fantastic if we could point what\nparts of my code can be enhanced with those of yours.\n\nMy test suite can also be run against the git-tag.sh code now, you\ncan check check your code with it. Feel free to say everything you want\nabout it!\n\nCarlos\n"},{"id":"44392","messageId":"4669DA98.9070603@xs4all.nl","threadId":"8512","inReplyTo":"Pine.LNX.4.64.0706082249040.4059@racer.site","subject":"Re: [PATCH] Port git-tag.sh to C.","fromName":"Matthijs Melchior","fromEmail":"mmelchior@xs4all.nl","sentAt":"2007-06-08T22:39:20Z","receivedAt":"2007-06-08T22:39:20Z","isPatch":true,"sender":{"key":"mmelchior@xs4all.nl","avatar":null},"body":"Hi,\n\nJohannes Schindelin wrote:\n> Hi,\n> \n> On Fri, 8 Jun 2007, Kristian Høgsberg wrote:\n> \n>> A more or less straight-forward port of git-tag.sh to C.\n> \n> It is somewhat unfortunate that you did not say that you were working on \n> this stuff; we have a Google Summer of Code project going on, which tries \n> to port many scripts to builtins.\n> \n> As it happens, I am working with jasam on exactly the same script.\n> \n> Pity,\n> Dscho\n\nPlease consider the idea of showing (part of) the tag annotation with\ngit-tag as well.\n\nSee message archived at:\n   http://permalink.gmane.org/gmane.comp.version-control.git/48962\n\nThanks,\n\tMatthijs Melchior.\n"}]}