Junio C Hamano <gitster@xxxxxxxxx> 于2022年7月12日周二 06:11写道: > > "ZheNing Hu via GitGitGadget" <gitgitgadget@xxxxxxxxx> writes: > > > From: ZheNing Hu <adlternative@xxxxxxxxx> > > > > 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. > > +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) > > +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. > > +{ > > + 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. > > + 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. > > + 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