Teach git-describe how to run name-rev
authorShawn O. Pearce <spearce@spearce.org>
Mon, 21 May 2007 07:20:25 +0000 (03:20 -0400)
committerJunio C Hamano <junkio@cox.net>
Tue, 22 May 2007 06:56:28 +0000 (23:56 -0700)
Often users want to know not which tagged version a commit came
after, but which tagged version a commit is contained within.
This latter task is the job of git-name-rev, but most users are
looking to git-describe to do the job.

Junio suggested we make `git describe --contains` run the correct
tool, `git name-rev`, and that's exactly what we do here.  The output
of name-rev was adjusted slightly through the new --name-only option,
allowing describe to execv into name-rev and maintain its current
output format.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
Documentation/git-describe.txt
Documentation/git-name-rev.txt
builtin-describe.c
builtin-name-rev.c

index 47a583d3a605d95fb860e6ea7142cebf374ec5aa..dc47b65ced36ac856ad23e2bebd3f3342b50471a 100644 (file)
@@ -8,7 +8,7 @@ git-describe - Show the most recent tag that is reachable from a commit
 
 SYNOPSIS
 --------
-'git-describe' [--all] [--tags] [--abbrev=<n>] <committish>...
+'git-describe' [--all] [--tags] [--contains] [--abbrev=<n>] <committish>...
 
 DESCRIPTION
 -----------
@@ -31,6 +31,11 @@ OPTIONS
        Instead of using only the annotated tags, use any tag
        found in `.git/refs/tags`.
 
+--contains::
+       Instead of finding the tag that predates the commit, find
+       the tag that comes after the commit, and thus contains it.
+       Automatically implies --tags.
+
 --abbrev=<n>::
        Instead of using the default 8 hexadecimal digits as the
        abbreviated object name, use <n> digits.
index d6c8bf800f4456ea63ff7d9b0c01b2d4f0d9d179..9a1645d29272d86a4b66cd96e7312e8380850891 100644 (file)
@@ -34,6 +34,13 @@ OPTIONS
        Read from stdin, append "(<rev_name>)" to all sha1's of nameable
        commits, and pass to stdout
 
+--name-only::
+       Instead of printing both the SHA-1 and the name, print only
+       the name.  If given with --tags the usual tag prefix of
+       "tags/" is also ommitted from the name, matching the output
+       of gitlink::git-describe[1] more closely.  This option
+       cannot be combined with --stdin.
+
 EXAMPLE
 -------
 
index 165917e40db78e7105a16d6e7a1653862a29fdc5..669110cb0645629ca5b152d8328aa91d63be1550 100644 (file)
@@ -3,6 +3,7 @@
 #include "tag.h"
 #include "refs.h"
 #include "builtin.h"
+#include "exec_cmd.h"
 
 #define SEEN           (1u<<0)
 #define MAX_TAGS       (FLAG_BITS - 1)
@@ -242,12 +243,15 @@ static void describe(const char *arg, int last_one)
 int cmd_describe(int argc, const char **argv, const char *prefix)
 {
        int i;
+       int contains = 0;
 
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
 
                if (*arg != '-')
                        break;
+               else if (!strcmp(arg, "--contains"))
+                       contains = 1;
                else if (!strcmp(arg, "--debug"))
                        debug = 1;
                else if (!strcmp(arg, "--all"))
@@ -272,6 +276,16 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 
        save_commit_buffer = 0;
 
+       if (contains) {
+               const char **args = xmalloc((4 + argc - i) * sizeof(char*));
+               args[0] = "name-rev";
+               args[1] = "--name-only";
+               args[2] = "--tags";
+               memcpy(args + 3, argv + i, (argc - i) * sizeof(char*));
+               args[3 + argc - i] = NULL;
+               return cmd_name_rev(3 + argc - i, args, prefix);
+       }
+
        if (argc <= i)
                describe("HEAD", 1);
        else
index ef1638590722017ad2cacca7ce30098fd0392bd5..a639e2feda26b658446719981ac22d6e3adbd3ac 100644 (file)
@@ -83,6 +83,7 @@ copy_data:
 
 struct name_ref_data {
        int tags_only;
+       int name_only;
        const char *ref_filter;
 };
 
@@ -110,6 +111,10 @@ static int name_ref(const char *path, const unsigned char *sha1, int flags, void
 
                if (!prefixcmp(path, "refs/heads/"))
                        path = path + 11;
+               else if (data->tags_only
+                   && data->name_only
+                   && !prefixcmp(path, "refs/tags/"))
+                       path = path + 10;
                else if (!prefixcmp(path, "refs/"))
                        path = path + 5;
 
@@ -149,7 +154,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
 {
        struct object_array revs = { 0, 0, NULL };
        int as_is = 0, all = 0, transform_stdin = 0;
-       struct name_ref_data data = { 0, NULL };
+       struct name_ref_data data = { 0, 0, NULL };
 
        git_config(git_default_config);
 
@@ -165,6 +170,9 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
                        if (!strcmp(*argv, "--")) {
                                as_is = 1;
                                continue;
+                       } else if (!strcmp(*argv, "--name-only")) {
+                               data.name_only = 1;
+                               continue;
                        } else if (!strcmp(*argv, "--tags")) {
                                data.tags_only = 1;
                                continue;
@@ -263,14 +271,17 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
                        struct object * obj = get_indexed_object(i);
                        if (!obj)
                                continue;
-                       printf("%s %s\n", sha1_to_hex(obj->sha1), get_rev_name(obj));
+                       if (!data.name_only)
+                               printf("%s ", sha1_to_hex(obj->sha1));
+                       printf("%s\n", get_rev_name(obj));
                }
        } else {
                int i;
-               for (i = 0; i < revs.nr; i++)
-                       printf("%s %s\n",
-                               revs.objects[i].name,
-                               get_rev_name(revs.objects[i].item));
+               for (i = 0; i < revs.nr; i++) {
+                       if (!data.name_only)
+                               printf("%s ", revs.objects[i].name);
+                       printf("%s\n", get_rev_name(revs.objects[i].item));
+               }
        }
 
        return 0;