git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] tag: support --sort=version

From
Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Date
Feb 19, 2014, 13:39 UTC
Message-ID
<1392817167-29802-1-git-send-email-pclouds@gmail.com>

--sort=version sorts tags as versions. GNU extension's strverscmp is used and no real compat implementation is provided so this is Linux only.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 I didn't know that coreutils' sort is simply a wrapper of strverscmp.
 With that GNU extension, implementing --sort is easy. Mac and Windows
 are welcome to reimplement strverscmp (of rip it off glibc).
 Documentation/git-tag.txt |  4 ++++
 builtin/tag.c             | 49 ++++++++++++++++++++++++++++++++++++++++++-----
 git-compat-util.h         |  7 +++++++
 3 files changed, 55 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 404257d..fc23dc0 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -95,6 +95,10 @@ OPTIONS
 	using fnmatch(3)).  Multiple patterns may be given; if any of
 	them matches, the tag is shown.
 
+--sort=<type>::
+	Sort in a specific order. Supported type is "version". Prepend
+	"-" to revert sort order.
+
 --column[=<options>]::
 --no-column::
 	Display tag listing in columns. See configuration variable
diff --git a/builtin/tag.c b/builtin/tag.c
index 74d3780..db3567b 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -30,6 +30,8 @@ static const char * const git_tag_usage[] = {
 struct tag_filter {
 	const char **patterns;
 	int lines;
+	int version_sort;
+	struct string_list tags;
 	struct commit_list *with_commit;
 };
 
@@ -166,7 +168,10 @@ static int show_reference(const char *refname, const unsigned char *sha1,
 			return 0;
 
 		if (!filter->lines) {
-			printf("%s\n", refname);
+			if (filter->version_sort)
+				string_list_append(&filter->tags, refname);
+			else
+				printf("%s\n", refname);
 			return 0;
 		}
 		printf("%-15s ", refname);
@@ -177,17 +182,38 @@ static int show_reference(const char *refname, const unsigned char *sha1,
 	return 0;
 }
 
+static int sort_by_version(const void *a_, const void *b_)
+{
+	const struct string_list_item *a = a_;
+	const struct string_list_item *b = b_;
+	return strverscmp(a->string, b->string);
+}
+
 static int list_tags(const char **patterns, int lines,
-			struct commit_list *with_commit)
+		     struct commit_list *with_commit, int version_sort)
 {
 	struct tag_filter filter;
 
 	filter.patterns = patterns;
 	filter.lines = lines;
+	filter.version_sort = version_sort;
 	filter.with_commit = with_commit;
+	memset(&filter.tags, 0, sizeof(filter.tags));
+	filter.tags.strdup_strings = 1;
 
 	for_each_tag_ref(show_reference, (void *) &filter);
-
+	if (version_sort) {
+		int i;
+		qsort(filter.tags.items, filter.tags.nr,
+		      sizeof(struct string_list_item), sort_by_version);
+		if (version_sort > 0)
+			for (i = 0; i < filter.tags.nr; i++)
+				printf("%s\n", filter.tags.items[i].string);
+		else
+			for (i = filter.tags.nr - 1; i >= 0; i--)
+				printf("%s\n", filter.tags.items[i].string);
+		string_list_clear(&filter.tags, 0);
+	}
 	return 0;
 }
 
@@ -437,7 +463,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 	struct create_tag_options opt;
 	char *cleanup_arg = NULL;
 	int annotate = 0, force = 0, lines = -1;
-	int cmdmode = 0;
+	int cmdmode = 0, version_sort = 0;
+	const char *sort = NULL;
 	const char *msgfile = NULL, *keyid = NULL;
 	struct msg_arg msg = { 0, STRBUF_INIT };
 	struct commit_list *with_commit = NULL;
@@ -462,6 +489,7 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 					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_STRING(0, "sort", &sort, N_("type"), N_("sort tags")),
 
 		OPT_GROUP(N_("Tag listing options")),
 		{
@@ -509,7 +537,18 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
 			copts.padding = 2;
 			run_column_filter(colopts, &copts);
 		}
-		ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit);
+		if (sort) {
+			if (!strcmp(sort, "version"))
+				version_sort = 1;
+			else if (!strcmp(sort, "-version"))
+				version_sort = -1;
+			else
+				die(_("unsupported sort type %s"), sort);
+		}
+		if (lines != -1 && version_sort)
+			die(_("--sort and -l are incompatible"));
+		ret = list_tags(argv, lines == -1 ? 0 : lines, with_commit,
+				version_sort);
 		if (column_active(colopts))
 			stop_column_filter();
 		return ret;
diff --git a/git-compat-util.h b/git-compat-util.h
index cbd86c3..22089e9 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -721,4 +721,11 @@ void warn_on_inaccessible(const char *path);
 /* Get the passwd entry for the UID of the current process. */
 struct passwd *xgetpwuid_self(void);
 
+#ifndef __GNU_LIBRARY__
+static inline int strverscmp(const char *s1, const char *s2)
+{
+	die("strverscmp() not supported");
+}
+#endif
+
 #endif
-- 
1.9.0.40.gaa8c3ea
Next: Jeff King
Message 1 of 25 in “tag: support --sort=version”
  1. tag: support --sort=versionNguyễn Thái Ngọc Duy, Feb 19, 2014
  2. Jeff KingFeb 19, 2014
  3. Duy NguyenFeb 19, 2014
  4. Jeff KingFeb 20, 2014
  5. Duy NguyenFeb 21, 2014
  6. Junio C HamanoFeb 21, 2014
  7. Jeff KingFeb 22, 2014
  8. Duy NguyenFeb 22, 2014
  9. Eric SunshineFeb 19, 2014
  10. tag: support --sort=<spec>Nguyễn Thái Ngọc Duy, Feb 22, 2014
  11. Jeff KingFeb 22, 2014
  12. Junio C HamanoFeb 24, 2014
  13. Duy NguyenFeb 24, 2014
  14. Jeff KingFeb 24, 2014
  15. tag: support --sort=<spec>Nguyễn Thái Ngọc Duy, Feb 25, 2014
  16. Junio C HamanoFeb 25, 2014
  17. Jeff KingFeb 26, 2014
  18. Duy NguyenFeb 26, 2014
  19. Jeff KingFeb 26, 2014
  20. Duy NguyenFeb 26, 2014
  21. Jeff KingFeb 26, 2014
  22. Duy NguyenFeb 26, 2014
  23. tag: support --sort=<spec>Nguyễn Thái Ngọc Duy, Feb 27, 2014
  24. Jeff KingFeb 27, 2014
  25. Duy NguyenFeb 27, 2014

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.