From patchwork Thu Nov 17 13:48:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 13046900 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7583FC433FE for ; Thu, 17 Nov 2022 13:48:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234533AbiKQNs1 (ORCPT ); Thu, 17 Nov 2022 08:48:27 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57100 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232342AbiKQNs0 (ORCPT ); Thu, 17 Nov 2022 08:48:26 -0500 Received: from mail-ed1-x52f.google.com (mail-ed1-x52f.google.com [IPv6:2a00:1450:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4C135C69 for ; Thu, 17 Nov 2022 05:48:24 -0800 (PST) Received: by mail-ed1-x52f.google.com with SMTP id f7so2597152edc.6 for ; Thu, 17 Nov 2022 05:48:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fgBRMbcy7J17ZTVoNNpXUJAszIia2bvIj23DBCCChn4=; b=YWTJ7IlTN7ntCqkU246rUXp6rXyj0jaRj/rhIpC9rvuK7VdgMjqFCiE6j31qQnaCnw llxkb8GPCq096+Z8i/mgsSP+7RLs/AbGt/bCS2V1jTx3sBJ2wIgZwA7JavVI5ud8UU1/ uubIklgcuNXtrdKx8Ym0CwRJuFgh1ka8TbeaOrRdtShYUey8mkTNZyzbnygFJCGxS9PD HQwQ+waVKjpAHip55krAZ1YDGl/yPhX8IpcmqVVVeoJGgTZP+W0gUVt6NjhXGre0AUYU NIgIR7L8ohmxC9/79ZiR7aBpGf2qZfA6e0GthZuSaEjZOJ9M27zQPrmvGsvRNhukPbOA RbSw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fgBRMbcy7J17ZTVoNNpXUJAszIia2bvIj23DBCCChn4=; b=xPA+qcf3hqGLOTlcbq6GjjFLmLAdEdGUcxBxoLfegFwR+fLbecX/q4vjtyie/8U1GX rH1aDumu9w2zB2KECpp7knuu0qiNmn1ZR4LFOWSUFfcjycMHiIvhSODFLvERSi/9DjWm R+MgQXzbdMSYFL3XLt6NdV3koFpyJ5XGSjK2GLeoMTy/t++HSCQV1BSzWbToiXHVAfEB OyvYjULj/GkX2bUaT/iSbWajzrUZ1hsV71bFhhQaFWLTuevmeqSHEX7hWlzSe0MW4fox i5bBS1cTzfh8AQI2eoXMAbUpljqov7k7tdaom4pRNADCsqvo4t/WCm+ov4WhgH8Aow9s ONuA== X-Gm-Message-State: ANoB5plhcyNiBk/pkSpR5hJohEcN+7UPKOAsAKN9WfMzdeLRkuSNxJ9Y KDYAhIDhcs6eMgSH+COHapUVnwXXHcTNzQ== X-Google-Smtp-Source: AA0mqf4Wns9l9Hu4Fz9pnIJ4JzFtFZTkCDFVgP+Vru8ZL8rRyyIGxT15eKKJVl2grQVh/3IKLBb7bg== X-Received: by 2002:a05:6402:288f:b0:460:d1f6:2917 with SMTP id eg15-20020a056402288f00b00460d1f62917mr2250984edb.207.1668692902463; Thu, 17 Nov 2022 05:48:22 -0800 (PST) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id m27-20020a170906581b00b007ad9adabcd4sm379257ejq.213.2022.11.17.05.48.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Nov 2022 05:48:21 -0800 (PST) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Taylor Blau , Teng Long , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= Subject: [RFC PATCH 1/4] ls-tree: don't use "show_tree_data" for "fast" callbacks Date: Thu, 17 Nov 2022 14:48:14 +0100 Message-Id: X-Mailer: git-send-email 2.38.0.1473.g172bcc0511c In-Reply-To: References: <20221117113023.65865-1-tenglong.tl@alibaba-inc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org As noted in [1] the code that made it in as part of 9c4d58ff2c3 (ls-tree: split up "fast path" callbacks, 2022-03-23) was a "maybe a good idea, maybe not" RFC-quality patch. I hadn't looked very carefully at the resulting patterns. The implementation shared the "struct show_tree_data data", which was introduced in e81517155e0 (ls-tree: introduce struct "show_tree_data", 2022-03-23) both for use in 455923e0a15 (ls-tree: introduce "--format" option, 2022-03-23), and because the "fat" callback hadn't been split up as 9c4d58ff2c3 did. Now that that's been done we can see that most of what show_tree_common() was doing could be done lazily by the callbacks themselves, who in the pre-image were often using an odd mis-match of their own arguments and those same arguments stuck into the "data" structure. Let's also have the callers initialize the "type", rather than grabbing it from the "data" structure afterwards. 1. https://lore.kernel.org/git/cover-0.7-00000000000-20220310T134811Z-avarab@gmail.com/ --- builtin/ls-tree.c | 44 ++++++++++++++++++-------------------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index c3ea09281af..cbb6782f9a5 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -173,19 +173,11 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, return recurse; } -static int show_tree_common(struct show_tree_data *data, int *recurse, - const struct object_id *oid, struct strbuf *base, - const char *pathname, unsigned mode) +static int show_tree_common(int *recurse, struct strbuf *base, + const char *pathname, enum object_type type) { - enum object_type type = object_type(mode); int ret = -1; - *recurse = 0; - data->mode = mode; - data->type = type; - data->oid = oid; - data->pathname = pathname; - data->base = base; if (type == OBJ_BLOB) { if (ls_options & LS_TREE_ONLY) @@ -217,15 +209,15 @@ static int show_tree_default(const struct object_id *oid, struct strbuf *base, { int early; int recurse; - struct show_tree_data data = { 0 }; + enum object_type type = object_type(mode); - early = show_tree_common(&data, &recurse, oid, base, pathname, mode); + early = show_tree_common(&recurse, base, pathname, type); if (early >= 0) return early; - printf("%06o %s %s\t", data.mode, type_name(data.type), - find_unique_abbrev(data.oid, abbrev)); - show_tree_common_default_long(base, pathname, data.base->len); + printf("%06o %s %s\t", mode, type_name(object_type(mode)), + find_unique_abbrev(oid, abbrev)); + show_tree_common_default_long(base, pathname, base->len); return recurse; } @@ -235,16 +227,16 @@ static int show_tree_long(const struct object_id *oid, struct strbuf *base, { int early; int recurse; - struct show_tree_data data = { 0 }; char size_text[24]; + enum object_type type = object_type(mode); - early = show_tree_common(&data, &recurse, oid, base, pathname, mode); + early = show_tree_common(&recurse, base, pathname, type); if (early >= 0) return early; - if (data.type == OBJ_BLOB) { + if (type == OBJ_BLOB) { unsigned long size; - if (oid_object_info(the_repository, data.oid, &size) == OBJ_BAD) + if (oid_object_info(the_repository, oid, &size) == OBJ_BAD) xsnprintf(size_text, sizeof(size_text), "BAD"); else xsnprintf(size_text, sizeof(size_text), @@ -253,9 +245,9 @@ static int show_tree_long(const struct object_id *oid, struct strbuf *base, xsnprintf(size_text, sizeof(size_text), "-"); } - printf("%06o %s %s %7s\t", data.mode, type_name(data.type), - find_unique_abbrev(data.oid, abbrev), size_text); - show_tree_common_default_long(base, pathname, data.base->len); + printf("%06o %s %s %7s\t", mode, type_name(type), + find_unique_abbrev(oid, abbrev), size_text); + show_tree_common_default_long(base, pathname, base->len); return recurse; } @@ -266,9 +258,9 @@ static int show_tree_name_only(const struct object_id *oid, struct strbuf *base, int early; int recurse; const size_t baselen = base->len; - struct show_tree_data data = { 0 }; + enum object_type type = object_type(mode); - early = show_tree_common(&data, &recurse, oid, base, pathname, mode); + early = show_tree_common(&recurse, base, pathname, type); if (early >= 0) return early; @@ -286,9 +278,9 @@ static int show_tree_object(const struct object_id *oid, struct strbuf *base, { int early; int recurse; - struct show_tree_data data = { 0 }; + enum object_type type = object_type(mode); - early = show_tree_common(&data, &recurse, oid, base, pathname, mode); + early = show_tree_common(&recurse, base, pathname, type); if (early >= 0) return early; From patchwork Thu Nov 17 13:48:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 13046903 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 221C2C4332F for ; Thu, 17 Nov 2022 13:48:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239671AbiKQNsg (ORCPT ); Thu, 17 Nov 2022 08:48:36 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57080 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233651AbiKQNs1 (ORCPT ); Thu, 17 Nov 2022 08:48:27 -0500 Received: from mail-ej1-x62b.google.com (mail-ej1-x62b.google.com [IPv6:2a00:1450:4864:20::62b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 386F610BC for ; Thu, 17 Nov 2022 05:48:25 -0800 (PST) Received: by mail-ej1-x62b.google.com with SMTP id f27so5232275eje.1 for ; Thu, 17 Nov 2022 05:48:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=x2kxHpamtwMLqsjvfmYl3fWvGvZoasUSwC7w0oRP9R8=; b=kHlWJeRDctUvsMvvtoz0zTUQPZhOGRW60exSMF35TpeRsH0eziI4gJceG+ZzGPlWem yUvfhSEQJXg63sEv+4h0SKsdhD2sy9qlHnQl45sKLfkBUKBd+9o7Ls5h8NF8CksIT+2o eIJSSC3yC5NtBSoiYHOGHAqdHMgl8cWJOZ2MjCj9Lsh+/dFEINAyivHqgFOoIDHE0t82 oTIn5eTWlWjZiSd5ojmkLCyratfqcUFWG6OY3EmCy7L01pK3t6XjELrJJcNlX88CbnB0 BIfHU0q/8aYNE+iR7jKTYm9jdYe4qD0q5JfEZU3kzwmrHA61wkvrCGjBFvKzqZ5dBvgO RMrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=x2kxHpamtwMLqsjvfmYl3fWvGvZoasUSwC7w0oRP9R8=; b=eNRZ3PPl6CYRw3thCop4x5+p0I16BJQPC03JQnBvN3t2zp7jyEykv4FQwqrPUJ3YHc KeYCes4mvL7sJUN55htDcw6IuIgugjoORFUZunl3olvRMWJppp4XiBPFJiHnR+c2U59P U/ltZrIYSN2uDVVNgEEmaX2NfymKAJ7QkbFd5gstV8785mcpMHMflBz6lyBu8rPavGMu KWIRft7sV4G0VeK972rDrO1yBTmqF2cTtNxJFxQudeBjmb3gZ2LUN6eB51pZzQvWmWLC aRRSQ8dmIcKij0sUjiSRQS0+SJ/OyZ1k2qp58zolwnWskD3YE+RRvJjoX4OHGO3mZrmH P/QA== X-Gm-Message-State: ANoB5pkbnzcVHafZj4KZ2gxFZ5Uvsxi7gN6uJHyEKmjutFBmz4KZX2y9 dxCqI5hSSp0ou4fq1skP9jQW5dJi8g4COg== X-Google-Smtp-Source: AA0mqf46pSnX2FPRHgJsp9GZciH4ik255VR51KAmpJ9oT1YAcTbkgHcbUeDVWWYtXAxOuVlxrJdxaw== X-Received: by 2002:a17:906:1953:b0:7a2:36c7:31eb with SMTP id b19-20020a170906195300b007a236c731ebmr2045645eje.491.1668692903382; Thu, 17 Nov 2022 05:48:23 -0800 (PST) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id m27-20020a170906581b00b007ad9adabcd4sm379257ejq.213.2022.11.17.05.48.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Nov 2022 05:48:22 -0800 (PST) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Taylor Blau , Teng Long , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= Subject: [RFC PATCH 2/4] ls-tree: use a "struct options" Date: Thu, 17 Nov 2022 14:48:15 +0100 Message-Id: X-Mailer: git-send-email 2.38.0.1473.g172bcc0511c In-Reply-To: References: <20221117113023.65865-1-tenglong.tl@alibaba-inc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org As a first step towards being able to turn this code into an API some day let's change the "static" options in builtin/ls-tree.c into a "struct ls_tree_options" that can be constructed dynamically without the help of parse_options(). Because we're now using non-static variables for this we'll need to clear_pathspec() at the end of cmd_ls_tree(), least various tests start failing under SANITIZE=leak. The memory leak was already there before, now it's just being brought to the surface. Signed-off-by: Ævar Arnfjörð Bjarmason --- builtin/ls-tree.c | 203 ++++++++++++++++++++++++++-------------------- 1 file changed, 116 insertions(+), 87 deletions(-) diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index cbb6782f9a5..54f7b604cb7 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -14,37 +14,11 @@ #include "parse-options.h" #include "pathspec.h" -static int line_termination = '\n'; -#define LS_RECURSIVE 1 -#define LS_TREE_ONLY (1 << 1) -#define LS_SHOW_TREES (1 << 2) -static int abbrev; -static int ls_options; -static struct pathspec pathspec; -static int chomp_prefix; -static const char *ls_tree_prefix; -static const char *format; -struct show_tree_data { - unsigned mode; - enum object_type type; - const struct object_id *oid; - const char *pathname; - struct strbuf *base; -}; - static const char * const ls_tree_usage[] = { N_("git ls-tree [] [...]"), NULL }; -static enum ls_tree_cmdmode { - MODE_DEFAULT = 0, - MODE_LONG, - MODE_NAME_ONLY, - MODE_NAME_STATUS, - MODE_OBJECT_ONLY, -} cmdmode; - static void expand_objectsize(struct strbuf *line, const struct object_id *oid, const enum object_type type, unsigned int padded) { @@ -64,10 +38,39 @@ static void expand_objectsize(struct strbuf *line, const struct object_id *oid, } } +struct ls_tree_options { + int line_termination; + int abbrev; + enum ls_tree_path_options { + LS_RECURSIVE = 1 << 0, + LS_TREE_ONLY = 1 << 1, + LS_SHOW_TREES = 1 << 2, + } ls_options; + struct pathspec pathspec; + int chomp_prefix; + const char *ls_tree_prefix; + const char *format; +}; + +struct show_tree_data { + unsigned mode; + enum object_type type; + const struct object_id *oid; + const char *pathname; + struct strbuf *base; +}; + +struct show_tree_data_cb { + struct ls_tree_options *options; + struct show_tree_data *data; +}; + static size_t expand_show_tree(struct strbuf *sb, const char *start, void *context) { - struct show_tree_data *data = context; + struct show_tree_data_cb *wrapper = context; + struct ls_tree_options *options = wrapper->options; + struct show_tree_data *data = wrapper->data; const char *end; const char *p; unsigned int errlen; @@ -92,10 +95,10 @@ static size_t expand_show_tree(struct strbuf *sb, const char *start, } else if (skip_prefix(start, "(objectsize)", &p)) { expand_objectsize(sb, data->oid, data->type, 0); } else if (skip_prefix(start, "(objectname)", &p)) { - strbuf_add_unique_abbrev(sb, data->oid, abbrev); + strbuf_add_unique_abbrev(sb, data->oid, options->abbrev); } else if (skip_prefix(start, "(path)", &p)) { const char *name = data->base->buf; - const char *prefix = chomp_prefix ? ls_tree_prefix : NULL; + const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; struct strbuf quoted = STRBUF_INIT; struct strbuf sbuf = STRBUF_INIT; strbuf_addstr(data->base, data->pathname); @@ -111,18 +114,19 @@ static size_t expand_show_tree(struct strbuf *sb, const char *start, return len; } -static int show_recursive(const char *base, size_t baselen, const char *pathname) +static int show_recursive(struct ls_tree_options *options, const char *base, + size_t baselen, const char *pathname) { int i; - if (ls_options & LS_RECURSIVE) + if (options->ls_options & LS_RECURSIVE) return 1; - if (!pathspec.nr) + if (!options->pathspec.nr) return 0; - for (i = 0; i < pathspec.nr; i++) { - const char *spec = pathspec.items[i].match; + for (i = 0; i < options->pathspec.nr; i++) { + const char *spec = options->pathspec.items[i].match; size_t len, speclen; if (strncmp(base, spec, baselen)) @@ -142,13 +146,13 @@ static int show_recursive(const char *base, size_t baselen, const char *pathname } static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, - const char *pathname, unsigned mode, void *context UNUSED) + const char *pathname, unsigned mode, void *context) { + struct ls_tree_options *options = context; size_t baselen; int recurse = 0; struct strbuf sb = STRBUF_INIT; enum object_type type = object_type(mode); - struct show_tree_data data = { .mode = mode, .type = type, @@ -156,81 +160,89 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, .pathname = pathname, .base = base, }; + struct show_tree_data_cb cb_data = { + .data = &data, + .options = options, + }; - if (type == OBJ_TREE && show_recursive(base->buf, base->len, pathname)) + if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname)) recurse = READ_TREE_RECURSIVE; - if (type == OBJ_TREE && recurse && !(ls_options & LS_SHOW_TREES)) + if (type == OBJ_TREE && recurse && !(options->ls_options & LS_SHOW_TREES)) return recurse; - if (type == OBJ_BLOB && (ls_options & LS_TREE_ONLY)) + if (type == OBJ_BLOB && (options->ls_options & LS_TREE_ONLY)) return 0; baselen = base->len; - strbuf_expand(&sb, format, expand_show_tree, &data); - strbuf_addch(&sb, line_termination); + strbuf_expand(&sb, options->format, expand_show_tree, &cb_data); + strbuf_addch(&sb, options->line_termination); fwrite(sb.buf, sb.len, 1, stdout); strbuf_release(&sb); strbuf_setlen(base, baselen); return recurse; } -static int show_tree_common(int *recurse, struct strbuf *base, - const char *pathname, enum object_type type) +static int show_tree_common(struct ls_tree_options *options, int *recurse, + struct strbuf *base, const char *pathname, + enum object_type type) { int ret = -1; *recurse = 0; if (type == OBJ_BLOB) { - if (ls_options & LS_TREE_ONLY) + if (options->ls_options & LS_TREE_ONLY) ret = 0; } else if (type == OBJ_TREE && - show_recursive(base->buf, base->len, pathname)) { + show_recursive(options, base->buf, base->len, pathname)) { *recurse = READ_TREE_RECURSIVE; - if (!(ls_options & LS_SHOW_TREES)) + if (!(options->ls_options & LS_SHOW_TREES)) ret = *recurse; } return ret; } -static void show_tree_common_default_long(struct strbuf *base, +static void show_tree_common_default_long(struct ls_tree_options *options, + struct strbuf *base, const char *pathname, const size_t baselen) { strbuf_addstr(base, pathname); write_name_quoted_relative(base->buf, - chomp_prefix ? ls_tree_prefix : NULL, stdout, - line_termination); + options->chomp_prefix ? options->ls_tree_prefix : NULL, stdout, + options->line_termination); strbuf_setlen(base, baselen); } static int show_tree_default(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, - void *context UNUSED) + void *context) { + struct ls_tree_options *options = context; int early; int recurse; enum object_type type = object_type(mode); - early = show_tree_common(&recurse, base, pathname, type); + early = show_tree_common(options, &recurse, base, pathname, type); if (early >= 0) return early; printf("%06o %s %s\t", mode, type_name(object_type(mode)), - find_unique_abbrev(oid, abbrev)); - show_tree_common_default_long(base, pathname, base->len); + find_unique_abbrev(oid, options->abbrev)); + show_tree_common_default_long(options, base, pathname, base->len); return recurse; } static int show_tree_long(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, - void *context UNUSED) + void *context) { + struct ls_tree_options *options = context; int early; int recurse; char size_text[24]; enum object_type type = object_type(mode); - early = show_tree_common(&recurse, base, pathname, type); + early = show_tree_common(options, &recurse, base, pathname, type); if (early >= 0) return early; @@ -246,48 +258,58 @@ static int show_tree_long(const struct object_id *oid, struct strbuf *base, } printf("%06o %s %s %7s\t", mode, type_name(type), - find_unique_abbrev(oid, abbrev), size_text); - show_tree_common_default_long(base, pathname, base->len); + find_unique_abbrev(oid, options->abbrev), size_text); + show_tree_common_default_long(options, base, pathname, base->len); return recurse; } static int show_tree_name_only(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, - void *context UNUSED) + void *context) { + struct ls_tree_options *options = context; int early; int recurse; const size_t baselen = base->len; enum object_type type = object_type(mode); - early = show_tree_common(&recurse, base, pathname, type); + early = show_tree_common(options, &recurse, base, pathname, type); if (early >= 0) return early; strbuf_addstr(base, pathname); write_name_quoted_relative(base->buf, - chomp_prefix ? ls_tree_prefix : NULL, - stdout, line_termination); + options->chomp_prefix ? options->ls_tree_prefix : NULL, + stdout, options->line_termination); strbuf_setlen(base, baselen); return recurse; } static int show_tree_object(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, - void *context UNUSED) + void *context) { + struct ls_tree_options *options = context; int early; int recurse; enum object_type type = object_type(mode); - early = show_tree_common(&recurse, base, pathname, type); + early = show_tree_common(options, &recurse, base, pathname, type); if (early >= 0) return early; - printf("%s%c", find_unique_abbrev(oid, abbrev), line_termination); + printf("%s%c", find_unique_abbrev(oid, options->abbrev), options->line_termination); return recurse; } +enum ls_tree_cmdmode { + MODE_DEFAULT = 0, + MODE_LONG, + MODE_NAME_ONLY, + MODE_NAME_STATUS, + MODE_OBJECT_ONLY, +}; + struct ls_tree_cmdmode_to_fmt { enum ls_tree_cmdmode mode; const char *const fmt; @@ -327,14 +349,18 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) struct tree *tree; int i, full_tree = 0; read_tree_fn_t fn = NULL; + enum ls_tree_cmdmode cmdmode = MODE_DEFAULT; + struct ls_tree_options options = { + .line_termination = '\n', + }; const struct option ls_tree_options[] = { - OPT_BIT('d', NULL, &ls_options, N_("only show trees"), + OPT_BIT('d', NULL, &options.ls_options, N_("only show trees"), LS_TREE_ONLY), - OPT_BIT('r', NULL, &ls_options, N_("recurse into subtrees"), + OPT_BIT('r', NULL, &options.ls_options, N_("recurse into subtrees"), LS_RECURSIVE), - OPT_BIT('t', NULL, &ls_options, N_("show trees when recursing"), + OPT_BIT('t', NULL, &options.ls_options, N_("show trees when recursing"), LS_SHOW_TREES), - OPT_SET_INT('z', NULL, &line_termination, + OPT_SET_INT('z', NULL, &options.line_termination, N_("terminate entries with NUL byte"), 0), OPT_CMDMODE('l', "long", &cmdmode, N_("include object size"), MODE_LONG), @@ -344,29 +370,30 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) MODE_NAME_STATUS), OPT_CMDMODE(0, "object-only", &cmdmode, N_("list only objects"), MODE_OBJECT_ONLY), - OPT_SET_INT(0, "full-name", &chomp_prefix, + OPT_SET_INT(0, "full-name", &options.chomp_prefix, N_("use full path names"), 0), OPT_BOOL(0, "full-tree", &full_tree, N_("list entire tree; not just current directory " "(implies --full-name)")), - OPT_STRING_F(0, "format", &format, N_("format"), + OPT_STRING_F(0, "format", &options.format, N_("format"), N_("format to use for the output"), PARSE_OPT_NONEG), - OPT__ABBREV(&abbrev), + OPT__ABBREV(&options.abbrev), OPT_END() }; struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format; + int ret; git_config(git_default_config, NULL); - ls_tree_prefix = prefix; + options.ls_tree_prefix = prefix; if (prefix) - chomp_prefix = strlen(prefix); + options.chomp_prefix = strlen(prefix); argc = parse_options(argc, argv, prefix, ls_tree_options, ls_tree_usage, 0); if (full_tree) { - ls_tree_prefix = prefix = NULL; - chomp_prefix = 0; + options.ls_tree_prefix = prefix = NULL; + options.chomp_prefix = 0; } /* * We wanted to detect conflicts between --name-only and @@ -378,10 +405,10 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) /* -d -r should imply -t, but -d by itself should not have to. */ if ( (LS_TREE_ONLY|LS_RECURSIVE) == - ((LS_TREE_ONLY|LS_RECURSIVE) & ls_options)) - ls_options |= LS_SHOW_TREES; + ((LS_TREE_ONLY|LS_RECURSIVE) & options.ls_options)) + options.ls_options |= LS_SHOW_TREES; - if (format && cmdmode) + if (options.format && cmdmode) usage_msg_opt( _("--format can't be combined with other format-altering options"), ls_tree_usage, ls_tree_options); @@ -396,13 +423,13 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) * cannot be lifted until it is converted to use * match_pathspec() or tree_entry_interesting() */ - parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC & - ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL), + parse_pathspec(&options.pathspec, PATHSPEC_ALL_MAGIC & + ~(PATHSPEC_FROMTOP | PATHSPEC_LITERAL), PATHSPEC_PREFER_CWD, prefix, argv + 1); - for (i = 0; i < pathspec.nr; i++) - pathspec.items[i].nowildcard_len = pathspec.items[i].len; - pathspec.has_wildcard = 0; + for (i = 0; i < options.pathspec.nr; i++) + options.pathspec.items[i].nowildcard_len = options.pathspec.items[i].len; + options.pathspec.has_wildcard = 0; tree = parse_tree_indirect(&oid); if (!tree) die("not a tree object"); @@ -412,11 +439,11 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) */ while (m2f) { if (!m2f->fmt) { - fn = format ? show_tree_fmt : show_tree_default; - } else if (format && !strcmp(format, m2f->fmt)) { + fn = options.format ? show_tree_fmt : show_tree_default; + } else if (options.format && !strcmp(options.format, m2f->fmt)) { cmdmode = m2f->mode; fn = m2f->fn; - } else if (!format && cmdmode == m2f->mode) { + } else if (!options.format && cmdmode == m2f->mode) { fn = m2f->fn; } else { m2f++; @@ -425,5 +452,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) break; } - return !!read_tree(the_repository, tree, &pathspec, fn, NULL); + ret = !!read_tree(the_repository, tree, &options.pathspec, fn, &options); + clear_pathspec(&options.pathspec); + return ret; } From patchwork Thu Nov 17 13:48:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 13046902 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4438CC4332F for ; Thu, 17 Nov 2022 13:48:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239336AbiKQNsb (ORCPT ); Thu, 17 Nov 2022 08:48:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57078 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234267AbiKQNs1 (ORCPT ); Thu, 17 Nov 2022 08:48:27 -0500 Received: from mail-ej1-x635.google.com (mail-ej1-x635.google.com [IPv6:2a00:1450:4864:20::635]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1E4371170 for ; Thu, 17 Nov 2022 05:48:26 -0800 (PST) Received: by mail-ej1-x635.google.com with SMTP id gv23so5208811ejb.3 for ; Thu, 17 Nov 2022 05:48:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=GBoVgeRvMP2Jx+grqy8u/c1+w3b651JLVP4QJ8dbVg8=; b=QmyQ0+KxG9m/gmiktfJDNpYYt6qr+Mt/btWa2a68cIyyak25O6Sk1LY0YzrJzPPyGa zJoXUtrvNsXI86vf300r6Q8dOPUPQ5AeIvyEf8brPGgoO4s+M2eJXUo/dVL5CDAJy542 ofJeUs1oWvUsvxiuRdIwZhzWyMl/ZwWgjm2H5zW3306xXg3FI0fSXJhKAuThVZtSohnt J8uZQzAmzWTGVJOtUxfC51WvlhMdqxSle7Rfhiph7TQ8ufivSQ6cN5HlTRJ7cg44RsH7 OBpW+OAr2lLnY/ju5UJw5nlc8XcDE3PHzY+5K5cIEu7PWonYIY4BCvqVeS77jkfS9Bgs orlA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=GBoVgeRvMP2Jx+grqy8u/c1+w3b651JLVP4QJ8dbVg8=; b=24ShsKegwWpoPtHVtJ+9l1IvXDE4VDT5vq+PFMVfXIKwWIpnWqs9xos0pTMiHr/f2l NqzUgDksORio5LvW0zkPtWed+gQCdDD+QImd8MudgrzeAnt6xuv5jRTCLMjgrFllAeKI HmIgj1lKd/n4BT8MheCvxoWqmDa9j0CWsdFhgPftYoNL5iV9Qj3YY3CJCIk4fQGIY7pX xRz9GjB5HJruQj11NHDScoyzw+omY/pLcDwPI/uJsNk2qY1xlynVW2mz8H3TYueSnRf5 tdj3DlS11UFPuopNVPGqDzVa7ob2lC7jsT5KzdE+MuHWJnKR1K16DuFQTZu9Bz9HFjx4 jmeg== X-Gm-Message-State: ANoB5pnMX2/82qN1s5KkGfmpZ61ZCO5uhF90vqaeGU1cTDLZxFa33T5C hI7wEGX1uprSexVeWsQpvfC9B1qMWY575w== X-Google-Smtp-Source: AA0mqf54ZMfqzrl64K45jRCD9Pyp7pUq9ml/SH9JtYyvKGfENP9Sbf5bw3xGdME4kWPh8HyyxBeFLA== X-Received: by 2002:a17:906:ef1:b0:78d:260d:a6e4 with SMTP id x17-20020a1709060ef100b0078d260da6e4mr2155305eji.93.1668692904306; Thu, 17 Nov 2022 05:48:24 -0800 (PST) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id m27-20020a170906581b00b007ad9adabcd4sm379257ejq.213.2022.11.17.05.48.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Nov 2022 05:48:23 -0800 (PST) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Taylor Blau , Teng Long , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= Subject: [RFC PATCH 3/4] ls-tree: fold "show_tree_data" into "cb" struct Date: Thu, 17 Nov 2022 14:48:16 +0100 Message-Id: X-Mailer: git-send-email 2.38.0.1473.g172bcc0511c In-Reply-To: References: <20221117113023.65865-1-tenglong.tl@alibaba-inc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org After the the preceding two commits the only user of the "show_tree_data" struct needed it along with the "options" member, let's instead fold all of that into a "show_tree_data" struct that we'll use only for that callback. Signed-off-by: Ævar Arnfjörð Bjarmason --- builtin/ls-tree.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index 54f7b604cb7..da664eecfb9 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -53,6 +53,7 @@ struct ls_tree_options { }; struct show_tree_data { + struct ls_tree_options *options; unsigned mode; enum object_type type; const struct object_id *oid; @@ -60,17 +61,11 @@ struct show_tree_data { struct strbuf *base; }; -struct show_tree_data_cb { - struct ls_tree_options *options; - struct show_tree_data *data; -}; - static size_t expand_show_tree(struct strbuf *sb, const char *start, void *context) { - struct show_tree_data_cb *wrapper = context; - struct ls_tree_options *options = wrapper->options; - struct show_tree_data *data = wrapper->data; + struct show_tree_data *data = context; + struct ls_tree_options *options = data->options; const char *end; const char *p; unsigned int errlen; @@ -153,17 +148,14 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, int recurse = 0; struct strbuf sb = STRBUF_INIT; enum object_type type = object_type(mode); - struct show_tree_data data = { + struct show_tree_data cb_data = { + .options = options, .mode = mode, .type = type, .oid = oid, .pathname = pathname, .base = base, }; - struct show_tree_data_cb cb_data = { - .data = &data, - .options = options, - }; if (type == OBJ_TREE && show_recursive(options, base->buf, base->len, pathname)) recurse = READ_TREE_RECURSIVE; From patchwork Thu Nov 17 13:48:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= X-Patchwork-Id: 13046904 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB5A9C433FE for ; Thu, 17 Nov 2022 13:48:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239997AbiKQNsm (ORCPT ); Thu, 17 Nov 2022 08:48:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57188 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234810AbiKQNsb (ORCPT ); Thu, 17 Nov 2022 08:48:31 -0500 Received: from mail-ed1-x534.google.com (mail-ed1-x534.google.com [IPv6:2a00:1450:4864:20::534]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D547B1A5 for ; Thu, 17 Nov 2022 05:48:26 -0800 (PST) Received: by mail-ed1-x534.google.com with SMTP id 21so2612833edv.3 for ; Thu, 17 Nov 2022 05:48:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FoUMF7pET/Mzp377uQSgQS6Fa1wFTQJzJqfEg0bz9hg=; b=GBZFRJQd+FLfhPs2qCzUuuQyYk5EAq5azbgguZbKOQRawZA8tBeM3B5Nhql/Rp73FV wdhkojXArm0Kh2bEbWsen62gcUCyWTfa3Pig5q1OKbfZnsGPgyoH56GWJg+8RDQYz2mg wX46Rir/CEBsYKbbJXKPthJwcIsIQkz5MMcRndeduJEchZjFpRe3uroRWMRTdWmdJT8T CYs6Iyf0jXmc4oQIIgyNozuNGFs4mrc4lm+ZVc19pUX2aC0Wkq2gN5JttNzB8ir0dfs4 HvMMnN0GS2ryhSFDNzg7spvQcJwRFPKJcj98bs7m0jtdiQj+rTH41uc/IaL+fxrlv8YC fLJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FoUMF7pET/Mzp377uQSgQS6Fa1wFTQJzJqfEg0bz9hg=; b=b1TXJgRjngEWZ/xoI0ep6h+HQ+ywNqerilrld17R5K8hTCOuqlR3wKQtPxKqv/uaIN TqGWiTjxUh1wJCmh+6a9EXwKGo7cbAPdLI+rlger7c8t7jZjO4o54W3pR8yzoRGDZ3nx Yd16fAKKbhurtxHhbCFQCDuY9Xz/UqzOjRE5GI1/R7AcCbbqZxnYHnmJ8+tYiQd7lz+Y gQa8sXbD8DQ5jcMxhivLTWJMaCVWU/45h9JeGzhyi8MLVKSsl3Kolcv7NqJ/3f7wyHob jA34HjBgdyc9ZI22y9S9BeNoX8HucIRZUFyAH+Ltx42lrvDAAclK7RfVnMrK2aFRewy7 HY1A== X-Gm-Message-State: ANoB5plu2ZKKGyjfFzsMgHQ3zhrLYjmV80nhdYp6fix5zMWZ34zmWG/w JfAkp6d0MEEa3zgt1bgh3bvx9afVbCHMJQ== X-Google-Smtp-Source: AA0mqf73HkcE/wKdJOO5A/giwzeoTKnanWj1UPA+cZfT2bl2Z1z3Ga4p090YzChOTo+Nc6Mwydhrbg== X-Received: by 2002:a05:6402:444a:b0:459:401:c23e with SMTP id o10-20020a056402444a00b004590401c23emr2344937edb.23.1668692905129; Thu, 17 Nov 2022 05:48:25 -0800 (PST) Received: from vm.nix.is (vm.nix.is. [2a01:4f8:120:2468::2]) by smtp.gmail.com with ESMTPSA id m27-20020a170906581b00b007ad9adabcd4sm379257ejq.213.2022.11.17.05.48.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 17 Nov 2022 05:48:24 -0800 (PST) From: =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= To: git@vger.kernel.org Cc: Taylor Blau , Teng Long , =?utf-8?b?w4Z2YXIgQXJuZmrDtnLDsCBCamFybWFzb24=?= Subject: [RFC PATCH 4/4] ls-tree: make "line_termination" less generic Date: Thu, 17 Nov 2022 14:48:17 +0100 Message-Id: X-Mailer: git-send-email 2.38.0.1473.g172bcc0511c In-Reply-To: References: <20221117113023.65865-1-tenglong.tl@alibaba-inc.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: git@vger.kernel.org The "ls-tree" command isn't capable of ending "lines" with anything except '\n' or '\0', and in the latter case we can avoid calling write_name_quoted_relative() entirely. Let's do that, less for optimization and more for clarity, the write_name_quoted_relative() API itself does much the same thing. Signed-off-by: Ævar Arnfjörð Bjarmason --- builtin/ls-tree.c | 58 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/builtin/ls-tree.c b/builtin/ls-tree.c index da664eecfb9..a743959f2b3 100644 --- a/builtin/ls-tree.c +++ b/builtin/ls-tree.c @@ -39,7 +39,7 @@ static void expand_objectsize(struct strbuf *line, const struct object_id *oid, } struct ls_tree_options { - int line_termination; + unsigned null_termination:1; int abbrev; enum ls_tree_path_options { LS_RECURSIVE = 1 << 0, @@ -166,7 +166,7 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base, baselen = base->len; strbuf_expand(&sb, options->format, expand_show_tree, &cb_data); - strbuf_addch(&sb, options->line_termination); + strbuf_addch(&sb, options->null_termination ? '\0' : '\n'); fwrite(sb.buf, sb.len, 1, stdout); strbuf_release(&sb); strbuf_setlen(base, baselen); @@ -198,10 +198,22 @@ static void show_tree_common_default_long(struct ls_tree_options *options, const char *pathname, const size_t baselen) { + const char *prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; + strbuf_addstr(base, pathname); - write_name_quoted_relative(base->buf, - options->chomp_prefix ? options->ls_tree_prefix : NULL, stdout, - options->line_termination); + + if (options->null_termination) { + struct strbuf sb = STRBUF_INIT; + const char *name = relative_path(base->buf, prefix, &sb); + + fputs(name, stdout); + fputc('\0', stdout); + + strbuf_release(&sb); + } else { + write_name_quoted_relative(base->buf, prefix, stdout, '\n'); + } + strbuf_setlen(base, baselen); } @@ -264,15 +276,25 @@ static int show_tree_name_only(const struct object_id *oid, struct strbuf *base, int recurse; const size_t baselen = base->len; enum object_type type = object_type(mode); + const char *prefix; early = show_tree_common(options, &recurse, base, pathname, type); if (early >= 0) return early; + prefix = options->chomp_prefix ? options->ls_tree_prefix : NULL; strbuf_addstr(base, pathname); - write_name_quoted_relative(base->buf, - options->chomp_prefix ? options->ls_tree_prefix : NULL, - stdout, options->line_termination); + if (options->null_termination) { + struct strbuf sb = STRBUF_INIT; + const char *name = relative_path(base->buf, prefix, &sb); + + fputs(name, stdout); + fputc('\0', stdout); + + strbuf_release(&sb); + } else { + write_name_quoted_relative(base->buf, prefix, stdout, '\n'); + } strbuf_setlen(base, baselen); return recurse; } @@ -285,12 +307,19 @@ static int show_tree_object(const struct object_id *oid, struct strbuf *base, int early; int recurse; enum object_type type = object_type(mode); + const char *str; early = show_tree_common(options, &recurse, base, pathname, type); if (early >= 0) return early; - printf("%s%c", find_unique_abbrev(oid, options->abbrev), options->line_termination); + str = find_unique_abbrev(oid, options->abbrev); + if (options->null_termination) { + fputs(str, stdout); + fputc('\0', stdout); + } else { + puts(str); + } return recurse; } @@ -342,9 +371,8 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) int i, full_tree = 0; read_tree_fn_t fn = NULL; enum ls_tree_cmdmode cmdmode = MODE_DEFAULT; - struct ls_tree_options options = { - .line_termination = '\n', - }; + int null_termination = 0; + struct ls_tree_options options = { 0 }; const struct option ls_tree_options[] = { OPT_BIT('d', NULL, &options.ls_options, N_("only show trees"), LS_TREE_ONLY), @@ -352,8 +380,8 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) LS_RECURSIVE), OPT_BIT('t', NULL, &options.ls_options, N_("show trees when recursing"), LS_SHOW_TREES), - OPT_SET_INT('z', NULL, &options.line_termination, - N_("terminate entries with NUL byte"), 0), + OPT_BOOL('z', NULL, &null_termination, + N_("terminate entries with NUL byte")), OPT_CMDMODE('l', "long", &cmdmode, N_("include object size"), MODE_LONG), OPT_CMDMODE(0, "name-only", &cmdmode, N_("list only filenames"), @@ -383,6 +411,8 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix) argc = parse_options(argc, argv, prefix, ls_tree_options, ls_tree_usage, 0); + options.null_termination = null_termination; + if (full_tree) { options.ls_tree_prefix = prefix = NULL; options.chomp_prefix = 0;