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

[PATCH] use natural ordering to display list of branches.

From
Cedric Vivier <cedricv@neonux.com>
Date
Jun 5, 2008, 17:41 UTC
Message-ID
<d45085aa0806051041y42ce467fq2e07371d225ccca3@mail.gmail.com>
Hi everyone,

This small patch makes git display list of branches in natural order. This way, when you name your branches against, for instance, a bug number from some bug-tracking tool, the list will show up in a natural/human/logical order.

Current behavior for "git branch": BUG-1040-doing-bar-is-too-slow BUG-84-calling-Z-with-null-segfaults BUG-900-program-freezes-when-user-click-on-button experimental-feature-X master

With the patch: BUG-84-calling-Z-with-null-segfaults BUG-900-program-freezes-when-user-click-on-button BUG-1040-doing-bar-takes-too-much-time experimental-feature-X master

Signed-off-by: Cedric Vivier <cedricv@neonux.com>
---
 Makefile         |    3 +
 builtin-branch.c |    3 +-
 strnatcmp.c      |  179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 strnatcmp.h      |   32 ++++++++++
 4 files changed, 216 insertions(+), 1 deletions(-)
 create mode 100644 strnatcmp.c
 create mode 100644 strnatcmp.h
diff --git a/Makefile b/Makefile
index cce5a6e..469b312 100644
--- a/Makefile
+++ b/Makefile
@@ -376,6 +376,7 @@ LIB_H += tree-walk.h
 LIB_H += unpack-trees.h
 LIB_H += utf8.h
 LIB_H += wt-status.h
+LIB_H += strnatcmp.h

 LIB_OBJS += alias.o
 LIB_OBJS += alloc.o
@@ -471,6 +472,7 @@ LIB_OBJS += write_or_die.o
 LIB_OBJS += ws.o
 LIB_OBJS += wt-status.o
 LIB_OBJS += xdiff-interface.o
+LIB_OBJS += strnatcmp.o

 BUILTIN_OBJS += builtin-add.o
 BUILTIN_OBJS += builtin-annotate.o
@@ -1141,6 +1143,7 @@ $(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h
xdiff/xdiff.h xdiff/xtypes.h \
 $(XDIFF_LIB): $(XDIFF_OBJS)
 	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(XDIFF_OBJS)

+strnatcmp.o: strnatcmp.c

 doc:
 	$(MAKE) -C Documentation all
diff --git a/builtin-branch.c b/builtin-branch.c
index d279702..c9c6788 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -13,6 +13,7 @@
 #include "remote.h"
 #include "parse-options.h"
 #include "branch.h"
+#include "strnatcmp.h"

 static const char * const builtin_branch_usage[] = {
 	"git-branch [options] [-r | -a] [--merged | --no-merged]",
@@ -279,7 +280,7 @@ static int ref_cmp(const void *r1, const void *r2)

 	if (c1->kind != c2->kind)
 		return c1->kind - c2->kind;
-	return strcmp(c1->name, c2->name);
+	return strnatcmp(c1->name, c2->name);
 }

 static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
diff --git a/strnatcmp.c b/strnatcmp.c
new file mode 100644
index 0000000..46bae0f
--- /dev/null
+++ b/strnatcmp.c
@@ -0,0 +1,179 @@
+/* -*- mode: c; c-file-style: "k&r" -*-
+
+  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
+  Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+/* partial change history:
+ *
+ * 2004-10-10 mbp: Lift out character type dependencies into macros.
+ *
+ * Eric Sosman pointed out that ctype functions take a parameter whose
+ * value must be that of an unsigned int, even on platforms that have
+ * negative chars in their default char type.
+ */
+
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>
+#include <stdio.h>
+
+#include "strnatcmp.h"
+
+
+/* These are defined as macros to make it easier to adapt this code to
+ * different characters types or comparison functions. */
+static inline int
+nat_isdigit(nat_char a)
+{
+     return isdigit((unsigned char) a);
+}
+
+
+static inline int
+nat_isspace(nat_char a)
+{
+     return isspace((unsigned char) a);
+}
+
+
+static inline nat_char
+nat_toupper(nat_char a)
+{
+     return toupper((unsigned char) a);
+}
+
+
+
+static int
+compare_right(nat_char const *a, nat_char const *b)
+{
+     int bias = 0;
+
+     /* The longest run of digits wins.  That aside, the greatest
+	value wins, but we can't know that it will until we've scanned
+	both numbers to know that they have the same magnitude, so we
+	remember it in BIAS. */
+     for (;; a++, b++) {
+	  if (!nat_isdigit(*a)  &&  !nat_isdigit(*b))
+	       return bias;
+	  else if (!nat_isdigit(*a))
+	       return -1;
+	  else if (!nat_isdigit(*b))
+	       return +1;
+	  else if (*a < *b) {
+	       if (!bias)
+		    bias = -1;
+	  } else if (*a > *b) {
+	       if (!bias)
+		    bias = +1;
+	  } else if (!*a  &&  !*b)
+	       return bias;
+     }
+
+     return 0;
+}
+
+
+static int
+compare_left(nat_char const *a, nat_char const *b)
+{
+     /* Compare two left-aligned numbers: the first to have a
+     different value wins. */
+     for (;; a++, b++) {
+	  if (!nat_isdigit(*a)  &&  !nat_isdigit(*b))
+	       return 0;
+	  else if (!nat_isdigit(*a))
+	       return -1;
+	  else if (!nat_isdigit(*b))
+	       return +1;
+	  else if (*a < *b)
+	       return -1;
+	  else if (*a > *b)
+	       return +1;
+     }
+
+     return 0;
+}
+
+
+static int strnatcmp0(nat_char const *a, nat_char const *b, int fold_case)
+{
+     int ai, bi;
+     nat_char ca, cb;
+     int fractional, result;
+
+     assert(a && b);
+     ai = bi = 0;
+     while (1) {
+	  ca = a[ai]; cb = b[bi];
+
+	  /* skip over leading spaces or zeros */
+	  while (nat_isspace(ca))
+	       ca = a[++ai];
+
+	  while (nat_isspace(cb))
+	       cb = b[++bi];
+
+	  /* process run of digits */
+	  if (nat_isdigit(ca)  &&  nat_isdigit(cb)) {
+	       fractional = (ca == '0' || cb == '0');
+
+	       if (fractional) {
+		    if ((result = compare_left(a+ai, b+bi)) != 0)
+			 return result;
+	       } else {
+		    if ((result = compare_right(a+ai, b+bi)) != 0)
+			 return result;
+	       }
+	  }
+
+	  if (!ca && !cb) {
+	       /* The strings compare the same.  Perhaps the caller
+	       will want to call strcmp to break the tie. */
+	       return 0;
+	  }
+
+	  if (fold_case) {
+	       ca = nat_toupper(ca);
+	       cb = nat_toupper(cb);
+	  }
+
+	  if (ca < cb)
+	       return -1;
+	  else if (ca > cb)
+	       return +1;
+
+	  ++ai; ++bi;
+     }
+}
+
+
+
+int strnatcmp(nat_char const *a, nat_char const *b) {
+     return strnatcmp0(a, b, 0);
+}
+
+
+/* Compare, recognizing numeric string and ignoring case. */
+int strnatcasecmp(nat_char const *a, nat_char const *b) {
+     return strnatcmp0(a, b, 1);
+}
+
diff --git a/strnatcmp.h b/strnatcmp.h
new file mode 100644
index 0000000..7b2ca39
--- /dev/null
+++ b/strnatcmp.h
@@ -0,0 +1,32 @@
+/* -*- mode: c; c-file-style: "k&r" -*-
+
+  strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
+  Copyright (C) 2000, 2004 by Martin Pool <mbp sourcefrog net>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+
+/* CUSTOMIZATION SECTION
+ *
+ * You can change this typedef, but must then also change the inline
+ * functions in strnatcmp.c */
+typedef char nat_char;
+
+int strnatcmp(nat_char const *a, nat_char const *b);
+int strnatcasecmp(nat_char const *a, nat_char const *b);
+
-- 
1.5.6.rc1.12.g7f71.dirty
Next: Johannes Schindelin
Message 1 of 27 in “use natural ordering to display list of branches.”
  1. use natural ordering to display list of branches.Cedric Vivier, Jun 5, 2008
  2. Johannes SchindelinJun 5, 2008
  3. Junio C HamanoJun 5, 2008
  4. Johannes SchindelinJun 5, 2008
  5. Cedric VivierJun 5, 2008
  6. Marius Storm-OlsenJun 5, 2008
  7. Paolo BonziniJun 6, 2008
  8. Johannes SchindelinJun 6, 2008
  9. Sverre RabbelierJun 6, 2008
  10. Paolo BonziniJun 6, 2008
  11. Brandon CaseyJun 6, 2008
  12. Cedric VivierJun 6, 2008
  13. Brandon CaseyJun 6, 2008
  14. Johannes SchindelinJun 6, 2008
  15. Junio C HamanoJun 6, 2008
  16. Asheesh LaroiaJun 6, 2008
  17. Jeff KingJun 7, 2008
  18. Cedric VivierJun 7, 2008
  19. Junio C HamanoJun 7, 2008
  20. Cedric VivierJun 7, 2008
  21. Junio C HamanoJun 7, 2008
  22. しらいしななこJun 6, 2008
  23. Ask Bjørn HansenJun 15, 2008
  24. Mike RalphsonJun 6, 2008
  25. Cedric VivierJun 6, 2008
  26. Mike RalphsonJun 6, 2008
  27. Andreas EricssonJun 9, 2008

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.