git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: Brian Lyles <brianmlyles@gmail.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] pretty: find pretty formats case-insensitively
Date: Mon, 25 Mar 2024 02:14:52 -0400	[thread overview]
Message-ID: <20240325061452.GA242093@coredump.intra.peff.net> (raw)
In-Reply-To: <20240324214316.917513-1-brianmlyles@gmail.com>

On Sun, Mar 24, 2024 at 04:43:09PM -0500, Brian Lyles wrote:

> User-defined pretty formats are stored in config, which is meant to use
> case-insensitive matching for names as noted in config.txt's 'Syntax'
> section:
> 
>     All the other lines [...] are recognized as setting variables, in
>     the form 'name = value' [...]. The variable names are
>     case-insensitive, [...].
> 
> When a user specifies one of their format aliases with an uppercase in
> it, however, it is not found.
> 
>     $ git config pretty.testAlias %h
>     $ git config --list | grep pretty
>     pretty.testalias=%h
>     $ git log --format=testAlias -1
>     fatal: invalid --pretty format: testAlias
>     $ git log --format=testalias -1
>     3c2a3fdc38

Yeah, I agree that case-insensitive matching makes more sense here due
to the nature of config keys, especially given this:

> This is true whether the name in the config file uses any uppercase
> characters or not.

I.e., the config code is going to normalize the variable names already,
so we must match (even if the user consistently specifies camelCase).

But...

>  static struct cmt_fmt_map *find_commit_format(const char *sought)
>  {
> +	struct cmt_fmt_map *result;
> +	char *sought_lower;
> +
>  	if (!commit_formats)
>  		setup_commit_formats();
>  
> -	return find_commit_format_recursive(sought, sought, 0);
> +	/*
> +	 * The sought name will be compared to config names that have already
> +	 * been normalized to lowercase.
> +	 */
> +	sought_lower = xstrdup_tolower(sought);
> +	result = find_commit_format_recursive(sought_lower, sought_lower, 0);
> +	free(sought_lower);
> +	return result;
>  }

The mention of "recursive" in the function we call made me what wonder
if we'd need more normalization. And I think we do. Try this
modification to your test:

diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index 321e305979..be549b1d4b 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -61,8 +61,9 @@ test_expect_success 'alias user-defined format' '
 
 test_expect_success 'alias user-defined format is matched case-insensitively' '
 	git log --pretty="format:%h" >expected &&
-	git config pretty.testalias "format:%h" &&
-	git log --pretty=testAlias >actual &&
+	git config pretty.testone "format:%h" &&
+	git config pretty.testtwo testOne &&
+	git log --pretty=testTwo >actual &&
 	test_cmp expected actual
 '
 

which fails because looking up "testOne" in the recursion won't work. So
I think we'd want to simply match case-insensitively inside the
function, like:

diff --git a/pretty.c b/pretty.c
index 50825c9d25..10f71ee004 100644
--- a/pretty.c
+++ b/pretty.c
@@ -147,7 +147,7 @@ static struct cmt_fmt_map *find_commit_format_recursive(const char *sought,
 	for (i = 0; i < commit_formats_len; i++) {
 		size_t match_len;
 
-		if (!starts_with(commit_formats[i].name, sought))
+		if (!istarts_with(commit_formats[i].name, sought))
 			continue;
 
 		match_len = strlen(commit_formats[i].name);

And then you would not even need to normalize it in
find_commit_format().

> +test_expect_success 'alias user-defined format is matched case-insensitively' '
> +	git log --pretty="format:%h" >expected &&
> +	git config pretty.testalias "format:%h" &&
> +	git log --pretty=testAlias >actual &&
> +	test_cmp expected actual
> +'

Modern style would be to use "test_config" here (or just "git -c"), but
I see the surrounding tests are too old to do so. So I'd be OK with
matching them (but cleaning up all of the surrounding ones would be
nice, too).

-Peff

PS The matching rules in find_commit_format_recursive() seem weird
   to me. We do a prefix match, and then return the entry whose name is
   the shortest? And break ties based on which came first? So:

     git -c pretty.abcd=format:one \
         -c pretty.abc=format:two \
         -c pretty.abd=format:three \
	 log -1 --format=ab

   quietly chooses "two". I guess the "shortest wins" is meant to allow
   "foo" to be chosen over "foobar" if you specify the whole name. But
   the fact that we don't flag an ambiguity between "abc" and "abd"
   seems strange.

   That is all orthogonal to your patch, of course, but just a
   head-scratcher I noticed while looking at the code.


  reply	other threads:[~2024-03-25 13:35 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-24 21:43 [PATCH] pretty: find pretty formats case-insensitively Brian Lyles
2024-03-25  6:14 ` Jeff King [this message]
2024-03-25  7:08   ` Brian Lyles
2024-03-25 18:12   ` Junio C Hamano
2024-03-25  7:25 ` [PATCH v2 1/2] pretty: update tests to use `test_config` Brian Lyles
2024-03-25  9:44   ` Jeff King
2024-03-25  7:25 ` [PATCH v2 2/2] pretty: find pretty formats case-insensitively Brian Lyles
2024-03-25  9:46   ` Jeff King
2024-03-25 15:58     ` Brian Lyles

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=20240325061452.GA242093@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=brianmlyles@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.
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).