When we are listing tags, we print each one as it is
processed by for_each_ref. We can't do that with --sort, of
course, as we need to see the whole list to sort. For the
--sort code path, we store each tag in a string_list, and
then print them all at the end.

This interacts badly with "-n", which needs not only the
name of the tag, but also the object itself. We simply
punted on handling this, and disallowed the combination.

This patch remedies that by storing the sha1 of each object
in the "util" field of the string list. We can then factor
out the printing to a helper function and call that function
either when we first see each tag, or after we have sorted.

Signed-off-by: Jeff King <p...@peff.net>
---
 builtin/tag.c  | 42 +++++++++++++++++++++++++-----------------
 cache.h        |  7 +++++++
 t/t7004-tag.sh | 18 ++++++++++++++++++
 3 files changed, 50 insertions(+), 17 deletions(-)

diff --git a/builtin/tag.c b/builtin/tag.c
index c6e8a71..2adfc3d 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -213,6 +213,18 @@ free_return:
        free(buf);
 }
 
+static void print_tag(const char *refname, const unsigned char *sha1,
+                     int lines)
+{
+               if (!lines)
+                       printf("%s\n", refname);
+               else {
+                       printf("%-15s ", refname);
+                       show_tag_lines(sha1, lines);
+                       putchar('\n');
+               }
+}
+
 static int show_reference(const char *refname, const unsigned char *sha1,
                          int flag, void *cb_data)
 {
@@ -232,16 +244,10 @@ static int show_reference(const char *refname, const 
unsigned char *sha1,
                if (points_at.nr && !match_points_at(refname, sha1))
                        return 0;
 
-               if (!filter->lines) {
-                       if (filter->sort)
-                               string_list_append(&filter->tags, refname);
-                       else
-                               printf("%s\n", refname);
-                       return 0;
-               }
-               printf("%-15s ", refname);
-               show_tag_lines(sha1, filter->lines);
-               putchar('\n');
+               if (filter->sort)
+                       string_list_append(&filter->tags, refname)->util = 
hashdup(sha1);
+               else
+                       print_tag(refname, sha1, filter->lines);
        }
 
        return 0;
@@ -273,12 +279,16 @@ static int list_tags(const char **patterns, int lines,
                        qsort(filter.tags.items, filter.tags.nr,
                              sizeof(struct string_list_item), sort_by_version);
                if (sort & REVERSE_SORT)
-                       for (i = filter.tags.nr - 1; i >= 0; i--)
-                               printf("%s\n", filter.tags.items[i].string);
+                       for (i = filter.tags.nr - 1; i >= 0; i--) {
+                               struct string_list_item *it = 
&filter.tags.items[i];
+                               print_tag(it->string, it->util, lines);
+                       }
                else
-                       for (i = 0; i < filter.tags.nr; i++)
-                               printf("%s\n", filter.tags.items[i].string);
-               string_list_clear(&filter.tags, 0);
+                       for (i = 0; i < filter.tags.nr; i++) {
+                               struct string_list_item *it = 
&filter.tags.items[i];
+                               print_tag(it->string, it->util, lines);
+                       }
+               string_list_clear(&filter.tags, 1);
        }
        return 0;
 }
@@ -634,8 +644,6 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
                        copts.padding = 2;
                        run_column_filter(colopts, &copts);
                }
-               if (lines != -1 && sort)
-                       die(_("--sort and -n are incompatible"));
                ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit, 
sort);
                if (column_active(colopts))
                        stop_column_filter();
diff --git a/cache.h b/cache.h
index df65231..74bf163 100644
--- a/cache.h
+++ b/cache.h
@@ -738,6 +738,13 @@ static inline void hashclr(unsigned char *hash)
        memset(hash, 0, 20);
 }
 
+static inline unsigned char *hashdup(const unsigned char *hash)
+{
+       unsigned char *ret = xmalloc(20);
+       hashcpy(ret, hash);
+       return ret;
+}
+
 #define EMPTY_TREE_SHA1_HEX \
        "4b825dc642cb6eb9a060e54bf8d69288fbee4904"
 #define EMPTY_TREE_SHA1_BIN_LITERAL \
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index e4ab0f5..279b932 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1423,6 +1423,24 @@ EOF
        test_cmp expect actual
 '
 
+test_expect_success 'sorting works with -n' '
+       cat >msg <<-\EOF &&
+       multiline
+       tag
+       message
+       EOF
+       git tag -F msg foo-long &&
+       git tag -l --sort=-refname -n2 "foo*" >actual &&
+       cat >expect <<-\EOF &&
+       foo1.6          Merge branch '\''master'\'' into stable
+       foo1.3          Merge branch '\''master'\'' into stable
+       foo1.10         Merge branch '\''master'\'' into stable
+       foo-long        multiline
+           tag
+       EOF
+       test_cmp expect actual
+'
+
 run_with_limited_stack () {
        (ulimit -s 64 && "$@")
 }
-- 
2.0.0.566.gfe3e6b2

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to