[PATCH v4 2/2] repo: make concern thresholds configurable
flat view
WARM2d
From: Mark C. Chu-Carroll <hidden>
Date: 2026-10-29 17:52:35
Subsystem:
documentation, the rest · Maintainers:
Jonathan Corbet, Linus Torvalds
Revision v4 (4 revisions archived).
Revisions (4)
The concern reporting mechanism so far provides a
measure of concern based on heuristic values estimated
by analyzing a collection of (hopefully) representative
repositories. But for different projects/usecases, the
thresholds at which a value becomes concerning may vary.
Provide a mechanism using git config to allow users to
configure per-repo concern levels for "git repo structure"
concern reporting.
Signed-off-by: Mark C. Chu-Carroll <redacted>
---
Documentation/config/repo.adoc | 59 ++++++++++++++++++
Documentation/git-repo.adoc | 11 ++++
builtin/repo.c | 38 +++++++++++-
t/t1901-repo-structure.sh | 138 ++++++++++++++++++++++++++++++++++++++++-
4 files changed, 244 insertions(+), 2 deletions(-)
diff --git a/Documentation/config/repo.adoc b/Documentation/config/repo.adoc
new file mode 100644
index 0000000000..811b099d72
--- /dev/null
+++ b/Documentation/config/repo.adoc@@ -0,0 +1,59 @@ +`repo.concern.commit-count`:: + Sets the value of the concern threshold for commit count. + +`repo.concern.tree-count`:: + Sets the value of the concern threshold for tree count. + +`repo.concern.blob-count`:: + Sets the value of the concern threshold for blob count. + +`repo.concern.tag-count`:: + Sets the value of the concern threshold for tag count. + +`repo.concern.commit-size`:: + Sets the value of the concern threshold for total commit size. + +`repo.concern.tree-size`:: + Sets the value of the concern threshold for total tree size. + +`repo.concern.blob-size`:: + Sets the value of the concern threshold for total blob size. + +`repo.concern.tag-size`:: + Sets the value of the concern threshold for total tag size. + +`repo.concern.commit-inflated-size`:: + Sets the value of the concern threshold for total size + of all inflated commits. + +`repo.concern.tree-inflated-size`:: + Sets the value of the concern threshold for total size of + all inflated trees. + +`repo.concern.blob-inflated-size`:: + Sets the value of the concern threshold for total size of + all inflated blobs. + +`repo.concern.tag-inflated-size`:: + Sets the value of the concern threshold for the total size + of all inflated tags. + +`repo.concern.commit-largest`:: + Sets the value of the concern threshold the size of the largest + commit. + +`repo.concern.tree-largest`:: + Sets the value of the concern threshold for the size of the + largest tree. + +`repo.concern.blob-largest`:: + Sets the value of the concern threshold for the size of the + largest blob. + +`repo.concern.tag-largest`:: + Sets the value of the concern threshold for the size of the + largest tag. + +All of the concern thresholds are integer values for the +floor of the base-2 log of the threshold value. The default values +of each threshold are set to heuristically determined values.
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index f186b27d87..516403e17d 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc@@ -101,6 +101,8 @@ statistic value. The value is considered concerning if it exceeds a heuristicall chosen threshold value; the degree of concern is the difference between the log_2 of the value, and the log_2 of the corresponding threshold. +The threshold values are configurable; see the configuration section below. + INFO KEYS --------- In order to obtain a set of values from `git repo info`, you should provide
@@ -153,6 +155,15 @@ using the `nul` format: git repo info --format=nul layout.bare layout.shallow ------------ +CONFIGURATION +------------- + +include::includes/cmd-config-section-all.adoc[] + +:git-repo: 1 +include::config/repo.adoc[] + + SEE ALSO -------- linkgit:git-rev-parse[1]
diff --git a/builtin/repo.c b/builtin/repo.c
index bd1866c5fa..4880c8b8f7 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c@@ -2,6 +2,7 @@ #include "builtin.h" #include "commit.h" +#include "config.h" #include "environment.h" #include "hash.h" #include "hex.h"
@@ -30,6 +31,8 @@ #define REPO_STRUCTURE_USAGE \ "git repo structure [--format=(table|lines|nul) | -z] [--[no-]concern]" +#define REPO_STRUCTURE_CONFIG_PREFIX "repo.concern." + static const char *const repo_usage[] = { REPO_INFO_USAGE, REPO_STRUCTURE_USAGE,
@@ -430,6 +433,35 @@ static size_t repo_structure_concern_level(const char* concern_name, return 0; } +/* + * Concern thresholds aren't universal. We try to set reasonable default + * values, but projects may want to set these thresholds differently. To + * support that, they can set the thresholds for their project in the + * project's git config, in the section "repo.structure.concern". + */ +static int config_concern_thresholds(const char *prefixed_var, + const char *str_val, + const struct config_context *ctx, + void *cb) +{ + struct concern_stat_threshold *thresholds = cb; + if (starts_with(prefixed_var, REPO_STRUCTURE_CONFIG_PREFIX)) { + const char *concern_name = &prefixed_var[strlen(REPO_STRUCTURE_CONFIG_PREFIX)]; + for (int i = 0; thresholds[i].name; i++) { + if (!strcmp(thresholds[i].name, concern_name)) { + int value = git_config_int(prefixed_var, str_val, ctx->kvi); + if (value < 0) + return -1; + thresholds[i].threshold = value; + return 0; + } + } + warning(_("Invalid concern threshold name: '%s'"), concern_name); + return 0; + } + return 0; +} + /* * Holds column data that gets stored for each row. */
@@ -835,6 +867,7 @@ static void stats_table_print_structure(const struct stats_table *table, strbuf_utf8_align(&buf, ALIGN_LEFT, concern_col_width, concern_str.buf); strbuf_addstr(&buf, " |"); } + strbuf_release(&concern_str); printf("%s\n", buf.buf); }
@@ -1041,7 +1074,6 @@ static void structure_keyvalue_print(struct repo_structure *stats, stats->objects.largest.tag_size.value, repo_structure_concern_thresholds), value_delim); - print_object_data("objects.commits.max_parents", key_delim, &stats->objects.largest.parent_count, value_delim); print_object_data("objects.trees.max_entries", key_delim,
@@ -1269,6 +1301,10 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix, usage(_("too many arguments")); repo_init_revisions(repo, &revs, prefix); + if (show_concern) + repo_config(repo, &config_concern_thresholds, &repo_structure_concern_thresholds); + + if (show_progress < 0) show_progress = isatty(2);
diff --git a/t/t1901-repo-structure.sh b/t/t1901-repo-structure.sh
index f92168025b..1db2cc5293 100755
--- a/t/t1901-repo-structure.sh
+++ b/t/t1901-repo-structure.sh@@ -67,7 +67,6 @@ test_expect_success 'empty repository' ' EOF git repo structure >out 2>err && - cp out /tmp/test1-out && test_cmp expect out && test_line_count = 0 err
@@ -145,6 +144,89 @@ test_expect_success SHA1 'repository with references and objects' ' ) ' +test_expect_success SHA1 'concern flagging' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + # differences between zlib and zlib-ng can cause this + # test to fail; so we just turn it off. + git config core.compression 0 && + # configure thresholds to get concern indications + git config repo.concern.commit-count 7 && + git config repo.concern.commit-size 14 && + git config repo.concern.tree-size 10 && + git config repo.concern.blob-size 8 && + git config repo.concern.blob-inflated-size 10 && + git config repo.concern.tag-size 2 && + git config repo.concern.commit-largest 4 && + git config repo.concern.blob-largest 2 && + test_commit_bulk 1005 && + git tag -a foo -m bar && + oid="$(git rev-parse HEAD)" && + git update-ref refs/remotes/origin/foo "$oid" && + + # Also creates a commit, tree, and blob. + git notes add -m foo && + + + # The tags disk size is handled specially due to the + # git-rev-list(1) --disk-usage=human option printing the full + # "byte/bytes" unit string instead of just "B". + cat >expect <<-EOF && + | Repository structure | Value | Concern | + | ------------------------- | ---------- | -------- | + | * References | | | + | * Count | 4 | | + | * Branches | 1 | | + | * Tags | 1 | | + | * Remotes | 1 | | + | * Others | 1 | | + | | | | + | * Reachable objects | | | + | * Count | 3.02 k | | + | * Commits | 1.01 k | ** | + | * Trees | 1.01 k | | + | * Blobs | 1.01 k | | + | * Tags | 1 | | + | * Inflated size | 16.03 MiB | | + | * Commits | 217.92 KiB | | + | * Trees | 15.81 MiB | | + | * Blobs | 11.68 KiB | *** | + | * Tags | 132 B | | + | * Disk size | $(object_type_disk_usage all true) | | + | * Commits | $(object_type_disk_usage commit true) | *** | + | * Trees | $(object_type_disk_usage tree true) | ******** | + | * Blobs | $(object_type_disk_usage blob true) | ****** | + | * Tags | $(object_type_disk_usage tag) B | ***** | + | | | | + | * Largest objects | | | + | * Commits | | | + | * Maximum size [1] | 223 B | *** | + | * Maximum parents [2] | 1 | | + | * Trees | | | + | * Maximum size [3] | 32.29 KiB | | + | * Maximum entries [4] | 1.01 k | | + | * Blobs | | | + | * Maximum size [5] | 13 B | * | + | * Tags | | | + | * Maximum size [6] | 132 B | | + + [1] 0dc91eb18580102a3a216c8bfecedeba2b9f9b9a + [2] 0dc91eb18580102a3a216c8bfecedeba2b9f9b9a + [3] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c + [4] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c + [5] 97d808e45116bf02103490294d3d46dad7a2ac62 + [6] 4dae4f5954f5e6feb3577cfb1b181daa3fd3afd2 + EOF + + git repo structure --concern >actual 2>err && + + test_cmp expect actual && + test_line_count = 0 err + ) +' + test_expect_success SHA1 'lines and nul format' ' test_when_finished "rm -rf repo" && git init repo &&
@@ -205,6 +287,60 @@ test_expect_success SHA1 'lines and nul format' ' ) ' +test_expect_success SHA1 'lines format with concerns' ' + test_when_finished "rm -rf repo" && + git init repo && + ( + cd repo && + # configure thresholds to get concern indications + git config core.compression 0 && + git config repo.concern.commit-count 7 && + git config repo.concern.commit-size 14 && + git config repo.concern.tree-size 10 && + git config repo.concern.blob-size 8 && + git config repo.concern.blob-inflated-size 10 && + git config repo.concern.tag-size 2 && + git config repo.concern.commit-largest 4 && + git config repo.concern.blob-largest 2 && + touch configured && + test_commit_bulk 1005 && + git tag -a foo -m bar && + oid="$(git rev-parse HEAD)" && + git update-ref refs/remotes/origin/foo "$oid" && + + # Also creates a commit, tree, and blob. + git notes add -m foo && + + + # The tags disk size is handled specially due to the + # git-rev-list(1) --disk-usage=human option printing the full + # "byte/bytes" unit string instead of just "B". + cat >expect <<-EOF && + objects.commits.count.concern_level=2 + objects.trees.count.concern_level=0 + objects.blobs.count.concern_level=0 + objects.tags.count.concern_level=0 + objects.commits.inflated_size.concern_level=0 + objects.trees.inflated_size.concern_level=0 + objects.blobs.inflated_size.concern_level=3 + objects.tags.inflated_size.concern_level=0 + objects.commits.disk_size.concern_level=3 + objects.trees.disk_size.concern_level=8 + objects.blobs.disk_size.concern_level=6 + objects.tags.disk_size.concern_level=5 + objects.commits.max_size.concern_level=3 + objects.trees.max_size.concern_level=0 + objects.blobs.max_size.concern_level=1 + objects.tags.max_size.concern_level=0 + EOF + + git repo structure --concern --format=lines >actual 2>err && + test_grep "concern_level" actual >actual-concerns && + test_cmp expect actual-concerns && + test_line_count = 0 err + ) +' + test_expect_success 'progress meter option' ' test_when_finished "rm -rf repo" && git init repo &&
--
2.53.0