Show changes to 3 files +427 −42
Documentation/git-repo.adoc, builtin/repo.c, t/t1901-repo-structure.sh
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" &&