git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Duy Nguyen <pclouds@gmail.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: Jeff King <peff@peff.net>, Git Mailing List <git@vger.kernel.org>
Subject: Support customized reordering in version sort
Date: Sat, 21 Feb 2015 10:02:10 +0700	[thread overview]
Message-ID: <20150221030209.GA567@lanh> (raw)
In-Reply-To: <CAPc5daVJ_nYk=tWqpUYPpsX6Z50H429jOh8QfMwUdNDdTDMq9w@mail.gmail.com>

On Fri, Feb 20, 2015 at 12:26:29AM -0800, Junio C Hamano wrote:
> On Thu, Feb 19, 2015 at 11:13 PM, Jeff King <peff@peff.net> wrote:
> 
> >> There is debian bug 777690 [1] that's basically about making tag's
> >> version sort aware about -rc, -pre suffixes. I imagine it would touch
> >> versioncmp.c and builtin/tag.c (to retrieve the suffixes from config
> >> file).
> >>
> >> [1] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=777690
> >
> > I think that's a reasonable thing to work on, but it's too big for a
> > microproject and too small for a GSoC.
> 
> That is certainly too big as a Micro, but I do not think it is too small
> for GSoC, if it is to be done right (meaning, not just implementing an
> arbitrary version comparison hardwired, but design how to make it
> extensible).

I did write "maybe more of mini-size than micro" then looked at the
micro list again and somehow decided to delete that. Anyway while I
still have my attention on it, might as well do it.

My idea is to make it easy for the user to change the sort algorithm.
And it's probably intuitive to just substitute a string with
something. So if "1-rc1" is put incorrectly before "1.1" and you
realize that "1.999" ought to be the last one before "2". You could
tell git to internally replace "1-rc1" with "1.999".

This patch does that. The user feeds substitution rules via
versionsort.substitute config keys, e.g.

    git config versionsort.substitute "-rc .999"

Performance is not a concern because I don't think people would throw
100k tags to it. There are two issues I'm aware of but not addressed:

 - the order of substitution matters, but right now it's up in the air
 - case-sensitiveness may surprise users

-- 8< --
diff --git a/versioncmp.c b/versioncmp.c
index 7511e08..2419e38 100644
--- a/versioncmp.c
+++ b/versioncmp.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "strbuf.h"
 
 /*
  * versioncmp(): copied from string/strverscmp.c in glibc commit
@@ -20,6 +21,57 @@
 #define  CMP    2
 #define  LEN    3
 
+struct subst_rule
+{
+	const char *before;
+	const char *after;
+};
+static struct subst_rule *rules;
+static int rule_nr, rule_alloc;
+
+static int versioncmp_config(const char *k, const char *v, void *cb)
+{
+	char *p, *s;
+	if (strcmp(k, "versionsort.substitute"))
+		return 0;
+	ALLOC_GROW(rules, rule_nr + 1, rule_alloc);
+	s = xstrdup(v);
+	p = strchr(s, ' ');
+	if (!p)
+		return error("missing space in %s", v);
+	*p = '\0';
+	rules[rule_nr].before = s;
+	rules[rule_nr].after = p + 1;
+	rule_nr++;
+	return 0;
+}
+
+static char *substitute(const unsigned char **strp)
+{
+	struct strbuf sb = STRBUF_INIT;
+	const char *str = (const char *)*strp;
+	int i;
+	if (!rules) {
+		rules = xmalloc(sizeof(*rules));
+		rule_alloc = 1;
+		git_config(versioncmp_config, NULL);
+	}
+	for (i = 0; i < rule_nr; i++) {
+		const struct subst_rule *r = rules + i;
+		const char *p = strstr(str, r->before);
+		if (!p)
+			continue;
+		if (!sb.len)
+			strbuf_addstr(&sb, str);
+		strbuf_splice(&sb, p - str, strlen(r->before),
+			      r->after, strlen(r->after));
+		str = sb.buf;
+	}
+	if ((const unsigned char *)str == *strp)
+		return NULL;
+	*strp = (const unsigned char *)sb.buf;
+	return sb.buf;
+}
 
 /*
  * Compare S1 and S2 as strings holding indices/version numbers,
@@ -32,6 +84,7 @@ int versioncmp(const char *s1, const char *s2)
 {
 	const unsigned char *p1 = (const unsigned char *) s1;
 	const unsigned char *p2 = (const unsigned char *) s2;
+	char *free1, *free2;
 	unsigned char c1, c2;
 	int state, diff;
 
@@ -58,6 +111,8 @@ int versioncmp(const char *s1, const char *s2)
 
 	if (p1 == p2)
 		return 0;
+	free1 = substitute(&p1);
+	free2 = substitute(&p2);
 
 	c1 = *p1++;
 	c2 = *p2++;
@@ -75,6 +130,10 @@ int versioncmp(const char *s1, const char *s2)
 	}
 
 	state = result_type[state * 3 + (((c2 == '0') + (isdigit (c2) != 0)))];
+	if (state != LEN) {
+		free(free1);
+		free(free2);
+	}
 
 	switch (state) {
 	case CMP:
@@ -82,10 +141,16 @@ int versioncmp(const char *s1, const char *s2)
 
 	case LEN:
 		while (isdigit (*p1++))
-			if (!isdigit (*p2++))
+			if (!isdigit (*p2++)) {
+				free(free1);
+				free(free2);
 				return 1;
+			}
 
-		return isdigit (*p2) ? -1 : diff;
+		c2 = *p2;
+		free(free1);
+		free(free2);
+		return isdigit (c2) ? -1 : diff;
 
 	default:
 		return state;
-- 8< --

  reply	other threads:[~2015-02-21  3:02 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-18 19:14 [RFH] GSoC 2015 application Jeff King
2015-02-18 19:32 ` Jeff King
2015-02-24 12:01   ` Johannes Schindelin
2015-02-24 12:06     ` [msysGit] " Jeff King
2015-02-24 12:25       ` Johannes Schindelin
2015-02-24 12:28         ` [msysGit] " Jeff King
2015-02-25  9:25           ` Johannes Schindelin
2015-02-25  9:39             ` Matthieu Moy
2015-02-25 10:25             ` Matthieu Moy
2015-02-25 12:15               ` Johannes Schindelin
2015-02-24 17:32     ` Matthieu Moy
2015-02-24 18:25       ` Junio C Hamano
2015-02-24 20:33         ` Johannes Schindelin
2015-02-24 21:02           ` Junio C Hamano
2015-02-24 23:56           ` Matthieu Moy
2015-02-25  0:34             ` [msysGit] " Stefan Beller
2015-02-25  9:25               ` Michael J Gruber
2015-02-25  8:44             ` Johannes Schindelin
2015-02-25 10:04               ` [msysGit] " Christian Couder
2015-02-25 10:02             ` Duy Nguyen
2015-02-25 12:10               ` Johannes Schindelin
2015-02-18 21:54 ` Junio C Hamano
2015-02-19  5:49   ` Junio C Hamano
2015-02-19 10:32 ` Matthieu Moy
2015-02-20  2:00   ` Jeff King
2015-02-20 10:06     ` Matthieu Moy
2015-02-20 10:22       ` Dennis Kaarsemaker
2015-02-20 10:34         ` Matthieu Moy
2015-02-20 23:06       ` Eric Sunshine
2015-02-20 10:31     ` [PATCH 1/3] microprojects: tweaks after discussion with Peff Matthieu Moy
2015-02-20 10:31       ` [PATCH 2/3] GSoC ideas: git bisect fixed/unfixed Matthieu Moy
2015-02-20 10:31       ` [PATCH 3/3] idea: Be nicer to the user on tracked/untracked merge conflicts Matthieu Moy
2015-02-20  3:26 ` [RFH] GSoC 2015 application Duy Nguyen
2015-02-20  7:13   ` Jeff King
2015-02-20  8:26     ` Junio C Hamano
2015-02-21  3:02       ` Duy Nguyen [this message]
2015-02-21  3:25         ` Support customized reordering in version sort Junio C Hamano
2015-02-21  3:33           ` Duy Nguyen
2015-02-21  5:12             ` Junio C Hamano
2015-02-21  5:37               ` Junio C Hamano
2015-02-26 10:44               ` [PATCH] versionsort: support reorder prerelease suffixes Nguyễn Thái Ngọc Duy
2015-02-27 21:37                 ` Junio C Hamano
2015-03-05  1:28                   ` Junio C Hamano
2015-03-09  1:01                     ` Duy Nguyen
2015-03-10  7:52                       ` Junio C Hamano
2015-03-10  8:03                         ` Eric Sunshine
2015-03-10 10:16                     ` [PATCH] config.txt: update versioncmp.prereleaseSuffix Nguyễn Thái Ngọc Duy
2015-02-20  5:35 ` [RFH] GSoC 2015 application Michael Haggerty
2015-02-20  7:29   ` Jeff King
2015-02-20  8:06     ` Junio C Hamano
2015-02-20  9:39     ` Matthieu Moy
2015-02-20  9:48       ` Jeff King
2015-02-20 11:35         ` Jeff King
2015-02-23  8:02           ` Matthieu Moy
2015-02-23 15:36             ` Jeff King
2015-03-04 22:05       ` Philip Oakley
2015-03-04 23:55         ` Stefan Beller
2015-03-05  0:17           ` Philip Oakley
2015-03-05  0:22             ` Junio C Hamano
2015-03-05  0:32               ` Stefan Beller
2015-03-05  1:17                 ` Junio C Hamano
2015-03-05  6:19                 ` Junio C Hamano
2015-03-06 11:24                   ` Duy Nguyen
2015-03-05  0:26           ` Duy Nguyen
2015-03-05 10:28         ` Nguyễn Thái Ngọc Duy
2015-03-05 10:28           ` [PATCH 1/6] upload-pack: move shallow deepen code out of receive_needs() Nguyễn Thái Ngọc Duy
2015-03-05 10:28           ` [PATCH 2/6] upload-pack: move "shallow" sending code out of deepen() Nguyễn Thái Ngọc Duy
2015-03-05 10:28           ` [PATCH 3/6] upload-pack: remove unused variable "backup" Nguyễn Thái Ngọc Duy
2015-03-05 10:28           ` [PATCH 4/6] upload-pack: move "unshallow" sending code out of deepen() Nguyễn Thái Ngọc Duy
2015-03-05 10:28           ` [PATCH 5/6] shallow.c: implement a generic shallow boundary finder based on rev-list Nguyễn Thái Ngọc Duy
2015-03-05 10:28           ` [PATCH 6/6] upload-pack: example code to use get_shallow_commits_by_rev_list Nguyễn Thái Ngọc Duy
2015-02-26 13:10 ` [RFH] GSoC 2015 application Duy Nguyen
2015-03-04 10:31   ` Jeff King
2015-03-04 11:21     ` 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

  List information: http://vger.kernel.org/majordomo-info.html

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

  git send-email \
    --in-reply-to=20150221030209.GA567@lanh \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=peff@peff.net \
    /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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).