From e9dcf5786240595fc410c6554ed9aa10fdf72ec6 Mon Sep 17 00:00:00 2001 From: Matthew John Cheetham Date: Wed, 29 Jan 2025 15:57:13 +0000 Subject: [PATCH] gc.c: extend vfs-cache-move to migrate loose objs Extend the `vfs-cache-move` maintenance task to also migrate any loose objects in the local ODB directory to the shared volume cache for VFS for Git/Scalar (if set). Signed-off-by: Matthew John Cheetham --- Documentation/git-maintenance.txt | 4 ++-- builtin/gc.c | 36 ++++++++++++++++++++++++++----- t/t7900-maintenance.sh | 16 ++++++++++---- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt index 2b4ca10713b62d..b899daa9634b41 100644 --- a/Documentation/git-maintenance.txt +++ b/Documentation/git-maintenance.txt @@ -163,8 +163,8 @@ vfs-cache-move:: The `vfs-cache-move` task only operates on Scalar or VFS for Git repositories (cloned with either `scalar clone` or `gvfs clone`) that have the `gvfs.sharedCache` configuration setting present. This task - migrates pack files from the repository's object directory in to the - shared volume cache. + migrates pack files and loose objects from the repository's object + directory in to the shared volume cache. OPTIONS ------- diff --git a/builtin/gc.c b/builtin/gc.c index cdbf1ec4ddd68a..01ee207a077155 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -1475,16 +1475,34 @@ static void move_pack_to_vfs_cache(const char *full_path, size_t full_path_len, srcdir = xstrndup(full_path, full_path_len - strlen(file_name) - 1); - /* Same source + destination means there's no work to do. */ - if (!fspathcmp(srcdir, vfs_object_dir)) - goto cleanup; - migrate_pack(srcdir, dstdir, file_name); -cleanup: free(srcdir); } +static int move_loose_object_to_vfs_cache(const struct object_id *oid, + const char *path, + UNUSED void *data) +{ + struct stat st; + struct strbuf dst = STRBUF_INIT; + char *hex = oid_to_hex(oid); + + strbuf_addf(&dst, "%s/%.2s/", vfs_object_dir, hex); + + if (stat(dst.buf, &st)) { + if (mkdir(dst.buf, 0777)) + die_errno(_("failed to create directory '%s'"), dst.buf); + } else if (!S_ISDIR(st.st_mode)) + die(_("expected '%s' to be a directory"), dst.buf); + + strbuf_addstr(&dst, hex+2); + rename_or_copy_or_die(path, dst.buf); + + strbuf_release(&dst); + return 0; +} + static int maintenance_task_vfs_cache_move(UNUSED struct maintenance_run_opts *opts, UNUSED struct gc_config *cfg) { @@ -1495,11 +1513,19 @@ static int maintenance_task_vfs_cache_move(UNUSED struct maintenance_run_opts *o if (!vfs_object_dir) return 0; + /* If the dest is the same as the local odb path then we do nothing. */ + if (!fspathcmp(r->objects->odb->path, vfs_object_dir)) + goto cleanup; + strbuf_addf(&dstdir, "%s/pack", vfs_object_dir); for_each_file_in_pack_dir(r->objects->odb->path, move_pack_to_vfs_cache, dstdir.buf); + for_each_loose_object(move_loose_object_to_vfs_cache, NULL, + FOR_EACH_OBJECT_LOCAL_ONLY); + +cleanup: strbuf_release(&dstdir); return 0; } diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh index a118aee3e7fe2e..ec18ca7f44be46 100755 --- a/t/t7900-maintenance.sh +++ b/t/t7900-maintenance.sh @@ -47,6 +47,10 @@ test_get_packdir_files() { fi } +test_get_loose_object_files () { + find .git/objects -type f -path '.git/objects/??/*' +} + test_expect_success 'help text' ' test_expect_code 129 git maintenance -h >actual && test_grep "usage: git maintenance " actual && @@ -1041,6 +1045,7 @@ test_expect_success 'vfs-cache-move task with no shared cache no op' ' test_import_packfile && test_get_packdir_files "*.pack" "*.idx" "*.keep" "*.rev" \ >files.txt && + test_get_loose_object_files >>files.txt && git maintenance run && while IFS= read -r f; do @@ -1049,14 +1054,14 @@ test_expect_success 'vfs-cache-move task with no shared cache no op' ' ) ' -test_expect_success 'vfs-cache-move task cache path same as pack dir no op' ' +test_expect_success 'vfs-cache-move task cache path same as local odb no op' ' test_when_finished "rm -rf repo" && git init repo && ( cd repo && test_commit something && - git config set gvfs.sharedcache .git/objects/pack && + git config set gvfs.sharedcache .git/objects && git config set maintenance.gc.enabled false && git config set maintenance.vfs-cache-move.enabled true && git config set maintenance.vfs-cache-move.auto 1 && @@ -1064,6 +1069,7 @@ test_expect_success 'vfs-cache-move task cache path same as pack dir no op' ' test_import_packfile && test_get_packdir_files "*.pack" "*.idx" "*.keep" "*.rev" \ >files.txt && + test_get_loose_object_files >>files.txt && git maintenance run && while IFS= read -r f; do @@ -1087,10 +1093,11 @@ test_expect_success 'vfs-cache-move task no .rev or .keep' ' test_import_packfile && test_get_packdir_files "*.pack" "*.idx" >src.txt && + test_get_loose_object_files >>src.txt && rm -f .git/objects/pack/*.rev .git/objects/pack/*.keep && - sed "s/.*\\//..\\/cache\\/pack\\//" src.txt >dst.txt && + sed "s/.git\\/objects\\//..\\/cache\\//" src.txt >dst.txt && git maintenance run && while IFS= read -r f; do @@ -1119,8 +1126,9 @@ test_expect_success 'vfs-cache-move task success' ' test_import_packfile && test_get_packdir_files "*.pack" "*.idx" "*.keep" "*.rev" \ >src.txt && + test_get_loose_object_files >>src.txt && - sed "s/.*\\//..\\/cache\\/pack\\//" src.txt >dst.txt && + sed "s/.git\\/objects\\//..\\/cache\\//" src.txt >dst.txt && git maintenance run && while IFS= read -r f; do