All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Mark C. Chu-Carroll" <markchucarroll@fastmail.com>
To: git@vger.kernel.org
Cc: jltobler@gmail.com, ps@pks.im,
	"Mark C. Chu-Carroll" <markchucarroll@fastmail.com>
Subject: [PATCH v2 1/1] repo: add filtering options to "repo structure"
Date: Mon,  5 Oct 2026 13:40:44 -0400	[thread overview]
Message-ID: <20261005174045.1900391-2-markchucarroll@fastmail.com> (raw)
In-Reply-To: <20261005174045.1900391-1-markchucarroll@fastmail.com>

Implement filtering for repo structure, imitating the mechanism
used in "git log".

Signed-off-by: Mark C. Chu-Carroll <markchucarroll@fastmail.com>
---
 Documentation/git-repo.adoc | 41 ++++++++++++++++--
 builtin/repo.c              | 16 +++++--
 t/t1901-repo-structure.sh   | 84 +++++++++++++++++++++++++++++++++++++
 3 files changed, 133 insertions(+), 8 deletions(-)

diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..5cbdf8e727 100644
--- a/Documentation/git-repo.adoc
+++ b/Documentation/git-repo.adoc
@@ -10,7 +10,7 @@ SYNOPSIS
 [synopsis]
 git repo info [--format=(lines|nul) | -z] [--all | <key>...]
 git repo info --keys [--format=(lines|nul) | -z]
-git repo structure [--format=(table|lines|nul) | -z]
+git repo structure [--format=(table|lines|nul) | -z] [<include|^exclude>...]
 
 DESCRIPTION
 -----------
@@ -56,9 +56,10 @@ supported:
 `nul`:::
 	Similar to `lines`, but using a _NUL_ character after each value.
 
-`structure [--format=(table|lines|nul) | -z]`::
-	Retrieve statistics about the current repository structure. The
-	following kinds of information are reported:
+`structure [--format=(table|lines|nul) | -z] [<include|^exclude>...]::
++
+Retrieve statistics about the current repository structure. The
+following kinds of information are reported:
 +
 * Reference counts categorized by type
 * Reachable object counts categorized by type
@@ -66,6 +67,16 @@ supported:
 * Total disk size of reachable objects by type
 * Largest reachable objects in the repository by type
 +
+The set of objects counted can be filtered by specifying a
+collection of query clauses to select which objects will be
+counted. These parameters follow the same syntax as the parameters
+to similar commands like `git log`. Semantically, these parameters
+are treated as a collection of include and exclude specifiers. Th
+set of objects counted will consist of all objects reachable from
+an object included by one of the include specifiers via a path that
+does not include an object in an exclude clause. If no includes
+are specified, then the include set is all reachable objects. 
++
 The output format can be chosen through the flag `--format`. Three formats are
 supported:
 +
@@ -141,6 +152,28 @@ using the `nul` format:
 git repo info --format=nul layout.bare layout.shallow
 ------------
 
+* Generates information about storage usage in the repository:
++
+------------
+git repo structure
+------------
++
+
+* Generates information about storage usage in the repository omitting
+the branch "foo":
++
+------------
+git repo structure ^foo 
+------------
++
+* Generates information about repository objects reachable from
+the references "x" and "y", but omitting anything that can
+only be reached on a path including "xchild":
++
+------------
+git repo structure x y ^xchild
+------------
++
 SEE ALSO
 --------
 linkgit:git-rev-parse[1]
diff --git a/builtin/repo.c b/builtin/repo.c
index 84e012f83f..b3aca71298 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -27,7 +27,7 @@
 	"git repo info --keys [--format=(lines|nul) | -z]"
 
 #define REPO_STRUCTURE_USAGE \
-	"git repo structure [--format=(table|lines|nul) | -z]"
+	"git repo structure [--format=(table|lines|nul) | -z] [<include|^exclude>...]"
 
 static const char *const repo_usage[] = {
 	REPO_INFO_USAGE,
@@ -946,12 +946,20 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
 		OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
 		OPT_END()
 	};
+	struct setup_revision_opt s_r_opt;
+	memset(&s_r_opt, 0, sizeof(s_r_opt));
+	s_r_opt.def = "HEAD";
+	s_r_opt.revarg_opt = REVARG_COMMITTISH;
 
-	argc = parse_options(argc, argv, prefix, options, repo_structure_usage, 0);
-	if (argc)
-		usage(_("too many arguments"));
+	argc = parse_options(argc, argv, prefix, options, repo_structure_usage,
+			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN_OPT);
 
 	repo_init_revisions(repo, &revs, prefix);
+	if (argc > 1) {
+		argc = setup_revisions(argc, argv, &revs, &s_r_opt);
+		if (argc > 1)
+			usage(_("too many arguments"));
+	}
 
 	if (show_progress < 0)
 		show_progress = isatty(2);
diff --git a/t/t1901-repo-structure.sh b/t/t1901-repo-structure.sh
index 02cc2b594a..eb2c595955 100755
--- a/t/t1901-repo-structure.sh
+++ b/t/t1901-repo-structure.sh
@@ -144,6 +144,90 @@ test_expect_success SHA1 'repository with references and objects' '
 	)
 '
 
+test_expect_success SHA1 'repository with references and objects, filtered' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit_bulk 1005 &&
+		git tag -a foo -m bar &&
+
+		oid="$(git rev-parse HEAD)" &&
+		git update-ref refs/remotes/origin/foo "$oid" &&
+		git checkout -b grobble &&
+		test_commit_bulk --ref=refs/heads/grobble 20 &&
+		git checkout master &&
+ 		test_commit_bulk 20 &&
+		# Also creates a commit, tree, and blob.
+		git notes add -m foo &&
+
+		# 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      |
+		| ------------------------- | ---------- |
+		| * References              |            |
+		|   * Count                 |      5     |
+		|     * Branches            |      2     |
+		|     * Tags                |      1     |
+		|     * Remotes             |      1     |
+		|     * Others              |      1     |
+		|                           |            |
+		| * Reachable objects       |            |
+		|   * Count                 |   3.06 k   |
+		|     * Commits             |   1.05 k   |
+		|     * Trees               |   1.01 k   |
+		|     * Blobs               |   1.01 k   |
+		|     * Tags                |      1     |
+		|   * Inflated size         |  16.04 MiB |
+		|     * Commits             | 226.54 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] df6400c01440c329f1011669c4c26cc0c7852887
+		[3] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
+		[4] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
+		[5] 97d808e45116bf02103490294d3d46dad7a2ac62
+		[6] 4dae4f5954f5e6feb3577cfb1b181daa3fd3afd2
+		EOF
+
+		git repo structure  >actual 2>actual-err &&
+		cp actual /tmp/actual &&
+		cp expect /tmp/expect &&
+		test_cmp expect actual &&
+		test_line_count = 0 actual-err &&
+
+		git repo structure grobble ^master >actual 2>actual-err &&
+		cp actual /tmp &&
+		cp actual-err /tmp &&
+		test_grep "|     \* Commits             |    21     |" actual &&
+		test_grep "|     \* Trees               |     2     |" actual &&
+		test_grep "|     \* Commits             |  4.50 KiB |" actual &&
+		test_grep "|     \* Trees               | 32.35 KiB |" actual &&
+		test_grep "|     \* Blobs               | 11.68 KiB |" actual &&
+		test_line_count = 0 actual-err
+	)
+'
+
 test_expect_success SHA1 'lines and nul format' '
 	test_when_finished "rm -rf repo" &&
 	git init repo &&
-- 
2.53.0


  reply	other threads:[~2026-10-05 17:40 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-24 16:45 [PATCH 0/1] repo: add filtering options to "repo structure" Mark C. Chu-Carroll
2026-09-24 16:45 ` [PATCH 1/1] " Mark C. Chu-Carroll
2026-09-30 16:28   ` Patrick Steinhardt
2026-10-05 18:52     ` Mark C. Chu-Carroll
2026-10-05 17:40   ` [PATCH v2 0/1] " Mark C. Chu-Carroll
2026-10-05 17:40     ` Mark C. Chu-Carroll [this message]
2026-10-06  5:51       ` [PATCH v2 1/1] " Patrick Steinhardt
2026-10-08 15:46         ` Kaartic Sivaraam
2026-10-09 15:49           ` Mark C. Chu-Carroll
2026-10-09 18:09   ` [PATCH v3 0/1] repo: add revision " Mark C. Chu-Carroll
2026-10-09 18:09     ` [PATCH v3 1/1] repo: add " Mark C. Chu-Carroll
2026-10-09 21:24       ` Junio C Hamano
2026-10-10 14:31         ` Mark C. Chu-Carroll
2026-10-10 15:05   ` [PATCH v4 0/1] repo: add revision " Mark C. Chu-Carroll
2026-10-10 15:05     ` [PATCH v4 1/1] repo: add " Mark C. Chu-Carroll
2026-10-13 11:50       ` Patrick Steinhardt
2026-10-13 13:56         ` Mark C. Chu-Carroll
2026-10-13 14:05           ` Patrick Steinhardt
2026-10-13 17:28     ` [PATCH v5 0/1] repo: add revision " Mark C. Chu-Carroll
2026-10-13 17:28       ` [PATCH v5 1/1] repo: add " Mark C. Chu-Carroll

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261005174045.1900391-2-markchucarroll@fastmail.com \
    --to=markchucarroll@fastmail.com \
    --cc=git@vger.kernel.org \
    --cc=jltobler@gmail.com \
    --cc=ps@pks.im \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.