sparse-index: use strbuf in path_found()

The path_found() method previously reused strings from the cache entries the calling methods were using. This prevents string manipulation in place and causes some odd reallocation before the final lstat() call in the method. Refactor the method to use strbufs and copy the path into the strbuf, but also only the parent directory and not the whole path. This looks like extra copying when assigning the path to the strbuf, but we save an allocation by dropping the 'tmp' string, and we are "reusing" the copy from 'tmp' to put the data in the strbuf. Signed-off-by: Derrick Stolee <stolee@gmail.com> Reviewed-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Derrick Stolee committed Jun 28, 2024 at 12:43 UTC 23dd6f8bcc11fc4a468f0863b64f3ebe27a173cd
1 file changed +9 -12
sparse-index.c
+9 -12
@@ -440,31 +440,30 @@ void ensure_correct_sparsity(struct index_state *istate)
440 }
441
442 struct path_found_data {
443 - const char *dirname;
444 - size_t dir_len;
443 + struct strbuf dir;
444 int dir_found;
445 };
446
447 #define PATH_FOUND_DATA_INIT { \
448 + .dir = STRBUF_INIT, \
449 .dir_found = 1 \
450 }
451
452 static void clear_path_found_data(struct path_found_data *data)
453 {
454 - return;
454 + strbuf_release(&data->dir);
455 }
456
457 static int path_found(const char *path, struct path_found_data *data)
458 {
459 struct stat st;
460 char *newdir;
461 - char *tmp;
461
462 /*
463 * If dirname corresponds to a directory that doesn't exist, and this
464 * path starts with dirname, then path can't exist.
465 */
467 - if (!data->dir_found && !memcmp(path, data->dirname, data->dir_len))
466 + if (!data->dir_found && !memcmp(path, data->dir.buf, data->dir.len))
467 return 0;
468
469 /*
@@ -486,17 +485,15 @@ static int path_found(const char *path, struct path_found_data *data)
485 * If path starts with directory (which we already lstat'ed and found),
486 * then no need to lstat parent directory again.
487 */
489 - if (data->dir_found && data->dirname &&
490 - memcmp(path, data->dirname, data->dir_len))
488 + if (data->dir_found && data->dir.buf &&
489 + memcmp(path, data->dir.buf, data->dir.len))
490 return 0;
491
492 /* Free previous dirname, and cache path's dirname */
494 - data->dirname = path;
495 - data->dir_len = newdir - path + 1;
493 + strbuf_reset(&data->dir);
494 + strbuf_add(&data->dir, path, newdir - path + 1);
495
497 - tmp = xstrndup(path, data->dir_len);
498 - data->dir_found = !lstat(tmp, &st);
499 - free(tmp);
496 + data->dir_found = !lstat(data->dir.buf, &st);
497
498 return 0;
499 }