Thread (2 messages) flat view 2 messages, 1 author, 17h ago
DORMANTno replies

[PATCH 1/1] repo: add filtering options to "repo structure"

From: Mark C. Chu-Carroll <hidden>
Date: 2026-09-24 16:45:17
Subsystem: documentation, the rest · Maintainers: Jonathan Corbet, Linus Torvalds

"git repo structure" provides a collection of useful information
about the information stored in a repo. In particular, it's
valuable for diagnosing performance issues caused by large objects
stored in a repo.

The current implementation of "git repo stucture" provides summary
information about everything in the repository - all of the
branches, remotes, tags, stashes, and notes. But sometimes
to properly diagnose a problem, it's useful to be able to exclude
refs that are known to not be relevant to the issue at hand.

Add a set of flags that allow a user to selective exclude
reference types from the report generated by "git repo structure".
When a ref type is excluded by the filter, it no longer appears
in the report (ie, if "--no-tags" is passed, the report line
for "Branches" will no longer appear under "* References").
Following the pattern of flags that are only used to
disable functionality (eg, "--no-verify" in "builtins/push.c"),
only the "--no-<reftype>" syntax is listed in the updated
documentation.

Overview of the changes:
- Add an enum to represent the structure flags.
- Add structure flags to the options for the "repo structure" commands.
- For each reference flag, add a conditional in "count_references"
  which decides whether or not to add a ref to the pending list.
  If an references is not added to the pending list, the things it
  transitively references will not be added to the stats.
- Add a set of test cases to verify that reference counts
  in the repo structure report correctly omit the specified
  resource types.
- Update the documentation for git-repo to include the new options.

Signed-off-by: Mark C. Chu-Carroll <redacted>
---
 Documentation/git-repo.adoc |  35 ++++-
 builtin/repo.c              | 158 +++++++++++++++------
 t/t1901-repo-structure.sh   | 276 ++++++++++++++++++++++++++++++++++++
 3 files changed, 427 insertions(+), 42 deletions(-)
diff --git a/Documentation/git-repo.adoc b/Documentation/git-repo.adoc
index ed7d80c690..463260cd23 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] [--no-branches] [--no-tags] [--no-remotes] [--no-notes] [--no-stashes]`::
 
 DESCRIPTION
 -----------
@@ -56,7 +56,7 @@ supported:
 `nul`:::
 	Similar to `lines`, but using a _NUL_ character after each value.
 
-`structure [--format=(table|lines|nul) | -z]`::
+`structure [--format=(table|lines|nul) | -z] [--no-branches] [--no-tags] [--no-remotes] [--no-notes] [--no-stashes]`::
 	Retrieve statistics about the current repository structure. The
 	following kinds of information are reported:
 +
@@ -66,6 +66,23 @@ supported:
 * Total disk size of reachable objects by type
 * Largest reachable objects in the repository by type
 +
+The types of objects counted can be filtered using flags:
++
+`--no-branches`:::
+	Omit branch refs from the set of objects to count.
+
+`--no-tags`:::
+	Omit tags from the set of objects to count.
+
+`--no-remotes`:::
+	Omit remotes from the set of objects to count.
+
+`--no-notes`:::
+	Omit notes from the set of objects to count.
+
+`--no-stashes`:::
+	Omit stashes from the set of objects to count.
++
 The output format can be chosen through the flag `--format`. Three formats are
 supported:
 +
@@ -141,6 +158,20 @@ 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
+remotes:
++
+------------
+git repo structure --no-remotes
+------------
+
 SEE ALSO
 --------
 linkgit:git-rev-parse[1]
diff --git a/builtin/repo.c b/builtin/repo.c
index 84e012f83f..c8f6e38011 100644
--- a/builtin/repo.c
+++ b/builtin/repo.c
@@ -53,6 +53,20 @@ enum output_format {
 	FORMAT_NUL_TERMINATED,
 };
 
+enum repo_structure_filter_flags {
+	REPO_STRUCTURE_FILTER_BRANCHES = (1 << 0),
+	REPO_STRUCTURE_FILTER_TAGS = (1 << 1),
+	REPO_STRUCTURE_FILTER_REMOTES = (1 << 2),
+	REPO_STRUCTURE_FILTER_NOTES  = (1 << 3),
+	REPO_STRUCTURE_FILTER_STASHES = (1 << 4),
+};
+
+#define REPO_STRUCTURE_FILTER_FLAGS_ALL (REPO_STRUCTURE_FILTER_BRANCHES | \
+					 REPO_STRUCTURE_FILTER_TAGS |	\
+					 REPO_STRUCTURE_FILTER_REMOTES | \
+					 REPO_STRUCTURE_FILTER_NOTES |\
+					 REPO_STRUCTURE_FILTER_STASHES)
+
 struct repo_info_field {
 	const char *key;
 	get_value_fn *get_value;
@@ -490,7 +504,8 @@ static inline size_t get_total_object_values(struct object_values *values)
 }
 
 static void stats_table_setup_structure(struct stats_table *table,
-					struct repo_structure *stats)
+					struct repo_structure *stats,
+					enum repo_structure_filter_flags flags)
 {
 	struct object_stats *objects = &stats->objects;
 	struct ref_stats *refs = &stats->refs;
@@ -502,9 +517,15 @@ static void stats_table_setup_structure(struct stats_table *table,
 	ref_total = get_total_reference_count(refs);
 	stats_table_addf(table, "* %s", _("References"));
 	stats_table_count_addf(table, ref_total, "  * %s", _("Count"));
-	stats_table_count_addf(table, refs->branches, "    * %s", _("Branches"));
-	stats_table_count_addf(table, refs->tags, "    * %s", _("Tags"));
-	stats_table_count_addf(table, refs->remotes, "    * %s", _("Remotes"));
+	if (flags & REPO_STRUCTURE_FILTER_BRANCHES) {
+		stats_table_count_addf(table, refs->branches, "    * %s", _("Branches"));
+	}
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		stats_table_count_addf(table, refs->tags, "    * %s", _("Tags"));
+	}
+	if (flags & REPO_STRUCTURE_FILTER_REMOTES) {
+		stats_table_count_addf(table, refs->remotes, "    * %s", _("Remotes"));
+	}
 	stats_table_count_addf(table, refs->others, "    * %s", _("Others"));
 
 	object_count_total = get_total_object_values(&objects->type_counts);
@@ -517,8 +538,10 @@ static void stats_table_setup_structure(struct stats_table *table,
 			       "    * %s", _("Trees"));
 	stats_table_count_addf(table, objects->type_counts.blobs,
 			       "    * %s", _("Blobs"));
-	stats_table_count_addf(table, objects->type_counts.tags,
-			       "    * %s", _("Tags"));
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		stats_table_count_addf(table, objects->type_counts.tags,
+				       "    * %s", _("Tags"));
+	}
 
 	inflated_object_total = get_total_object_values(&objects->inflated_sizes);
 	stats_table_size_addf(table, inflated_object_total,
@@ -529,8 +552,11 @@ static void stats_table_setup_structure(struct stats_table *table,
 			      "    * %s", _("Trees"));
 	stats_table_size_addf(table, objects->inflated_sizes.blobs,
 			      "    * %s", _("Blobs"));
-	stats_table_size_addf(table, objects->inflated_sizes.tags,
-			      "    * %s", _("Tags"));
+
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		stats_table_size_addf(table, objects->inflated_sizes.tags,
+				      "    * %s", _("Tags"));
+	}
 
 	disk_object_total = get_total_object_values(&objects->disk_sizes);
 	stats_table_size_addf(table, disk_object_total,
@@ -541,8 +567,10 @@ static void stats_table_setup_structure(struct stats_table *table,
 			      "    * %s", _("Trees"));
 	stats_table_size_addf(table, objects->disk_sizes.blobs,
 			      "    * %s", _("Blobs"));
-	stats_table_size_addf(table, objects->disk_sizes.tags,
-			      "    * %s", _("Tags"));
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		stats_table_size_addf(table, objects->disk_sizes.tags,
+				      "    * %s", _("Tags"));
+	}
 
 	stats_table_addf(table, "");
 	stats_table_addf(table, "* %s", _("Largest objects"));
@@ -569,11 +597,13 @@ static void stats_table_setup_structure(struct stats_table *table,
 				     &objects->largest.blob_size.oid,
 				     objects->largest.blob_size.value,
 				     "    * %s", _("Maximum size"));
-	stats_table_addf(table, "  * %s", _("Tags"));
-	stats_table_object_size_addf(table,
-				     &objects->largest.tag_size.oid,
-				     objects->largest.tag_size.value,
-				     "    * %s", _("Maximum size"));
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		stats_table_addf(table, "  * %s", _("Tags"));
+		stats_table_object_size_addf(table,
+					     &objects->largest.tag_size.oid,
+					     objects->largest.tag_size.value,
+					     "    * %s", _("Maximum size"));
+	}
 }
 
 #define INDEX_WIDTH 4
@@ -681,14 +711,21 @@ static void print_object_data(const char *key, char key_delim,
 }
 
 static void structure_keyvalue_print(struct repo_structure *stats,
-				     char key_delim, char value_delim)
+				     char key_delim, char value_delim,
+				     enum repo_structure_filter_flags flags)
 {
-	print_keyvalue("references.branches.count", key_delim,
-		       stats->refs.branches, value_delim);
+	if (flags & REPO_STRUCTURE_FILTER_BRANCHES) {
+		print_keyvalue("references.branches.count", key_delim,
+			       stats->refs.branches, value_delim);
+	}
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
 	print_keyvalue("references.tags.count", key_delim,
 		       stats->refs.tags, value_delim);
-	print_keyvalue("references.remotes.count", key_delim,
-		       stats->refs.remotes, value_delim);
+	}
+	if (flags & REPO_STRUCTURE_FILTER_REMOTES) {
+		print_keyvalue("references.remotes.count", key_delim,
+			       stats->refs.remotes, value_delim);
+	}
 	print_keyvalue("references.others.count", key_delim,
 		       stats->refs.others, value_delim);
 
@@ -698,8 +735,10 @@ static void structure_keyvalue_print(struct repo_structure *stats,
 		       stats->objects.type_counts.trees, value_delim);
 	print_keyvalue("objects.blobs.count", key_delim,
 		       stats->objects.type_counts.blobs, value_delim);
-	print_keyvalue("objects.tags.count", key_delim,
-		       stats->objects.type_counts.tags, value_delim);
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		print_keyvalue("objects.tags.count", key_delim,
+			       stats->objects.type_counts.tags, value_delim);
+	}
 
 	print_keyvalue("objects.commits.inflated_size", key_delim,
 		       stats->objects.inflated_sizes.commits, value_delim);
@@ -707,8 +746,10 @@ static void structure_keyvalue_print(struct repo_structure *stats,
 		       stats->objects.inflated_sizes.trees, value_delim);
 	print_keyvalue("objects.blobs.inflated_size", key_delim,
 		       stats->objects.inflated_sizes.blobs, value_delim);
-	print_keyvalue("objects.tags.inflated_size", key_delim,
-		       stats->objects.inflated_sizes.tags, value_delim);
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		print_keyvalue("objects.tags.inflated_size", key_delim,
+			       stats->objects.inflated_sizes.tags, value_delim);
+	}
 
 	print_keyvalue("objects.commits.disk_size", key_delim,
 		       stats->objects.disk_sizes.commits, value_delim);
@@ -716,8 +757,10 @@ static void structure_keyvalue_print(struct repo_structure *stats,
 		       stats->objects.disk_sizes.trees, value_delim);
 	print_keyvalue("objects.blobs.disk_size", key_delim,
 		       stats->objects.disk_sizes.blobs, value_delim);
-	print_keyvalue("objects.tags.disk_size", key_delim,
-		       stats->objects.disk_sizes.tags, value_delim);
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		print_keyvalue("objects.tags.disk_size", key_delim,
+			       stats->objects.disk_sizes.tags, value_delim);
+	}
 
 	print_object_data("objects.commits.max_size", key_delim,
 			  &stats->objects.largest.commit_size, value_delim);
@@ -725,8 +768,10 @@ static void structure_keyvalue_print(struct repo_structure *stats,
 			  &stats->objects.largest.tree_size, value_delim);
 	print_object_data("objects.blobs.max_size", key_delim,
 			  &stats->objects.largest.blob_size, value_delim);
-	print_object_data("objects.tags.max_size", key_delim,
-			  &stats->objects.largest.tag_size, value_delim);
+	if (flags & REPO_STRUCTURE_FILTER_TAGS) {
+		print_object_data("objects.tags.max_size", key_delim,
+				  &stats->objects.largest.tag_size, value_delim);
+	}
 
 	print_object_data("objects.commits.max_parents", key_delim,
 			  &stats->objects.largest.parent_count, value_delim);
@@ -739,6 +784,7 @@ static void structure_keyvalue_print(struct repo_structure *stats,
 struct count_references_data {
 	struct ref_stats *stats;
 	struct rev_info *revs;
+	enum repo_structure_filter_flags flags;
 	struct progress *progress;
 };
 
@@ -747,19 +793,42 @@ static int count_references(const struct reference *ref, void *cb_data)
 	struct count_references_data *data = cb_data;
 	struct ref_stats *stats = data->stats;
 	size_t ref_count;
+	bool add_pending = false;
 
 	switch (ref_kind_from_refname(ref->name)) {
 	case FILTER_REFS_BRANCHES:
-		stats->branches++;
+		if (data->flags & REPO_STRUCTURE_FILTER_BRANCHES) {
+			stats->branches++;
+			add_pending = true;
+		}
 		break;
 	case FILTER_REFS_REMOTES:
-		stats->remotes++;
+		if (data->flags & REPO_STRUCTURE_FILTER_REMOTES) {
+			stats->remotes++;
+			add_pending = true;
+		}
 		break;
 	case FILTER_REFS_TAGS:
-		stats->tags++;
+		if (data->flags & REPO_STRUCTURE_FILTER_TAGS) {
+			stats->tags++;
+			add_pending = true;
+		}
 		break;
 	case FILTER_REFS_OTHERS:
-		stats->others++;
+		if (!strcmp(ref->name, "refs/stash")) {
+			if (data->flags & REPO_STRUCTURE_FILTER_STASHES) {
+				stats->others++;
+				add_pending = true;
+			}
+		} else if (starts_with(ref->name, "refs/notes")) {
+			if (data->flags & REPO_STRUCTURE_FILTER_NOTES) {
+				stats->others++;
+				add_pending = true;
+			}
+		} else {
+			stats->others++;
+			add_pending = true;
+		}
 		break;
 	default:
 		BUG("unexpected reference type");
@@ -769,10 +838,11 @@ static int count_references(const struct reference *ref, void *cb_data)
 	 * While iterating through references for counting, also add OIDs in
 	 * preparation for the path walk.
 	 */
-	add_pending_oid(data->revs, NULL, ref->oid, 0);
-
-	ref_count = get_total_reference_count(stats);
-	display_progress(data->progress, ref_count);
+	if (add_pending) {
+		add_pending_oid(data->revs, NULL, ref->oid, 0);
+		ref_count = get_total_reference_count(stats);
+		display_progress(data->progress, ref_count);
+	}
 
 	return 0;
 }
@@ -780,11 +850,13 @@ static int count_references(const struct reference *ref, void *cb_data)
 static void structure_count_references(struct ref_stats *stats,
 				       struct rev_info *revs,
 				       struct repository *repo,
+				       enum repo_structure_filter_flags flags,
 				       int show_progress)
 {
 	struct count_references_data data = {
 		.stats = stats,
 		.revs = revs,
+		.flags = flags,
 	};
 
 	if (show_progress)
@@ -935,6 +1007,7 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
 	struct repo_structure stats = { 0 };
 	struct rev_info revs;
 	int show_progress = -1;
+	int flags = REPO_STRUCTURE_FILTER_FLAGS_ALL;
 	struct option options[] = {
 		OPT_CALLBACK_F(0, "format", &format, N_("format"),
 			       N_("output format"),
@@ -944,6 +1017,11 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
 			       PARSE_OPT_NONEG | PARSE_OPT_NOARG,
 			       parse_format_cb),
 		OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
+		OPT_BIT(0, "branches", &flags, N_("include branches in structure statistics"), REPO_STRUCTURE_FILTER_BRANCHES),
+		OPT_BIT(0, "tags", &flags, N_("include tags in structure statistics"), REPO_STRUCTURE_FILTER_TAGS),
+		OPT_BIT(0, "remotes", &flags, N_("include remotes in structure statistics"), REPO_STRUCTURE_FILTER_REMOTES),
+		OPT_BIT(0, "notes", &flags, N_("include notes in structure statistics"), REPO_STRUCTURE_FILTER_NOTES),
+		OPT_BIT(0, "stashes", &flags, N_("include stashes in structure statistics"), REPO_STRUCTURE_FILTER_STASHES),
 		OPT_END()
 	};
 
@@ -956,19 +1034,19 @@ static int cmd_repo_structure(int argc, const char **argv, const char *prefix,
 	if (show_progress < 0)
 		show_progress = isatty(2);
 
-	structure_count_references(&stats.refs, &revs, repo, show_progress);
+	structure_count_references(&stats.refs, &revs, repo, flags, show_progress);
 	structure_count_objects(&stats.objects, &revs, repo, show_progress);
 
 	switch (format) {
 	case FORMAT_TABLE:
-		stats_table_setup_structure(&table, &stats);
+		stats_table_setup_structure(&table, &stats, flags);
 		stats_table_print_structure(&table);
 		break;
 	case FORMAT_NEWLINE_TERMINATED:
-		structure_keyvalue_print(&stats, '=', '\n');
+		structure_keyvalue_print(&stats, '=', '\n', flags);
 		break;
 	case FORMAT_NUL_TERMINATED:
-		structure_keyvalue_print(&stats, '\n', '\0');
+		structure_keyvalue_print(&stats, '\n', '\0', flags);
 		break;
 	default:
 		BUG("invalid output format");
diff --git a/t/t1901-repo-structure.sh b/t/t1901-repo-structure.sh
index 02cc2b594a..60a82493c6 100755
--- a/t/t1901-repo-structure.sh
+++ b/t/t1901-repo-structure.sh
@@ -144,6 +144,170 @@ test_expect_success SHA1 'repository with references and objects' '
 	)
 '
 
+
+test_expect_success SHA1 'repository with references and objects, filtered with --no-origins' '
+	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 other_branch &&
+		test_commit_bulk 5 &&
+
+		git checkout master &&
+
+		# 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      |
+		| ------------------------- | ---------- |
+		| * References              |            |
+		|   * Count                 |      4     |
+		|     * Branches            |      2     |
+		|     * Tags                |      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.04 MiB |
+		|     * Commits             | 219.00 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] 0a8f6a47f34078bb7c4b2bb4377c2133157f6703
+		[3] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
+		[4] 60665251ab71dbd8c18d9bf2174f4ee0d58aa06c
+		[5] 97d808e45116bf02103490294d3d46dad7a2ac62
+		[6] 4dae4f5954f5e6feb3577cfb1b181daa3fd3afd2
+		EOF
+		git repo structure --no-remotes >actual 2>err &&
+		test_cmp expect actual &&
+		test_line_count = 0 err
+	)
+'
+
+test_expect_success SHA1 'repository with references and objects, filtered with "--no-branches"' '
+	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 other_branch &&
+		test_commit_bulk 5 &&
+
+		git checkout master &&
+
+		# Also creates a commit, tree, and blob.
+		git notes add -m foo &&
+
+		git repo structure --no-branches >actual 2>err &&
+		test_line_count = 0 err &&
+		test_grep "|   \* Count                 |      3     |" actual &&
+		test_grep "|     \* Others              |      1     |" actual &&
+		test_grep !  "Branches" actual
+	)
+'
+
+test_expect_success SHA1 'repository with references and objects, filtered with "--no-notes"' '
+	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 other_branch &&
+		test_commit_bulk 5 &&
+
+		git checkout master &&
+
+		# Also creates a commit, tree, and blob.
+		git notes add -m foo &&
+
+		git repo structure --no-notes >actual 2>err &&
+		test_line_count = 0 err &&
+		test_grep "|   \* Count                 |      4     |" actual &&
+		test_grep "|     \* Others              |      0     |" actual &&
+		test_grep "|     \* Commits             | 218.81 KiB |" actual
+	)
+'
+
+test_expect_success SHA1 'repository with references and objects, filtered with multiple flags' '
+	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 other_branch &&
+		test_commit_bulk 5 &&
+
+		git checkout master &&
+
+		# Also creates a commit, tree, and blob.
+		git notes add -m foo &&
+
+		git repo structure --no-notes --no-branches >actual 2>err &&
+		test_line_count = 0 err &&
+		test_grep "|   \* Count                 |      2     |" actual &&
+		test_grep "|     \* Others              |      0     |" actual &&
+		test_grep "|     \* Commits             | 217.73 KiB |" actual &&
+		test_grep !  "Branches" actual &&
+
+		git repo structure --no-notes --no-branches --no-remotes >actual 2>err &&
+		test_line_count = 0 err &&
+		test_grep "|   \* Count                 |      1     |" actual &&
+		test_grep "|     \* Others              |      0     |" actual &&
+		test_grep "|     \* Commits             | 217.73 KiB |" actual &&
+		test_grep !  "Branches" actual &&
+		test_grep ! "Remotes" actual
+	)
+'
+
 test_expect_success SHA1 'lines and nul format' '
 	test_when_finished "rm -rf repo" &&
 	git init repo &&
@@ -203,6 +367,118 @@ test_expect_success SHA1 'lines and nul format' '
 		test_line_count = 0 err
 	)
 '
+test_expect_success SHA1 'lines and nul format with --no-tags filter' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit_bulk 42 &&
+		git tag -a foo -m bar &&
+
+		cat >expect <<-EOF &&
+		references.branches.count=1
+		references.remotes.count=0
+		references.others.count=0
+		objects.commits.count=42
+		objects.trees.count=42
+		objects.blobs.count=42
+		objects.commits.inflated_size=9225
+		objects.trees.inflated_size=28554
+		objects.blobs.inflated_size=453
+		objects.commits.disk_size=$(object_type_disk_usage commit)
+		objects.trees.disk_size=$(object_type_disk_usage tree)
+		objects.blobs.disk_size=$(object_type_disk_usage blob)
+		objects.commits.max_size=221
+		objects.commits.max_size_oid=de3508174b5c2ace6993da67cae9be9069e2df39
+		objects.trees.max_size=1335
+		objects.trees.max_size_oid=09931deea9d81ec21300d3e13c74412f32eacec5
+		objects.blobs.max_size=11
+		objects.blobs.max_size_oid=eaeeedced46482bd4281fda5a5f05ce24854151f
+		objects.commits.max_parents=1
+		objects.commits.max_parents_oid=de3508174b5c2ace6993da67cae9be9069e2df39
+		objects.trees.max_entries=42
+		objects.trees.max_entries_oid=09931deea9d81ec21300d3e13c74412f32eacec5
+		EOF
+
+		git repo structure --format=lines --no-tags >actual 2>err &&
+		test_cmp expect actual &&
+		test_line_count = 0 err &&
+
+		git repo structure --format=nul --no-tags >out 2>err &&
+		tr "\012\000" "=\012" <out >actual &&
+
+		test_cmp expect actual &&
+		test_line_count = 0 err &&
+
+		# "-z", as a synonym to "--format=nul", participates in the
+		# usual "last one wins" rule.
+		git repo structure --format=table -z --no-tags >out 2>err &&
+		tr "\012\000" "=\012" <out >actual &&
+
+		test_cmp expect actual &&
+		test_line_count = 0 err
+	)
+'
+
+test_expect_success SHA1 'lines and nul format with --no-branches filter' '
+	test_when_finished "rm -rf repo" &&
+	git init repo &&
+	(
+		cd repo &&
+		test_commit_bulk 42 &&
+		git tag -a foo -m bar &&
+
+		cat >expect <<-EOF &&
+		references.tags.count=1
+		references.remotes.count=0
+		references.others.count=0
+		objects.commits.count=42
+		objects.trees.count=42
+		objects.blobs.count=42
+		objects.tags.count=1
+		objects.commits.inflated_size=9225
+		objects.trees.inflated_size=28554
+		objects.blobs.inflated_size=453
+		objects.tags.inflated_size=132
+		objects.commits.disk_size=$(object_type_disk_usage commit)
+		objects.trees.disk_size=$(object_type_disk_usage tree)
+		objects.blobs.disk_size=$(object_type_disk_usage blob)
+		objects.tags.disk_size=$(object_type_disk_usage tag)
+		objects.commits.max_size=221
+		objects.commits.max_size_oid=de3508174b5c2ace6993da67cae9be9069e2df39
+		objects.trees.max_size=1335
+		objects.trees.max_size_oid=09931deea9d81ec21300d3e13c74412f32eacec5
+		objects.blobs.max_size=11
+		objects.blobs.max_size_oid=eaeeedced46482bd4281fda5a5f05ce24854151f
+		objects.tags.max_size=132
+		objects.tags.max_size_oid=1ee0f2b16ea37d895dbe9dbd76cd2ac70446176c
+		objects.commits.max_parents=1
+		objects.commits.max_parents_oid=de3508174b5c2ace6993da67cae9be9069e2df39
+		objects.trees.max_entries=42
+		objects.trees.max_entries_oid=09931deea9d81ec21300d3e13c74412f32eacec5
+		EOF
+
+		git repo structure --format=lines --no-branches >actual 2>err &&
+		cp expect /tmp/expect &&
+		cp actual /tmp/actual &&
+		test_cmp expect actual &&
+		test_line_count = 0 err &&
+
+		git repo structure --format=nul --no-branches >out 2>err &&
+		tr "\012\000" "=\012" <out >actual &&
+
+		test_cmp expect actual &&
+		test_line_count = 0 err &&
+
+		# "-z", as a synonym to "--format=nul", participates in the
+		# usual "last one wins" rule.
+		git repo structure --format=table -z --no-branches >out 2>err &&
+		tr "\012\000" "=\012" <out >actual &&
+
+		test_cmp expect actual &&
+		test_line_count = 0 err
+	)
+'
 
 test_expect_success 'progress meter option' '
 	test_when_finished "rm -rf repo" &&
-- 
2.53.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help