胡哲宁 <adlternative@xxxxxxxxx> writes: >> OK. When show_stage is set, skipping_duplicates is automatically >> turned off (and show_unmerged is automatically covered as it turns >> show_stage on automatically). So this feature has really become >> "are we showing only names, and if so, did we show an entry of the >> same name before?". > Yeah,showing only names,so I yesterday ask such question :) >> >> > if (!show_unmerged || ce_stage(ce)) >> > show_ce(repo, dir, ce, fullname.buf, >> > ce_stage(ce) ? tag_unmerged : >> > (ce_skip_worktree(ce) ? tag_skip_worktree : >> > tag_cached)); >> > + if (show_cached && skipping_duplicates) >> > + last_shown_ce = ce; >> >> The code that calls show_ce() belonging to a totally separate if() >> statement makes my stomach hurt---how are we going to guarantee that >> "last shown" really will keep track of what was shown last? >> >> Shouldn't the above be more like this? >> >> - if (!show_unmerged || ce_stage(ce)) >> + if (!show_unmerged || ce_stage(ce)) { >> show_ce(repo, dir, ce, fullname.buf, >> ce_stage(ce) ? tag_unmerged : >> (ce_skip_worktree(ce) ? tag_skip_worktree : >> tag_cached)); >> + last_shown_ce = ce; >> + } >> > well,I am also thinking about this question :"last_shown_ce" is not true > last shown ce,but may be If "last_shown_ce" truly seen every last shown > ce ,We may need more cumbersome logic to make the program correct. > I have tried the processing method of your above code before, but found > that some errors may have occurred. I think judicious use of "goto" without introducing the last_shown would probably result in a much more maintainable code. It may look somewhat like so: for (i = 0; i < repo->index->cache_nr; i++) { const struct cache_entry *ce = repo->index->cache[i]; struct stat st; int stat_err; construct_fullname(&fullname, repo, ce); if ((dir->flags & DIR_SHOW_IGNORED) && !ce_excluded(dir, repo->index, fullname.buf, ce)) continue; if (ce->ce_flags & CE_UPDATE) continue; if ((show_cached || show_stage) && (!show_unmerged || ce_stage(ce))) { show_ce(repo, dir, ce, fullname.buf, ce_stage(ce) ? tag_unmerged : (ce_skip_worktree(ce) ? tag_skip_worktree : tag_cached)); if (skip_duplicates) goto skip_to_next_name; } if (!show_deleted && !show_modified) continue; if (ce_skip_worktree(ce)) continue; stat_err = lstat(fullname.buf, &st); if (stat_err && (errno != ENOENT && errno != ENOTDIR)) error_errno("cannot lstat '%s'", fullname.buf); if (show_deleted) { show_ce(repo, dir, ce, fullname.buf, tag_removed); if (skip_duplicates) goto skip_to_next_name; } if (show_modified && (stat_err || ie_modified(repo->index, ce, &st, 0))) show_ce(repo, dir, ce, fullname.buf, tag_modified); continue; skip_to_next_name: { int j; const struct cache_entry **cache = repo->index->cache; for (j = i + 1; j < repo->index->cache_nr; j++) if (strcmp(ce->ce_name, cache[j]->ce_name)) break; i = j - 1; /* compensate for outer for loop */ } }