[PATCH v6 0/1] support `--object-only` option for "git-ls-tree"
From: Teng Long <hidden>
Date: 2021-12-17 06:57:25
Diffs from patch v5:
* Let "write_name_quoted_relative" support two terminations, they are
"CQ_NO_TERMINATOR_C_QUOTED" and "CQ_NO_TERMINATOR_AS_IS" (They are
used to let the function write "name" at a 'c_quoted' way or just
'as-is', but without print a terminator).
* Rename "follow" to "interspace" (Representing whether any further
output needs an inter-field space).
* Nits fixed.
Many thanks to Junio and Ævar for your help and patient explanation.
I noticed Ævar suggest the solution with using `--format`, but in
this patch, the current approach continues. If this part of code needs
to be improved or we want to support "--format" in "ls-tree" in the
future, I'm more than glad to continue to contribute.
Thanks.
Teng Long (1):
ls-tree.c: support `--object-only` option for "git-ls-tree"
Documentation/git-ls-tree.txt | 7 +-
builtin/ls-tree.c | 131 ++++++++++++++++++++++++----------
quote.c | 8 +--
quote.h | 19 +++++
t/t3103-ls-tree-misc.sh | 8 +++
t/t3104-ls-tree-oid.sh | 51 +++++++++++++
6 files changed, 183 insertions(+), 41 deletions(-)
create mode 100755 t/t3104-ls-tree-oid.sh
Range-diff against v5:
1: 38d55a878c ! 1: 2e449d1c79 ls-tree.c: support `--object-only` option for "git-ls-tree"
@@ builtin/ls-tree.c
-#define LS_SHOW_TREES 4
-#define LS_NAME_ONLY 8
-#define LS_SHOW_SIZE 16
-+#define LS_TREE_ONLY 1 << 1
-+#define LS_SHOW_TREES 1 << 2
-+#define LS_NAME_ONLY 1 << 3
-+#define LS_SHOW_SIZE 1 << 4
-+#define LS_OBJECT_ONLY 1 << 5
++#define LS_TREE_ONLY (1 << 1)
++#define LS_SHOW_TREES (1 << 2)
++#define LS_NAME_ONLY (1 << 3)
++#define LS_SHOW_SIZE (1 << 4)
++#define LS_OBJECT_ONLY (1 << 5)
static int abbrev;
static int ls_options;
static struct pathspec pathspec;
static int chomp_prefix;
static const char *ls_tree_prefix;
-+static unsigned int shown_bits = 0;
-+#define SHOW_DEFAULT 29 /* 11101 size is not shown to output by default */
-+#define SHOW_MODE 1 << 4
-+#define SHOW_TYPE 1 << 3
-+#define SHOW_OBJECT_NAME 1 << 2
-+#define SHOW_SIZE 1 << 1
++static unsigned int shown_bits;
+#define SHOW_FILE_NAME 1
++#define SHOW_SIZE (1 << 1)
++#define SHOW_OBJECT_NAME (1 << 2)
++#define SHOW_TYPE (1 << 3)
++#define SHOW_MODE (1 << 4)
++#define SHOW_DEFAULT 29 /* 11101 size is not shown to output by default */
static const char * const ls_tree_usage[] = {
N_("git ls-tree [<options>] <tree-ish> [<path>...]"),
@@ builtin/ls-tree.c
+ MODE_UNSPECIFIED = 0,
+ MODE_NAME_ONLY,
+ MODE_OBJECT_ONLY,
-+ MODE_LONG
++ MODE_LONG,
+};
+
+static int cmdmode = MODE_UNSPECIFIED;
@@ builtin/ls-tree.c: static int show_tree(const struct object_id *oid, struct strb
{
int retval = 0;
int baselen;
-+ int follow = 0;
++ int interspace = 0;
const char *type = blob_type;
if (S_ISGITLINK(mode)) {
@@ builtin/ls-tree.c: static int show_tree(const struct object_id *oid, struct strb
- find_unique_abbrev(oid, abbrev),
- size_text);
+ if (shown_bits & SHOW_MODE) {
-+ printf("%06o",mode);
-+ follow = 1;
++ printf("%06o", mode);
++ interspace = 1;
+ }
+ if (shown_bits & SHOW_TYPE) {
-+ printf("%s%s", follow == 1 ? " " : "", type);
-+ follow = 1;
++ printf("%s%s", interspace ? " " : "", type);
++ interspace = 1;
+ }
+ if (shown_bits & SHOW_OBJECT_NAME) {
-+ printf("%s%s", follow == 1 ? " " : "",
++ printf("%s%s", interspace ? " " : "",
+ find_unique_abbrev(oid, abbrev));
+ if (!(shown_bits ^ SHOW_OBJECT_NAME))
-+ printf("%c", line_termination);
-+ follow = 1;
++ goto LINE_FINISH;
++ interspace = 1;
+ }
+ if (shown_bits & SHOW_SIZE) {
+ char size_text[24];
@@ builtin/ls-tree.c: static int show_tree(const struct object_id *oid, struct strb
- printf("%06o %s %s\t", mode, type,
- find_unique_abbrev(oid, abbrev));
+ xsnprintf(size_text, sizeof(size_text), "-");
-+ printf("%s%7s", follow == 1 ? " " : "", size_text);
-+ follow = 1;
++ printf("%s%7s", interspace ? " " : "", size_text);
++ interspace = 1;
+ }
+ if (shown_bits & SHOW_FILE_NAME) {
-+ if (follow)
++ if (interspace)
+ printf("\t");
+ baselen = base->len;
+ strbuf_addstr(base, pathname);
+ write_name_quoted_relative(base->buf,
+ chomp_prefix ? ls_tree_prefix : NULL,
-+ stdout, line_termination);
++ stdout,
++ line_termination
++ ? CQ_NO_TERMINATOR_C_QUOTED
++ : CQ_NO_TERMINATOR_AS_IS);
+ strbuf_setlen(base, baselen);
}
- baselen = base->len;
@@ builtin/ls-tree.c: static int show_tree(const struct object_id *oid, struct strb
- chomp_prefix ? ls_tree_prefix : NULL,
- stdout, line_termination);
- strbuf_setlen(base, baselen);
++
++LINE_FINISH:
++ putchar(line_termination);
return retval;
}
@@ builtin/ls-tree.c: int cmd_ls_tree(int argc, const char **argv, const char *pref
* show_recursive() rolls its own matching code and is
* generally ignorant of 'struct pathspec'. The magic mask
+ ## quote.c ##
+@@ quote.c: void quote_two_c_style(struct strbuf *sb, const char *prefix, const char *path,
+
+ void write_name_quoted(const char *name, FILE *fp, int terminator)
+ {
+- if (terminator) {
++ if (0 < terminator || terminator == CQ_NO_TERMINATOR_C_QUOTED)
+ quote_c_style(name, NULL, fp, 0);
+- } else {
++ else
+ fputs(name, fp);
+- }
+- fputc(terminator, fp);
++ if (0 <= terminator)
++ fputc(terminator, fp);
+ }
+
+ void write_name_quoted_relative(const char *name, const char *prefix,
+
+ ## quote.h ##
+@@ quote.h: int unquote_c_style(struct strbuf *, const char *quoted, const char **endp);
+ #define CQUOTE_NODQ 01
+ size_t quote_c_style(const char *name, struct strbuf *, FILE *, unsigned);
+ void quote_two_c_style(struct strbuf *, const char *, const char *, unsigned);
++/*
++ * Write a name, typically a filename, followed by a terminator that
++ * separates it from what comes next.
++ * When terminator is NUL, the name is given as-is. Otherwise, the
++ * name is c-quoted, suitable for text output. HT and LF are typical
++ * values used for the terminator, but other positive values are possible.
++ *
++ * In addition to non-negative values two special values in terminator
++ * are possible.
++ *
++ * -1: show the name c-quoted, without adding any terminator.
++ * -2: show the name as-is, without adding any terminator.
++ */
++#define CQ_NO_TERMINATOR_C_QUOTED (-1)
++#define CQ_NO_TERMINATOR_AS_IS (-2)
+
+ void write_name_quoted(const char *name, FILE *, int terminator);
++/*
++ * Similar to the above, but the name is first made relative to the prefix
++ * before being shown.
++ */
+ void write_name_quoted_relative(const char *name, const char *prefix,
+ FILE *fp, int terminator);
+
+
## t/t3103-ls-tree-misc.sh ##
@@ t/t3103-ls-tree-misc.sh: test_expect_success 'ls-tree fails with non-zero exit code on broken tree' '
test_must_fail git ls-tree -r HEAD
--
2.33.1.10.g5f17c1a2c1.dirty