Code

Add "--patch" option to git-add--interactive
[git.git] / builtin-tag.c
index 82ebda11b02b2fd1fad3e3687832bb222e84f500..566b9d186fb8a20841cce23914643556c6c24382 100644 (file)
@@ -17,12 +17,9 @@ static const char builtin_tag_usage[] =
 
 static char signingkey[1000];
 
-static void launch_editor(const char *path, struct strbuf *buffer)
+void launch_editor(const char *path, struct strbuf *buffer)
 {
        const char *editor, *terminal;
-       struct child_process child;
-       const char *args[3];
-       int fd;
 
        editor = getenv("GIT_EDITOR");
        if (!editor && editor_program)
@@ -43,22 +40,16 @@ static void launch_editor(const char *path, struct strbuf *buffer)
        if (!editor)
                editor = "vi";
 
-       memset(&child, 0, sizeof(child));
-       child.argv = args;
-       args[0] = editor;
-       args[1] = path;
-       args[2] = NULL;
+       if (strcmp(editor, ":")) {
+               const char *args[] = { editor, path, NULL };
 
-       if (run_command(&child))
-               die("There was a problem with the editor %s.", editor);
-
-       fd = open(path, O_RDONLY);
-       if (fd < 0)
-               die("could not open '%s': %s", path, strerror(errno));
-       if (strbuf_read(buffer, fd, 0) < 0) {
-               die("could not read message file '%s': %s", path, strerror(errno));
+               if (run_command_v_opt(args, 0))
+                       die("There was a problem with the editor %s.", editor);
        }
-       close(fd);
+
+       if (strbuf_read_file(buffer, path, 0) < 0)
+               die("could not read message file '%s': %s",
+                   path, strerror(errno));
 }
 
 struct tag_filter {
@@ -86,17 +77,16 @@ static int show_reference(const char *refname, const unsigned char *sha1,
                }
                printf("%-15s ", refname);
 
-               sp = buf = read_sha1_file(sha1, &type, &size);
-               if (!buf)
+               buf = read_sha1_file(sha1, &type, &size);
+               if (!buf || !size)
                        return 0;
-               if (!size) {
+
+               /* skip header */
+               sp = strstr(buf, "\n\n");
+               if (!sp) {
                        free(buf);
                        return 0;
                }
-               /* skip header */
-               while (sp + 1 < buf + size &&
-                               !(sp[0] == '\n' && sp[1] == '\n'))
-                       sp++;
                /* only take up to "lines" lines, and strip the signature */
                for (i = 0, sp += 2;
                                i < filter->lines && sp < buf + size &&
@@ -252,9 +242,37 @@ static int git_tag_config(const char *var, const char *value)
        return git_default_config(var, value);
 }
 
+static void write_tag_body(int fd, const unsigned char *sha1)
+{
+       unsigned long size;
+       enum object_type type;
+       char *buf, *sp, *eob;
+       size_t len;
+
+       buf = read_sha1_file(sha1, &type, &size);
+       if (!buf)
+               return;
+       /* skip header */
+       sp = strstr(buf, "\n\n");
+
+       if (!sp || !size || type != OBJ_TAG) {
+               free(buf);
+               return;
+       }
+       sp += 2; /* skip the 2 LFs */
+       eob = strstr(sp, "\n" PGP_SIGNATURE "\n");
+       if (eob)
+               len = eob - sp;
+       else
+               len = buf + size - sp;
+       write_or_die(fd, sp, len);
+
+       free(buf);
+}
+
 static void create_tag(const unsigned char *object, const char *tag,
                       struct strbuf *buf, int message, int sign,
-                          unsigned char *result)
+                          unsigned char *prev, unsigned char *result)
 {
        enum object_type type;
        char header_buf[1024];
@@ -287,7 +305,11 @@ static void create_tag(const unsigned char *object, const char *tag,
                if (fd < 0)
                        die("could not create file '%s': %s",
                                                path, strerror(errno));
-               write_or_die(fd, tag_template, strlen(tag_template));
+
+               if (!is_null_sha1(prev))
+                       write_tag_body(fd, prev);
+               else
+                       write_or_die(fd, tag_template, strlen(tag_template));
                close(fd);
 
                launch_editor(path, buf);
@@ -296,14 +318,11 @@ static void create_tag(const unsigned char *object, const char *tag,
                free(path);
        }
 
-       strbuf_setlen(buf, stripspace(buf->buf, buf->len, 1));
+       stripspace(buf, 1);
 
        if (!message && !buf->len)
                die("no tag message?");
 
-       /* insert the header and add the '\n' if needed: */
-       if (buf->len)
-               strbuf_addch(buf, '\n');
        strbuf_insert(buf, 0, header_buf, header_len);
 
        if (sign && do_sign(buf) < 0)
@@ -364,8 +383,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                        continue;
                }
                if (!strcmp(arg, "-F")) {
-                       int fd;
-
                        annotate = 1;
                        i++;
                        if (i == argc)
@@ -373,17 +390,14 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                        if (message)
                                die("only one -F or -m option is allowed.");
 
-                       if (!strcmp(argv[i], "-"))
-                               fd = 0;
-                       else {
-                               fd = open(argv[i], O_RDONLY);
-                               if (fd < 0)
-                                       die("could not open '%s': %s",
+                       if (!strcmp(argv[i], "-")) {
+                               if (strbuf_read(&buf, 0, 1024) < 0)
+                                       die("cannot read %s", argv[i]);
+                       } else {
+                               if (strbuf_read_file(&buf, argv[i], 1024) < 0)
+                                       die("could not open or read '%s': %s",
                                                argv[i], strerror(errno));
                        }
-                       if (strbuf_read(&buf, fd, 1024) < 0) {
-                               die("cannot read %s", argv[i]);
-                       }
                        message = 1;
                        continue;
                }
@@ -432,7 +446,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                die("tag '%s' already exists", tag);
 
        if (annotate)
-               create_tag(object, tag, &buf, message, sign, object);
+               create_tag(object, tag, &buf, message, sign, prev, object);
 
        lock = lock_any_ref_for_update(ref, prev, 0);
        if (!lock)