ls-tree: split up "fast path" callbacks

Make the various if/else in the callbacks for the "fast path" a lot easier to read by just using common functions for the parts that are common, and have per-format callbacks for those parts that are different. Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com> Signed-off-by: Teng Long <dyroneteng@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ævar Arnfjörð Bjarmason committed Mar 23, 2022 at 17:13 UTC 9c4d58ff2c385f49585197c8650356955e1fa02e
1 file changed +125 -74
builtin/ls-tree.c
+125 -74
@@ -173,108 +173,157 @@ static int show_tree_fmt(const struct object_id *oid, struct strbuf *base,
173 return recurse;
174 }
175
176 -static int show_default(struct show_tree_data *data)
176 +static int show_tree_common(struct show_tree_data *data, int *recurse,
177 + const struct object_id *oid, struct strbuf *base,
178 + const char *pathname, unsigned mode)
179 {
178 - size_t baselen = data->base->len;
179 -
180 - if (cmdmode == MODE_LONG) {
181 - char size_text[24];
182 - if (data->type == OBJ_BLOB) {
183 - unsigned long size;
184 - if (oid_object_info(the_repository, data->oid, &size) == OBJ_BAD)
185 - xsnprintf(size_text, sizeof(size_text), "BAD");
186 - else
187 - xsnprintf(size_text, sizeof(size_text),
188 - "%" PRIuMAX, (uintmax_t)size);
189 - } else {
190 - xsnprintf(size_text, sizeof(size_text), "-");
191 - }
192 - printf("%06o %s %s %7s\t", data->mode, type_name(data->type),
193 - find_unique_abbrev(data->oid, abbrev), size_text);
194 - } else {
195 - printf("%06o %s %s\t", data->mode, type_name(data->type),
196 - find_unique_abbrev(data->oid, abbrev));
197 - }
198 - baselen = data->base->len;
199 - strbuf_addstr(data->base, data->pathname);
200 - write_name_quoted_relative(data->base->buf,
201 - chomp_prefix ? ls_tree_prefix : NULL, stdout,
202 - line_termination);
203 - strbuf_setlen(data->base, baselen);
204 - return 1;
205 -}
206 -
207 -static int show_tree(const struct object_id *oid, struct strbuf *base,
208 - const char *pathname, unsigned mode, void *context)
209 -{
210 - int recurse = 0;
211 - size_t baselen;
180 enum object_type type = object_type(mode);
213 - struct show_tree_data data = {
214 - .mode = mode,
215 - .type = type,
216 - .oid = oid,
217 - .pathname = pathname,
218 - .base = base,
219 - };
181 + int ret = -1;
182 +
183 + *recurse = 0;
184 + data->mode = mode;
185 + data->type = type;
186 + data->oid = oid;
187 + data->pathname = pathname;
188 + data->base = base;
189
190 if (type == OBJ_BLOB) {
191 if (ls_options & LS_TREE_ONLY)
223 - return 0;
192 + ret = 0;
193 } else if (type == OBJ_TREE &&
194 show_recursive(base->buf, base->len, pathname)) {
226 - recurse = READ_TREE_RECURSIVE;
195 + *recurse = READ_TREE_RECURSIVE;
196 if (!(ls_options & LS_SHOW_TREES))
228 - return recurse;
197 + ret = *recurse;
198 }
199
231 - if (cmdmode == MODE_OBJECT_ONLY) {
232 - printf("%s%c", find_unique_abbrev(oid, abbrev), line_termination);
233 - return recurse;
234 - }
200 + return ret;
201 +}
202
236 - if (cmdmode == MODE_NAME_ONLY) {
237 - baselen = base->len;
238 - strbuf_addstr(base, pathname);
239 - write_name_quoted_relative(base->buf,
240 - chomp_prefix ? ls_tree_prefix : NULL,
241 - stdout, line_termination);
242 - strbuf_setlen(base, baselen);
243 - return recurse;
203 +static void show_tree_common_default_long(struct strbuf *base,
204 + const char *pathname,
205 + const size_t baselen)
206 +{
207 + strbuf_addstr(base, pathname);
208 + write_name_quoted_relative(base->buf,
209 + chomp_prefix ? ls_tree_prefix : NULL, stdout,
210 + line_termination);
211 + strbuf_setlen(base, baselen);
212 +}
213 +
214 +static int show_tree_default(const struct object_id *oid, struct strbuf *base,
215 + const char *pathname, unsigned mode,
216 + void *context)
217 +{
218 + int early;
219 + int recurse;
220 + struct show_tree_data data = { 0 };
221 +
222 + early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
223 + if (early >= 0)
224 + return early;
225 +
226 + printf("%06o %s %s\t", data.mode, type_name(data.type),
227 + find_unique_abbrev(data.oid, abbrev));
228 + show_tree_common_default_long(base, pathname, data.base->len);
229 + return recurse;
230 +}
231 +
232 +static int show_tree_long(const struct object_id *oid, struct strbuf *base,
233 + const char *pathname, unsigned mode, void *context)
234 +{
235 + int early;
236 + int recurse;
237 + struct show_tree_data data = { 0 };
238 + char size_text[24];
239 +
240 + early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
241 + if (early >= 0)
242 + return early;
243 +
244 + if (data.type == OBJ_BLOB) {
245 + unsigned long size;
246 + if (oid_object_info(the_repository, data.oid, &size) == OBJ_BAD)
247 + xsnprintf(size_text, sizeof(size_text), "BAD");
248 + else
249 + xsnprintf(size_text, sizeof(size_text),
250 + "%" PRIuMAX, (uintmax_t)size);
251 + } else {
252 + xsnprintf(size_text, sizeof(size_text), "-");
253 }
254
246 - if (cmdmode == MODE_LONG ||
247 - (!ls_options || (ls_options & LS_RECURSIVE)
248 - || (ls_options & LS_SHOW_TREES)
249 - || (ls_options & LS_TREE_ONLY)))
250 - show_default(&data);
255 + printf("%06o %s %s %7s\t", data.mode, type_name(data.type),
256 + find_unique_abbrev(data.oid, abbrev), size_text);
257 + show_tree_common_default_long(base, pathname, data.base->len);
258 + return 1;
259 +}
260
261 +static int show_tree_name_only(const struct object_id *oid, struct strbuf *base,
262 + const char *pathname, unsigned mode, void *context)
263 +{
264 + int early;
265 + int recurse;
266 + const size_t baselen = base->len;
267 + struct show_tree_data data = { 0 };
268 +
269 + early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
270 + if (early >= 0)
271 + return early;
272 +
273 + strbuf_addstr(base, pathname);
274 + write_name_quoted_relative(base->buf,
275 + chomp_prefix ? ls_tree_prefix : NULL,
276 + stdout, line_termination);
277 + strbuf_setlen(base, baselen);
278 + return recurse;
279 +}
280 +
281 +static int show_tree_object(const struct object_id *oid, struct strbuf *base,
282 + const char *pathname, unsigned mode, void *context)
283 +{
284 + int early;
285 + int recurse;
286 + struct show_tree_data data = { 0 };
287 +
288 + early = show_tree_common(&data, &recurse, oid, base, pathname, mode);
289 + if (early >= 0)
290 + return early;
291 +
292 + printf("%s%c", find_unique_abbrev(oid, abbrev), line_termination);
293 return recurse;
294 }
295
296 struct ls_tree_cmdmode_to_fmt {
297 enum ls_tree_cmdmode mode;
298 const char *const fmt;
299 + read_tree_fn_t fn;
300 };
301
302 static struct ls_tree_cmdmode_to_fmt ls_tree_cmdmode_format[] = {
303 {
304 .mode = MODE_DEFAULT,
305 .fmt = "%(objectmode) %(objecttype) %(objectname)%x09%(path)",
306 + .fn = show_tree_default,
307 },
308 {
309 .mode = MODE_LONG,
310 .fmt = "%(objectmode) %(objecttype) %(objectname) %(objectsize:padded)%x09%(path)",
311 + .fn = show_tree_long,
312 },
313 {
314 .mode = MODE_NAME_ONLY, /* And MODE_NAME_STATUS */
315 .fmt = "%(path)",
316 + .fn = show_tree_name_only,
317 },
318 {
319 .mode = MODE_OBJECT_ONLY,
320 .fmt = "%(objectname)",
321 + .fn = show_tree_object
322 + },
323 + {
324 + /* fallback */
325 + .fn = show_tree_default,
326 },
277 - { 0 },
327 };
328
329 int cmd_ls_tree(int argc, const char **argv, const char *prefix)
@@ -282,7 +331,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
331 struct object_id oid;
332 struct tree *tree;
333 int i, full_tree = 0;
285 - read_tree_fn_t fn = show_tree;
334 + read_tree_fn_t fn = NULL;
335 const struct option ls_tree_options[] = {
336 OPT_BIT('d', NULL, &ls_options, N_("only show trees"),
337 LS_TREE_ONLY),
@@ -311,6 +360,7 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
360 OPT__ABBREV(&abbrev),
361 OPT_END()
362 };
363 + struct ls_tree_cmdmode_to_fmt *m2f = ls_tree_cmdmode_format;
364
365 git_config(git_default_config, NULL);
366 ls_tree_prefix = prefix;
@@ -365,18 +415,19 @@ int cmd_ls_tree(int argc, const char **argv, const char *prefix)
415 * The generic show_tree_fmt() is slower than show_tree(), so
416 * take the fast path if possible.
417 */
368 - if (format) {
369 - struct ls_tree_cmdmode_to_fmt *m2f;
370 -
371 - fn = show_tree_fmt;
372 - for (m2f = ls_tree_cmdmode_format; m2f->fmt; m2f++) {
373 - if (strcmp(format, m2f->fmt))
374 - continue;
375 -
418 + while (m2f) {
419 + if (!m2f->fmt) {
420 + fn = format ? show_tree_fmt : show_tree_default;
421 + } else if (format && !strcmp(format, m2f->fmt)) {
422 cmdmode = m2f->mode;
377 - fn = show_tree;
378 - break;
423 + fn = m2f->fn;
424 + } else if (!format && cmdmode == m2f->mode) {
425 + fn = m2f->fn;
426 + } else {
427 + m2f++;
428 + continue;
429 }
430 + break;
431 }
432
433 return !!read_tree(the_repository, tree, &pathspec, fn, NULL);