[PATCH v2] ls-files.c: add --object-only option
- From
ZheNing Hu via GitGitGadget <gitgitgadget@gmail.com>
- Date
- Jun 9, 2022, 12:37 UTC
- Message-ID
- <pull.1250.v2.git.1654778272871.gitgitgadget@gmail.com>
- 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_doneDocumentation/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