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

[PATCH] Introduce git version --list-features for porcelain use

From
Shawn O. Pearce <spearce@spearce.org>
Date
Jun 21, 2007, 04:59 UTC
Message-ID
<20070621045903.GA14047@spearce.org>

As a porcelain author I'm finding it difficult to keep track of what features I can use in git-gui. Newer versions of Git have newer capabilities but they don't always immediately get newer version numbers that I can easily test for.

This is a simple plumbing option that lets a porcelain ask the plumbing for its capabilities, at which point the porcelain can work around anything missing, or recommend to the user that they upgrade their plumbing layer.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 Because 'maint' does not support `git-blame -w` I can't apply your
 recent (and insanely good idea) 'git-gui: use "blame -w -C -C" for
 "where did it come from, originally?"' without something like the
 following, so I know that `git blame -w -C -C` will be accepted
 by the underlying plumbing.  ;-)
 help.c           |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 t/t0000-basic.sh |   16 +++++++++++
 2 files changed, 91 insertions(+), 2 deletions(-)
diff --git a/help.c b/help.c
index 1cd33ec..9f24a0f 100644
--- a/help.c
+++ b/help.c
@@ -9,6 +9,11 @@
 #include "common-cmds.h"
 #include <sys/ioctl.h>
 
+static const char *supported_features[] = {
+	"blame-ignore-whitespace",
+	"list-features",
+};
+
 /* most GUI terminals set COLUMNS (although some don't export it) */
 static int term_columns(void)
 {
@@ -190,10 +195,78 @@ void help_unknown_cmd(const char *cmd)
 	exit(1);
 }
 
+static int is_feature_name_sane(const char *a)
+{
+	if (!*a || *a == '-')
+		return 0;
+	for (; *a; a++) {
+		if (! ((*a >= 'a' && *a <= 'z')
+		    || (*a >= '0' && *a <= '9')
+		    || *a == '-'))
+			return 0;
+	}
+	return 1;
+}
+
+static int cmp_feature(const void *a_, const void *b_)
+{
+	const char *a = *((const char **)a_);
+	const char *b = *((const char **)b_);
+	return strcmp(a, b);
+}
+
+static void list_features()
+{
+	unsigned cnt = ARRAY_SIZE(supported_features);
+	unsigned i;
+
+	qsort(supported_features, cnt,
+		sizeof(supported_features[0]), cmp_feature);
+	for (i = 0; i < cnt; i++) {
+		const char *f = supported_features[i];
+		if (!is_feature_name_sane(f))
+			die("feature name \"%s\" is bogus", f);
+		printf("%s\n", f);
+	}
+}
+
+static int supports_feature(const char *the_feature)
+{
+	unsigned cnt = ARRAY_SIZE(supported_features);
+	unsigned i;
+
+	for (i = 0; i < cnt; i++) {
+		if (!strcmp(supported_features[i], the_feature))
+			return 0;
+	}
+	return 1;
+}
+
+static const char version_usage[] =
+"git-version [(--list-features | --supports-feature=<name>*)]";
+
 int cmd_version(int argc, const char **argv, const char *prefix)
 {
-	printf("git version %s\n", git_version_string);
-	return 0;
+	int i, ret = 0, list = 0, test = 0;
+
+	for (i = 1; i < argc; i++) {
+		const char *arg = argv[i];
+		if (!strcmp(arg, "--list-features"))
+			list = 1;
+		else if (!prefixcmp(arg, "--supports-feature=")) {
+			test = 1;
+			ret |= supports_feature(arg + 19);
+		} else
+			usage(version_usage);
+	}
+
+	if (list && test)
+		die("cannot use both --list-features and --supports-feature");
+	if (list)
+		list_features();
+	if (!list && !test)
+		printf("git version %s\n", git_version_string);
+	return ret;
 }
 
 int cmd_help(int argc, const char **argv, const char *prefix)
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 8bfe832..9fc5824 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -31,6 +31,22 @@ fi
 . ./test-lib.sh
 
 ################################################################
+# git version
+
+test_expect_success \
+	'git version is functional' \
+	'git version'
+test_expect_success \
+	'git version --list-features' \
+	'git version --list-features'
+test_expect_success \
+	'feature "list-features" is supported' \
+	'git version --supports-feature=list-features'
+test_expect_failure \
+	'feature "THISNEVERWILLBEAGITFEATURE" is not supported' \
+	'git version --supports-feature=THISNEVERWILLBEAGITFEATURE'
+
+################################################################
 # git-init has been done in an empty repository.
 # make sure it is empty.
 
-- 
1.5.2.2.1050.g51a8b
Next: Junio C Hamano
Message 1 of 16 in “Introduce git version --list-features for porcelain use”
  1. Introduce git version --list-features for porcelain useShawn O. Pearce, Jun 21, 2007
  2. Junio C HamanoJun 21, 2007
  3. Shawn O. PearceJun 21, 2007
  4. Junio C HamanoJun 21, 2007
  5. Make list of features auto-managed.Junio C Hamano, Jun 21, 2007
  6. Junio C HamanoJun 21, 2007
  7. Nicolas PitreJun 21, 2007
  8. Junio C HamanoJun 21, 2007
  9. Shawn O. PearceJun 22, 2007
  10. Junio C HamanoJun 22, 2007
  11. Nicolas PitreJun 22, 2007
  12. Shawn O. PearceJun 22, 2007
  13. Nicolas PitreJun 22, 2007
  14. Josef WeidendorferJun 22, 2007
  15. Catalin MarinasJun 22, 2007
  16. Johannes SchindelinJun 21, 2007

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.