From 6d9e5622477e271eb4d4629fd1e5772eb56ca2b9 Mon Sep 17 00:00:00 2001 From: Jeff Hostetler Date: Wed, 19 Jun 2024 16:10:34 -0400 Subject: [PATCH] virtualization: add new builtin command to print hydration level GVFS users can easily (and accidentally) over-hydrate their enlistments. This causes some commands to be very slow. Create a command to print the current hydration level. This should help our support team investigate the state of their enlistment. Signed-off-by: Jeff Hostetler --- .gitignore | 1 + Documentation/git-virtualization.txt | 24 +++++++ Makefile | 1 + builtin.h | 1 + builtin/virtualization.c | 102 +++++++++++++++++++++++++++ command-list.txt | 1 + git.c | 1 + t/t1093-virtualfilesystem.sh | 11 +++ 8 files changed, 142 insertions(+) create mode 100644 Documentation/git-virtualization.txt create mode 100644 builtin/virtualization.c diff --git a/.gitignore b/.gitignore index 5a923058bbd593..8b9b3c2b2aedb6 100644 --- a/.gitignore +++ b/.gitignore @@ -182,6 +182,7 @@ /git-verify-pack /git-verify-tag /git-version +/git-virtualization /git-web--browse /git-whatchanged /git-worktree diff --git a/Documentation/git-virtualization.txt b/Documentation/git-virtualization.txt new file mode 100644 index 00000000000000..f628df6c96b5c0 --- /dev/null +++ b/Documentation/git-virtualization.txt @@ -0,0 +1,24 @@ +git-virtualization(1) +===================== + +NAME +---- + +git-virtualization - EXPERIMENTAL: Measure virtualization level of worktree + + +SYNOPSIS +-------- +[verse] +(EXPERIMENTAL!) `git virtualization` + + +DESCRIPTION +----------- + +Measure the virtualization level of the worktree. + + +GIT +--- +Part of the linkgit:git[1] suite diff --git a/Makefile b/Makefile index 3f77192081c8ca..3f66968796933d 100644 --- a/Makefile +++ b/Makefile @@ -1346,6 +1346,7 @@ BUILTIN_OBJS += builtin/var.o BUILTIN_OBJS += builtin/verify-commit.o BUILTIN_OBJS += builtin/verify-pack.o BUILTIN_OBJS += builtin/verify-tag.o +BUILTIN_OBJS += builtin/virtualization.o BUILTIN_OBJS += builtin/worktree.o BUILTIN_OBJS += builtin/write-tree.o diff --git a/builtin.h b/builtin.h index 78722b676d4b88..c933909c06edaa 100644 --- a/builtin.h +++ b/builtin.h @@ -245,6 +245,7 @@ int cmd_var(int argc, const char **argv, const char *prefix); int cmd_verify_commit(int argc, const char **argv, const char *prefix); int cmd_verify_tag(int argc, const char **argv, const char *prefix); int cmd_version(int argc, const char **argv, const char *prefix); +int cmd_virtualization(int argc, const char **argv, const char *prefix); int cmd_whatchanged(int argc, const char **argv, const char *prefix); int cmd_worktree(int argc, const char **argv, const char *prefix); int cmd_write_tree(int argc, const char **argv, const char *prefix); diff --git a/builtin/virtualization.c b/builtin/virtualization.c new file mode 100644 index 00000000000000..7bf4d158b4b2f5 --- /dev/null +++ b/builtin/virtualization.c @@ -0,0 +1,102 @@ +#include "builtin.h" +#include "config.h" +#include "json-writer.h" +#include "parse-options.h" +#include "read-cache-ll.h" +#include "repository.h" +#include "trace2.h" + +static const char * const virt_usage[] = { + N_("(EXPERIMENTAL!) git virtualization"), + NULL, +}; + +static struct option virt_options[] = { + OPT_END(), +}; + +static int virt_load_config_cb(const char *var, + const char *value, + const struct config_context *ctx, + void *pvoid) +{ + return git_default_config(var, value, ctx, pvoid); +} + +static void virt_load_config(void) +{ + git_config(virt_load_config_cb, NULL); +} + +static uint64_t count_skipped(struct repository *repo) +{ + uint64_t k; + uint64_t count = 0; + + for (k = 0; k < repo->index->cache_nr; k++) { + const struct cache_entry *ce_k = repo->index->cache[k]; + + if (ce_skip_worktree(ce_k)) + count++; + } + + return count; +} + +static void print_hydration(struct repository *repo) +{ + uint64_t c_skipped; + uint64_t c_total; + uint64_t c_hydrated; + double hydration; + + c_skipped = count_skipped(the_repository); + c_total = (uint64_t)the_repository->index->cache_nr; + c_hydrated = c_total - c_skipped; + + if (c_total > 0) + hydration = (double)(c_hydrated * 100) / (double)c_total; + else + hydration = 0.0; + + printf("Skipped: %" PRIu64 "\n", c_skipped); + printf("Hydrated: %" PRIu64 "\n", c_hydrated); + printf("Total: %" PRIu64 "\n", c_total); + + printf("Hydration: %.2f%%\n", hydration); + + if (trace2_is_enabled()) { + struct json_writer jw = JSON_WRITER_INIT; + + jw_object_begin(&jw, 0); + { + jw_object_intmax(&jw, "skipped", c_skipped); + jw_object_intmax(&jw, "hydrated", c_hydrated); + jw_object_intmax(&jw, "total", c_total); + + jw_object_double(&jw, "hydration", 2, hydration); + } + jw_end(&jw); + + trace2_data_json("virt", repo, "stats", &jw); + + jw_release(&jw); + } +} + +int cmd_virtualization(int argc, const char **argv, const char *prefix) +{ + prepare_repo_settings(the_repository); + the_repository->settings.command_requires_full_index = 1; + + virt_load_config(); + + argc = parse_options(argc, argv, prefix, virt_options, virt_usage, 0); + + if (repo_read_index(the_repository) < 0) + die("index file corrupt"); + + print_hydration(the_repository); + + return 0; +} diff --git a/command-list.txt b/command-list.txt index c4cd0f352b8833..6c4aa9159e15cf 100644 --- a/command-list.txt +++ b/command-list.txt @@ -201,6 +201,7 @@ git-verify-commit ancillaryinterrogators git-verify-pack plumbinginterrogators git-verify-tag ancillaryinterrogators git-version ancillaryinterrogators +git-virtualization mainporcelain git-whatchanged ancillaryinterrogators complete git-worktree mainporcelain git-write-tree plumbingmanipulators diff --git a/git.c b/git.c index af85e84c10b45e..a00c1ddeb7e84e 100644 --- a/git.c +++ b/git.c @@ -705,6 +705,7 @@ static struct cmd_struct commands[] = { { "verify-pack", cmd_verify_pack }, { "verify-tag", cmd_verify_tag, RUN_SETUP }, { "version", cmd_version }, + { "virtualization", cmd_virtualization, RUN_SETUP | NEED_WORK_TREE }, { "whatchanged", cmd_whatchanged, RUN_SETUP }, { "worktree", cmd_worktree, RUN_SETUP }, { "write-tree", cmd_write_tree, RUN_SETUP }, diff --git a/t/t1093-virtualfilesystem.sh b/t/t1093-virtualfilesystem.sh index cad13d680cb199..21fd59efea3a16 100755 --- a/t/t1093-virtualfilesystem.sh +++ b/t/t1093-virtualfilesystem.sh @@ -89,6 +89,17 @@ test_expect_success 'verify skip-worktree bit is set for absolute path' ' test_cmp expected actual ' +test_expect_success 'verify hydration percentage' ' + git virtualization >actual && + cat >expected <<-\EOF && + Skipped: 3 + Hydrated: 1 + Total: 4 + Hydration: 25.00% + EOF + test_cmp expected actual +' + test_expect_success 'verify skip-worktree bit is cleared for absolute path' ' clean_repo && write_script .git/hooks/virtualfilesystem <<-\EOF &&