All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Cc: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
Subject: [PATCH] tag: support --sort=version
Date: Wed, 19 Feb 2014 20:39:27 +0700	[thread overview]
Message-ID: <1392817167-29802-1-git-send-email-pclouds@gmail.com> (raw)

--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

             reply	other threads:[~2014-02-19 13:39 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-19 13:39 Nguyễn Thái Ngọc Duy [this message]
2014-02-19 14:09 ` [PATCH] tag: support --sort=version Jeff King
2014-02-19 14:19   ` Duy Nguyen
2014-02-20 20:43     ` Jeff King
2014-02-21 11:58       ` Duy Nguyen
2014-02-21 17:48         ` Junio C Hamano
2014-02-22  7:59         ` Jeff King
2014-02-22  9:07           ` Duy Nguyen
2014-02-19 18:43 ` Eric Sunshine
2014-02-22  3:29 ` [PATCH v2] tag: support --sort=<spec> Nguyễn Thái Ngọc Duy
2014-02-22  8:04   ` Jeff King
2014-02-24 16:39     ` Junio C Hamano
2014-02-24 23:30       ` Duy Nguyen
2014-02-24 23:33         ` Jeff King
2014-02-25 12:22   ` [PATCH v3] " Nguyễn Thái Ngọc Duy
2014-02-25 17:42     ` Junio C Hamano
2014-02-26  9:05     ` Jeff King
2014-02-26 11:03       ` Duy Nguyen
2014-02-26 11:08         ` Jeff King
2014-02-26 11:11           ` Duy Nguyen
2014-02-26 11:17             ` Jeff King
2014-02-26 11:31           ` Duy Nguyen
2014-02-27 12:56     ` [PATCH v4] " Nguyễn Thái Ngọc Duy
2014-02-27 13:11       ` Jeff King
2014-02-27 13:23         ` Duy Nguyen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1392817167-29802-1-git-send-email-pclouds@gmail.com \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.