git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "ZheNing Hu via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "Junio C Hamano" <gitster@pobox.com>,
	"Christian Couder" <christian.couder@gmail.com>,
	"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
	"ZheNing Hu" <adlternative@gmail.com>,
	"ZheNing Hu" <adlternative@gmail.com>
Subject: [PATCH v2] ls-files.c: add --object-only option
Date: Thu, 09 Jun 2022 12:37:52 +0000	[thread overview]
Message-ID: <pull.1250.v2.git.1654778272871.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1250.git.1654509678718.gitgitgadget@gmail.com>

From: ZheNing Hu <adlternative@gmail.com>

`git ls-files --stage` default output format is:

[<tag> ]<mode> <object> <stage> <file>

sometime we want to find a path's corresponding objectname,
we will parse the output and extract objectname from it
again and again.

So introduce a new option `--object-only` which can only
output objectname when giving `--stage` or `--resolve-undo`.

Signed-off-by: ZheNing Hu <adlternative@gmail.com>
---
    ls-files.c: add --object-only option
    
    v1 -> v2: rename option '--only-object-name' to '--object-only'.

Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1250%2Fadlternative%2Fzh%2Fls-file-only-objectname-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1250/adlternative/zh/ls-file-only-objectname-v2
Pull-Request: https://github.com/gitgitgadget/git/pull/1250

Range-diff vs v1:

 1:  10efe3bd9ca ! 1:  aed0bd2c791 ls-files.c: add --only-object-name option
     @@ Metadata
      Author: ZheNing Hu <adlternative@gmail.com>
      
       ## Commit message ##
     -    ls-files.c: add --only-object-name option
     +    ls-files.c: add --object-only option
      
          `git ls-files --stage` default output format is:
      
     @@ Commit message
          we will parse the output and extract objectname from it
          again and again.
      
     -    So introduce a new option `--only-object-name` which can only
     +    So introduce a new option `--object-only` which can only
          output objectname when giving `--stage` or `--resolve-undo`.
      
          Signed-off-by: ZheNing Hu <adlternative@gmail.com>
     @@ Documentation/git-ls-files.txt: SYNOPSIS
       		[-s|--stage] [-u|--unmerged] [-k|--|killed] [-m|--modified]
       		[--directory [--no-empty-directory]] [--eol]
      -		[--deduplicate]
     -+		[--deduplicate] [--only-object-name]
     ++		[--deduplicate] [--object-only]
       		[-x <pattern>|--exclude=<pattern>]
       		[-X <file>|--exclude-from=<file>]
       		[--exclude-per-directory=<file>]
     @@ Documentation/git-ls-files.txt: OPTIONS
       	When any of the `-t`, `--unmerged`, or `--stage` option is
       	in use, this option has no effect.
       
     -+--only-object-name:
     ++--object-only:
      +	When giving `--stage` or `--resolve-undo` , only output `<object>`
      +	instead of `[<tag> ]<mode> <object> <stage> <file>` format.
      +
     @@ builtin/ls-files.c: static int show_deleted;
       static int show_cached;
       static int show_others;
       static int show_stage;
     -+static int only_object_name;
     ++static int object_only;
       static int show_unmerged;
       static int show_resolve_undo;
       static int show_modified;
     @@ builtin/ls-files.c: static void show_ce(struct repository *repo, struct dir_stru
       			fputs(tag, stdout);
       		} else {
      +			const char *object_name = repo_find_unique_abbrev(repo, &ce->oid, abbrev);
     -+			if (only_object_name) {
     ++			if (object_only) {
      +				printf("%s%c", object_name, line_terminator);
      +				return;
      +			}
     @@ builtin/ls-files.c: static void show_ru_info(struct index_state *istate)
       		for (i = 0; i < 3; i++) {
       			if (!ui->mode[i])
       				continue;
     -+			if (only_object_name) {
     ++			if (object_only) {
      +				printf("%s%c", find_unique_abbrev(&ui->oid[i], abbrev), line_terminator);
      +				continue;
      +			}
     @@ builtin/ls-files.c: int cmd_ls_files(int argc, const char **argv, const char *cm
       			DIR_SHOW_IGNORED),
       		OPT_BOOL('s', "stage", &show_stage,
       			N_("show staged contents' object name in the output")),
     -+		OPT_BOOL(0, "only-object-name", &only_object_name,
     ++		OPT_BOOL(0, "object-only", &object_only,
      +			N_("only show staged contents' object name in the output")),
       		OPT_BOOL('k', "killed", &show_killed,
       			N_("show files on the filesystem that need to be removed")),
     @@ builtin/ls-files.c: int cmd_ls_files(int argc, const char **argv, const char *cm
       		die("ls-files --recurse-submodules does not support "
       		    "--error-unmatch");
       
     -+	if (only_object_name && !show_stage && !show_resolve_undo)
     -+		die("ls-files --only-object-name only used with --stage "
     -+		    "or --resolve-undo");
     ++	if (object_only && !show_stage && !show_resolve_undo)
     ++		die(_("ls-files --object-only only used with --stage "
     ++		    "or --resolve-undo"));
      +
       	parse_pathspec(&pathspec, 0,
       		       PATHSPEC_PREFER_CWD,
     @@ t/t2030-unresolve-info.sh: check_resolve_undo () {
       	test_cmp "$msg.expect" "$msg.actual"
       }
       
     -+check_resolve_undo_only_object_name() {
     ++check_resolve_undo_object_only() {
      +	msg=$1
      +	shift
      +	while case $# in
      +	0)	break ;;
     -+	1|2|3)	die "Bug in check-resolve-undo test" ;;
     ++	1|2|3)	BUG "wrong arguments" ;;
      +	esac
      +	do
      +		path=$1
     @@ t/t2030-unresolve-info.sh: check_resolve_undo () {
      +			case "$sha1" in
      +			'') continue ;;
      +			esac
     -+			sha1=$(git rev-parse --verify "$sha1")
     ++			sha1=$(git rev-parse --verify "$sha1") &&
      +			printf "%s\n" $sha1
      +		done
      +	done >"$msg.expect" &&
     -+	git ls-files --resolve-undo --only-object-name >"$msg.actual" &&
     ++	git ls-files --resolve-undo --object-only >"$msg.actual" &&
      +	test_cmp "$msg.expect" "$msg.actual"
      +}
      +
     @@ t/t2030-unresolve-info.sh: test_expect_success 'rerere forget (add-add conflict)
       	test_i18ngrep "no remembered" actual
       '
       
     -+test_expect_success '--resolve-undo with --only-object-name' '
     ++test_expect_success '--resolve-undo with --object-only' '
      +	prime_resolve_undo &&
     -+	check_resolve_undo_only_object_name kept fi/le initial:fi/le second:fi/le third:fi/le &&
     ++	check_resolve_undo_object_only kept fi/le initial:fi/le second:fi/le third:fi/le &&
      +	git checkout second^0 &&
      +	echo switching clears &&
      +	check_resolve_undo cleared
     @@ t/t3004-ls-files-basic.sh: test_expect_success SYMLINKS 'ls-files with absolute
       	test_cmp expect actual
       '
       
     -+test_expect_success 'git ls-files --stage with --only-object-name' '
     ++test_expect_success 'git ls-files --stage with --object-only' '
      +	git init test &&
      +	test_when_finished "rm -rf test" &&
     -+	(
     -+		cd test &&
     -+		echo a >a.txt &&
     -+		echo b >b.txt &&
     -+		git add a.txt b.txt &&
     -+		oid1=$(git hash-object a.txt) &&
     -+		oid2=$(git hash-object b.txt) &&
     -+		git ls-files --stage --only-object-name >actual &&
     -+		cat >expect <<-EOF &&
     -+		$oid1
     -+		$oid2
     -+		EOF
     -+		test_cmp expect actual
     -+	)
     ++	echo a >test/a.txt &&
     ++	echo b >test/b.txt &&
     ++	git -C test add a.txt b.txt &&
     ++	oid1=$(git -C test hash-object a.txt) &&
     ++	oid2=$(git -C test hash-object b.txt) &&
     ++	git -C test ls-files --stage --object-only >actual &&
     ++	cat >expect <<-EOF &&
     ++	$oid1
     ++	$oid2
     ++	EOF
     ++	test_cmp expect actual
      +'
      +
     -+test_expect_success 'git ls-files --only-object-name without --stage or --resolve-undo' '
     ++test_expect_success 'git ls-files --object-only without --stage or --resolve-undo' '
      +	git init test &&
      +	test_when_finished "rm -rf test" &&
     -+	(
     -+		cd test &&
     -+		echo a >a.txt &&
     -+		echo b >b.txt &&
     -+		git add a.txt b.txt &&
     -+		test_must_fail git ls-files --only-object-name 2>stderr &&
     -+		test_i18ngrep "fatal: ls-files --only-object-name only used with --stage or --resolve-undo" stderr
     -+	)
     ++	echo a >test/a.txt &&
     ++	echo b >test/b.txt &&
     ++	git -C test add a.txt b.txt &&
     ++	test_must_fail git -C test ls-files --object-only 2>stderr &&
     ++	grep "fatal: ls-files --object-only only used with --stage or --resolve-undo" stderr
      +'
      +
       test_done


 Documentation/git-ls-files.txt |  6 +++++-
 builtin/ls-files.c             | 18 +++++++++++++++++-
 t/t2030-unresolve-info.sh      | 33 +++++++++++++++++++++++++++++++++
 t/t3004-ls-files-basic.sh      | 26 ++++++++++++++++++++++++++
 4 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 0dabf3f0ddc..9736b02b565 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -13,7 +13,7 @@ SYNOPSIS
 		[-c|--cached] [-d|--deleted] [-o|--others] [-i|--|ignored]
 		[-s|--stage] [-u|--unmerged] [-k|--|killed] [-m|--modified]
 		[--directory [--no-empty-directory]] [--eol]
-		[--deduplicate]
+		[--deduplicate] [--object-only]
 		[-x <pattern>|--exclude=<pattern>]
 		[-X <file>|--exclude-from=<file>]
 		[--exclude-per-directory=<file>]
@@ -88,6 +88,10 @@ OPTIONS
 	When any of the `-t`, `--unmerged`, or `--stage` option is
 	in use, this option has no effect.
 
+--object-only:
+	When giving `--stage` or `--resolve-undo` , only output `<object>`
+	instead of `[<tag> ]<mode> <object> <stage> <file>` format.
+
 -x <pattern>::
 --exclude=<pattern>::
 	Skip untracked files matching pattern.
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index e791b65e7e9..2fef5f40a3f 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -26,6 +26,7 @@ static int show_deleted;
 static int show_cached;
 static int show_others;
 static int show_stage;
+static int object_only;
 static int show_unmerged;
 static int show_resolve_undo;
 static int show_modified;
@@ -241,10 +242,15 @@ static void show_ce(struct repository *repo, struct dir_struct *dir,
 		if (!show_stage) {
 			fputs(tag, stdout);
 		} else {
+			const char *object_name = repo_find_unique_abbrev(repo, &ce->oid, abbrev);
+			if (object_only) {
+				printf("%s%c", object_name, line_terminator);
+				return;
+			}
 			printf("%s%06o %s %d\t",
 			       tag,
 			       ce->ce_mode,
-			       repo_find_unique_abbrev(repo, &ce->oid, abbrev),
+			       object_name,
 			       ce_stage(ce));
 		}
 		write_eolinfo(repo->index, ce, fullname);
@@ -274,6 +280,10 @@ static void show_ru_info(struct index_state *istate)
 		for (i = 0; i < 3; i++) {
 			if (!ui->mode[i])
 				continue;
+			if (object_only) {
+				printf("%s%c", find_unique_abbrev(&ui->oid[i], abbrev), line_terminator);
+				continue;
+			}
 			printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
 			       find_unique_abbrev(&ui->oid[i], abbrev),
 			       i + 1);
@@ -635,6 +645,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 			DIR_SHOW_IGNORED),
 		OPT_BOOL('s', "stage", &show_stage,
 			N_("show staged contents' object name in the output")),
+		OPT_BOOL(0, "object-only", &object_only,
+			N_("only show staged contents' object name in the output")),
 		OPT_BOOL('k', "killed", &show_killed,
 			N_("show files on the filesystem that need to be removed")),
 		OPT_BIT(0, "directory", &dir.flags,
@@ -734,6 +746,10 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
 		die("ls-files --recurse-submodules does not support "
 		    "--error-unmatch");
 
+	if (object_only && !show_stage && !show_resolve_undo)
+		die(_("ls-files --object-only only used with --stage "
+		    "or --resolve-undo"));
+
 	parse_pathspec(&pathspec, 0,
 		       PATHSPEC_PREFER_CWD,
 		       prefix, argv);
diff --git a/t/t2030-unresolve-info.sh b/t/t2030-unresolve-info.sh
index f691e6d9032..cdab953980c 100755
--- a/t/t2030-unresolve-info.sh
+++ b/t/t2030-unresolve-info.sh
@@ -32,6 +32,31 @@ check_resolve_undo () {
 	test_cmp "$msg.expect" "$msg.actual"
 }
 
+check_resolve_undo_object_only() {
+	msg=$1
+	shift
+	while case $# in
+	0)	break ;;
+	1|2|3)	BUG "wrong arguments" ;;
+	esac
+	do
+		path=$1
+		shift
+		for stage in 1 2 3
+		do
+			sha1=$1
+			shift
+			case "$sha1" in
+			'') continue ;;
+			esac
+			sha1=$(git rev-parse --verify "$sha1") &&
+			printf "%s\n" $sha1
+		done
+	done >"$msg.expect" &&
+	git ls-files --resolve-undo --object-only >"$msg.actual" &&
+	test_cmp "$msg.expect" "$msg.actual"
+}
+
 prime_resolve_undo () {
 	git reset --hard &&
 	git checkout second^0 &&
@@ -194,4 +219,12 @@ test_expect_success 'rerere forget (add-add conflict)' '
 	test_i18ngrep "no remembered" actual
 '
 
+test_expect_success '--resolve-undo with --object-only' '
+	prime_resolve_undo &&
+	check_resolve_undo_object_only kept fi/le initial:fi/le second:fi/le third:fi/le &&
+	git checkout second^0 &&
+	echo switching clears &&
+	check_resolve_undo cleared
+'
+
 test_done
diff --git a/t/t3004-ls-files-basic.sh b/t/t3004-ls-files-basic.sh
index a16e25c79bd..6c81ead140e 100755
--- a/t/t3004-ls-files-basic.sh
+++ b/t/t3004-ls-files-basic.sh
@@ -52,4 +52,30 @@ test_expect_success SYMLINKS 'ls-files with absolute paths to symlinks' '
 	test_cmp expect actual
 '
 
+test_expect_success 'git ls-files --stage with --object-only' '
+	git init test &&
+	test_when_finished "rm -rf test" &&
+	echo a >test/a.txt &&
+	echo b >test/b.txt &&
+	git -C test add a.txt b.txt &&
+	oid1=$(git -C test hash-object a.txt) &&
+	oid2=$(git -C test hash-object b.txt) &&
+	git -C test ls-files --stage --object-only >actual &&
+	cat >expect <<-EOF &&
+	$oid1
+	$oid2
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'git ls-files --object-only without --stage or --resolve-undo' '
+	git init test &&
+	test_when_finished "rm -rf test" &&
+	echo a >test/a.txt &&
+	echo b >test/b.txt &&
+	git -C test add a.txt b.txt &&
+	test_must_fail git -C test ls-files --object-only 2>stderr &&
+	grep "fatal: ls-files --object-only only used with --stage or --resolve-undo" stderr
+'
+
 test_done

base-commit: ab336e8f1c8009c8b1aab8deb592148e69217085
-- 
gitgitgadget

  parent reply	other threads:[~2022-06-09 12:38 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-06 10:01 [PATCH] ls-files.c: add --only-object-name option ZheNing Hu via GitGitGadget
2022-06-06 17:42 ` Ævar Arnfjörð Bjarmason
2022-06-08 14:38   ` ZheNing Hu
2022-06-08 16:09     ` Junio C Hamano
2022-06-09 12:37 ` ZheNing Hu via GitGitGadget [this message]
2022-06-09 19:50   ` [PATCH v2] ls-files.c: add --object-only option Junio C Hamano
2022-06-12 10:24     ` ZheNing Hu
2022-06-13 17:19       ` Junio C Hamano

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

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

  git send-email \
    --in-reply-to=pull.1250.v2.git.1654778272871.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=adlternative@gmail.com \
    --cc=avarab@gmail.com \
    --cc=christian.couder@gmail.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /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.
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 NNTP newsgroup(s).