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

Re: [PATCH v3] ls-files: introduce "--format" option

From
Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Date
Jun 24, 2022, 13:25 UTC
Message-ID
<220624.86letmi383.gmgdl@evledraar.gmail.com>
In-Reply-To
<pull.1262.v3.git.1655777140231.gitgitgadget@gmail.com>
On Tue, Jun 21 2022, ZheNing Hu via GitGitGadget wrote:
Show 31 quoted lines
> From: ZheNing Hu <adlternative@gmail.com>
> [...]
> +	if (skip_prefix(start, "(objectmode)", &p))
> +		strbuf_addf(sb, "%06o", data->ce->ce_mode);
> +	else if (skip_prefix(start, "(objectname)", &p))
> +		strbuf_add_unique_abbrev(sb, &data->ce->oid, abbrev);
> +	else if (skip_prefix(start, "(stage)", &p))
> +		strbuf_addf(sb, "%d", ce_stage(data->ce));
> +	else if (skip_prefix(start, "(eol)", &p))
> +		write_eolinfo_to_buf(sb, data->istate,
> +				     data->ce, data->pathname);
> +	else if (skip_prefix(start, "(path)", &p))
> +		write_name_to_buf(sb, data->pathname);
> +	else if (skip_prefix(start, "(ctime)", &p))
> +		strbuf_addf(sb, "ctime: %u:%u",
> +			    sd->sd_ctime.sec, sd->sd_ctime.nsec);
> +	else if (skip_prefix(start, "(mtime)", &p))
> +		strbuf_addf(sb, "mtime: %u:%u",
> +			    sd->sd_mtime.sec, sd->sd_mtime.nsec);
> +	else if (skip_prefix(start, "(dev)", &p))
> +		strbuf_addf(sb, "dev: %u", sd->sd_dev);
> +	else if (skip_prefix(start, "(ino)", &p))
> +		strbuf_addf(sb, "ino: %u", sd->sd_ino);
> +	else if (skip_prefix(start, "(uid)", &p))
> +		strbuf_addf(sb, "uid: %u", sd->sd_uid);
> +	else if (skip_prefix(start, "(gid)", &p))
> +		strbuf_addf(sb, "gid: %u", sd->sd_gid);
> +	else if (skip_prefix(start, "(size)", &p))
> +		strbuf_addf(sb, "size: %u", sd->sd_size);
> +	else if (skip_prefix(start, "(flags)", &p))
> +		strbuf_addf(sb, "flags: %x", data->ce->ce_flags);

In my mind almost the entire point of a --format is that you can e.g. \0-delimit it, and don't need to do other parsing games.

So this really should be adding just e.g. "%x", not "flags: %x", 

Similarly, let's no have :-delimited fields. First, for a formatted number "1656077225:850723245" is just bizarre for %(ctime), let's use ".", not ":", so: "1656077225.850723245".

And let's call that %(ctime), then have (which is trivial to add) a %(ctime:sec) and %(ctime:nsec), so someone who wants to format this can parse it as they please, ditto for mtime.

Looking at your tests it seemed you went down the route of aligning the output with the --debug output, which is already pre-formatted. I.e. to make what you have here match:

                printf("  ctime: %u:%u\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
                printf("  mtime: %u:%u\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
                printf("  dev: %u\tino: %u\n", sd->sd_dev, sd->sd_ino);
                printf("  uid: %u\tgid: %u\n", sd->sd_uid, sd->sd_gid);
                printf("  size: %u\tflags: %x\n", sd->sd_size, ce->ce_flags);

I think that's a mistake, we should be able to emit those individual %-specifiers instead, not that line as-is without the " " prefix and "\n" suffix.

> +
> +	if (format && (show_stage || show_others || show_killed ||
> +		show_resolve_undo || skipping_duplicates || debug_mode))
> +			die(_("ls-files --format cannot used with -s, -o, -k, --resolve-undo, --deduplicate, --debug"));

Use usage_msg_opt() or usage_msg_optf() here instead of die(), and no need to include "ls-files " in the message.

See die_for_incompatible_opt4, maybe you can just use that instead? A bit painful, but:

    die_for_incompatible_opt4(format, "--format", show_stage, "-s", show_others, "-o", show_killed, "-k");
    die_for_incompatible_opt4(format, "--format", show_resolve_undo, "--resolve-undo", skipping_duplicates, "--deduplicate", debug_mode, "--debug");

But urgh, that helper really should use usage_msg_opt() instead, but using it for now as-is probably sucks less.

I also think we should not forbid combining this wtih --debug, it's
helpful to construct a format. This seems to work:
		
	diff --git a/builtin/ls-files.c b/builtin/ls-files.c
	index 387641b32df..82f13edef7e 100644
	--- a/builtin/ls-files.c
	+++ b/builtin/ls-files.c
	@@ -343,12 +343,17 @@ static void show_ce(struct repository *repo, struct dir_struct *dir,
	 				  S_ISGITLINK(ce->ce_mode))) {
	 		if (format) {
	 			show_ce_fmt(repo, ce, format, fullname);
	-			return;
	+			if (!debug_mode)
	+				return;
	 		}
	 
	 		tag = get_tag(ce, tag);
	 
	-		if (!show_stage) {
	+		if (format) {
	+			if (!debug_mode)
	+				BUG("unreachable");
	+			; /* for --debug */
	+		} else if (!show_stage) {
	 			fputs(tag, stdout);
	 		} else {
	 			printf("%s%06o %s %d\t",
	@@ -814,7 +819,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
	 	}
	 
	 	if (format && (show_stage || show_others || show_killed ||
	-		show_resolve_undo || skipping_duplicates || debug_mode))
	+		show_resolve_undo || skipping_duplicates))
	 			die(_("ls-files --format cannot used with -s, -o, -k, --resolve-undo, --deduplicate, --debug"));
	 
	 	if (show_tag || show_valid_bit || show_fsmonitor_bit) {
	
I.e. we'll get:
	
	$ ./git ls-files --debug --format='<%(flags) %(path)>'  -- po/is.po
	<flags: 0 po/is.po>
	po/is.po
	  ctime: 1654300098:369653868
	  mtime: 1654300098:369653868
	  dev: 2306     ino: 10487322
	  uid: 1001     gid: 1001
	  size: 3370    flags: 0

Which I think is quite useful when poking around in this an coming up with a format.

Show 14 quoted lines
> +
>  	if (show_tag || show_valid_bit || show_fsmonitor_bit) {
>  		tag_cached = "H ";
>  		tag_unmerged = "M ";
> diff --git a/t/t3013-ls-files-format.sh b/t/t3013-ls-files-format.sh
> new file mode 100755
> index 00000000000..8c3ef2df138
> --- /dev/null
> +++ b/t/t3013-ls-files-format.sh
> @@ -0,0 +1,124 @@
> +#!/bin/sh
> +
> +test_description='git ls-files --format test'
> +
Add this line here:
TEST_PASSES_SANITIZE_LEAK=true

I.e. just before test-lib.sh, see other test examples. Then we'll test this under SANITIZE=leak in CI, to ensure it doesn't leak memory.

Show 11 quoted lines
> +. ./test-lib.sh
> +
> +test_expect_success 'setup' '
> +	echo o1 >o1 &&
> +	echo o2 >o2 &&
> +	git add o1 o2 &&
> +	git add --chmod +x o1 &&
> +	git commit -m base
> +'
> +
> [...]
Show 6 quoted lines
> +for flag in -s -o -k --resolve-undo --deduplicate --debug
> +do
> +	test_expect_success "git ls-files --format is incompatible with $flag" '
> +		test_must_fail git ls-files --format="%(objectname)" $flag
> +	'
> +done
Nit: I think it's good to move these sotrs of tests before "setup", and
give them a "usage: " prefix, see some other existing examples.

We usually use test_expect_code 129 for those, depending on if you'll end up with die() or not...

nit: missing \n before this line:
> +test_done
>
> base-commit: ab336e8f1c8009c8b1aab8deb592148e69217085
Previous: ZheNing HuNext: Junio C Hamano
Message 19 of 61 in “ls-files: introduce "--format" and "--object-only" options”
  1. 0/2 ls-files: introduce "--format" and "--object-only" optionsZheNing Hu via GitGitGadget, Jun 15, 2022
  2. 1/2 ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jun 15, 2022
  3. Ævar Arnfjörð BjarmasonJun 15, 2022
  4. ZheNing HuJun 18, 2022
  5. 2/2 ls-files: introduce "--object-only" optionZheNing Hu via GitGitGadget, Jun 15, 2022
  6. Ævar Arnfjörð BjarmasonJun 15, 2022
  7. ZheNing HuJun 18, 2022
  8. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jun 19, 2022
  9. Phillip WoodJun 19, 2022
  10. ZheNing HuJun 20, 2022
  11. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jun 21, 2022
  12. Phillip WoodJun 23, 2022
  13. Junio C HamanoJun 23, 2022
  14. Phillip WoodJun 24, 2022
  15. ZheNing HuJun 26, 2022
  16. Ævar Arnfjörð BjarmasonJun 24, 2022
  17. Junio C HamanoJun 24, 2022
  18. ZheNing HuJun 26, 2022
  19. Ævar Arnfjörð BjarmasonJun 24, 2022
  20. Junio C HamanoJun 24, 2022
  21. ZheNing HuJun 26, 2022
  22. Junio C HamanoJun 27, 2022
  23. ZheNing HuJun 27, 2022
  24. Junio C HamanoJun 27, 2022
  25. ZheNing HuJul 1, 2022
  26. ZheNing HuJun 26, 2022
  27. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jun 26, 2022
  28. Junio C HamanoJun 27, 2022
  29. ZheNing HuJun 27, 2022
  30. Ævar Arnfjörð BjarmasonJun 27, 2022
  31. ZheNing HuJul 1, 2022
  32. Phillip WoodJun 28, 2022
  33. ZheNing HuJul 1, 2022
  34. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jul 5, 2022
  35. Ævar Arnfjörð BjarmasonJul 5, 2022
  36. ZheNing HuJul 11, 2022
  37. Torsten BögershausenJul 5, 2022
  38. ZheNing HuJul 11, 2022
  39. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jul 11, 2022
  40. Junio C HamanoJul 11, 2022
  41. ZheNing HuJul 12, 2022
  42. Junio C HamanoJul 12, 2022
  43. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jul 13, 2022
  44. Ævar Arnfjörð BjarmasonJul 18, 2022
  45. ZheNing HuJul 19, 2022
  46. Junio C HamanoJul 19, 2022
  47. ZheNing HuJul 19, 2022
  48. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jul 20, 2022
  49. Junio C HamanoJul 20, 2022
  50. Ævar Arnfjörð BjarmasonJul 21, 2022
  51. Eric SunshineJul 21, 2022
  52. Junio C HamanoJul 21, 2022
  53. ZheNing HuJul 22, 2022
  54. Junio C HamanoJul 23, 2022
  55. Junio C HamanoJul 23, 2022
  56. ZheNing HuJul 24, 2022
  57. Junio C HamanoJul 25, 2022
  58. ZheNing HuJul 25, 2022
  59. ls-files: introduce "--format" optionZheNing Hu via GitGitGadget, Jul 23, 2022
  60. Jiang XinSep 8, 2022
  61. ZheNing HuSep 11, 2022

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.