Re: [PATCH v6] ls-files: introduce "--format" option
- From
ZheNing Hu <adlternative@gmail.com>
- Date
- Jul 12, 2022, 13:53 UTC
- Message-ID
- <CAOLTT8RSo83ZBXbT_MLigD946_xHjnX-aS76D_K7=ScbMR=nYw@mail.gmail.com>
- In-Reply-To
- <xmqqleszl2p0.fsf@gitster.g>
Junio C Hamano <gitster@pobox.com> 于2022年7月12日周二 06:11写道:
Show 26 quoted lines
> > "ZheNing Hu via GitGitGadget" <gitgitgadget@gmail.com> writes: > > > From: ZheNing Hu <adlternative@gmail.com> > > > > Add a new option --format that output index enties ... > > Let's quote the options and use the Oxford comma. > > ls-files: introduce "--format" option > > Add a new option "--format" that outputs index entries in a > custom format, taking inspiration from the option with the same > name in the `git ls-tree` command. > > "--format" cannot used with "-s", "-o", "-k", "-t", "--resolve-undo", > "--deduplicate", and "--eol". > > > +It is possible to print in a custom format by using the `--format` > > +option, which is able to interpolate different fields using > > So we use the term "field" to mean different piece of information we > can present. The definition of what fields are available come later > and the presentation order is a bit awkward, but hopefully the text > is understandable as-is. >
OK.
Show 15 quoted lines
> > +a `%(fieldname)` notation. For example, if you only care about the > > +"objectname" and "path" fields, you can execute with a specific > > +"--format" like > > + > > + git ls-files --format='%(objectname) %(path)' > > And the example makes it pretty clear. OK. > > > +FIELD NAMES > > +----------- > > +Various values from structured fields can be used to interpolate > > Are we dealing with unstructured fields, too? If not, let's drop > "structured". >
OK (copy from git-ls-tree.txt too)
Show 13 quoted lines
> > +into the resulting output. For each outputting line, the following > > +names can be used: > > "outputting line" sounds like a non language. > > > The way each path is shown can be customized by using the > `--format=<format>` option, where the %(fieldname) in the > <format> string for various aspects of the index entry are > interpolated. The following "fieldname" are understood: > > perhaps? >
This will indeed be better.
Show 27 quoted lines
> > +{
> > + struct show_index_data *data = context;
> > + const char *end;
> > + const char *p;
> > + size_t len = strbuf_expand_literal_cb(sb, start, NULL);
> > + struct stat st;
> > +
> > + if (len)
> > + return len;
> > + if (*start != '(')
> > + die(_("bad ls-files format: element '%s' "
> > + "does not start with '('"), start);
> > +
> > + end = strchr(start + 1, ')');
> > + if (!end)
> > + die(_("bad ls-files format: element '%s'"
> > + "does not end in ')'"), start);
> > +
> > + len = end - start + 1;
> > + if (skip_prefix(start, "(objectmode)", &p))
>
>
> Using skip_prefix() not for the purpose of skipping (notice that
> nobody uses p at all) is ugly. We already computed start and end
> (hence the length), so we should be able to do much better than
> this.
>Agree. I check the parsing format part of ref-filter.c, we just need to find the atom's begin pos and end pos, then we can use memcmp() to know what's the type of atom.
> But let's let it pass, as it was copy-pasted from existing code in > ls-tree.c::expand_show_tree(). >
Yeah, maybe we can optimize it later.
Show 28 quoted lines
> > + else if (skip_prefix(start, "(eolinfo:index)", &p) &&
> > + S_ISREG(data->ce->ce_mode))
> > + strbuf_addstr(sb, get_cached_convert_stats_ascii(data->istate,
> > + data->ce->name));
>
> This is outright wrong, isn't it?
>
> It is unlikely to see such a trivial error in the 6th round of a
> series after other reviewers looked at it many times, so perhaps I
> am missing something? Or perhaps this is a new code added in this
> round.
>
> If you ask for %(eolinfo:index) for an index entry that is not a
> regular file, this "else if" will not trigger, and the control will
> eventually fall through to hit "bad ls-files format" but what you
> detected is not a bad format at all. Once the skip_prefix() hits,
> you should be committed to handle that "field" and never let the
> other choices in this if/elif/ cascade to see it.
>
> It is OK to interpolate %(eolinfo:index) to an empty string for a
> gitlink and a symbolic link, but the right way to do so would
> probably be:
>
> else if (skip_prefix(start, "(eolinfo:index)", &p) {
> if (S_ISREG(data->ce->ce_mode))
> strbuf_addstr(...);
> } else ...
>Yeah, but we would use "{", "}" again, so just revert this code to v5,
which uses a
wrap function.Show 19 quoted lines
> > + else if (skip_prefix(start, "(eolinfo:worktree)", &p) && > > + !lstat(data->pathname, &st) && S_ISREG(st.st_mode)) > > + strbuf_addstr(sb, get_wt_convert_stats_ascii(data->pathname)); > > Likewise. > > > +test_expect_success 'setup' ' > > + echo o1 >o1 && > > + echo o2 >o2 && > > + git add o1 o2 && > > + git add --chmod +x o1 && > > + git commit -m base > > +' > > Apparently, this set-up is too trivial to uncover the above bug that > can be spotted in 10 seconds of staring at the code. Perhaps add a > symbolic link (use "git update-index --cacheinfo" and you do not > have to worry about Windows), a subdirectory and a submodule? >
Ah, Just looking at the c code, I took a long time (more than 10 minutes) to find out where the mistake was. But yeah, use a subdirectory can quickly meet the error, so I need to add more cases here.
Thanks for your review.
ZheNing Hu