]> git.ipfire.org Git - thirdparty/git.git/commitdiff
builtin/cat-file: support "blob:limit=" objects filter
authorPatrick Steinhardt <ps@pks.im>
Wed, 2 Apr 2025 11:13:40 +0000 (13:13 +0200)
committerJunio C Hamano <gitster@pobox.com>
Mon, 7 Apr 2025 21:43:50 +0000 (14:43 -0700)
Implement support for the "blob:limit=" filter in git-cat-file(1), which
causes us to omit all blobs that are bigger than a certain size.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-cat-file.adoc
builtin/cat-file.c
t/t1006-cat-file.sh

index afcdb0a473802535f9e1fc7b37334aafa0287326..48e05e1af52253baca8d1b15840953de07977d4f 100644 (file)
@@ -91,6 +91,11 @@ OPTIONS
        printed at all. The '<filter-spec>' may be one of the following:
 +
 The form '--filter=blob:none' omits all blobs.
++
+The form '--filter=blob:limit=<n>[kmg]' omits blobs of size at least n
+bytes or units.  n may be zero.  The suffixes k, m, and g can be used to name
+units in KiB, MiB, or GiB.  For example, 'blob:limit=1k' is the same as
+'blob:limit=1024'.
 
 --path=<path>::
        For use with `--textconv` or `--filters`, to allow specifying an object
index bcceb646f85dfd84d568554e3ee93e71226320a4..629c6cddcb2239f4c4bddaa590ae72bcfe9b7878 100644 (file)
@@ -483,8 +483,11 @@ static void batch_object_write(const char *obj_name,
                int ret;
 
                if (use_mailmap ||
-                   opt->objects_filter.choice == LOFC_BLOB_NONE)
+                   opt->objects_filter.choice == LOFC_BLOB_NONE ||
+                   opt->objects_filter.choice == LOFC_BLOB_LIMIT)
                        data->info.typep = &data->type;
+               if (opt->objects_filter.choice == LOFC_BLOB_LIMIT)
+                       data->info.sizep = &data->size;
 
                if (pack)
                        ret = packed_object_info(the_repository, pack, offset,
@@ -509,6 +512,15 @@ static void batch_object_write(const char *obj_name,
                                return;
                        }
                        break;
+               case LOFC_BLOB_LIMIT:
+                       if (data->type == OBJ_BLOB &&
+                           data->size >= opt->objects_filter.blob_limit_value) {
+                               if (!opt->all_objects)
+                                       report_object_status(opt, obj_name,
+                                                            &data->oid, "excluded");
+                               return;
+                       }
+                       break;
                default:
                        BUG("unsupported objects filter");
                }
@@ -1049,6 +1061,7 @@ int cmd_cat_file(int argc,
        case LOFC_DISABLED:
                break;
        case LOFC_BLOB_NONE:
+       case LOFC_BLOB_LIMIT:
                if (!batch.enabled)
                        usage(_("objects filter only supported in batch mode"));
                break;
index 7404c135b1e5877c2b8be382f80098124a9c8f4b..4f14840b71a15f05837efd850511e64baeab6c92 100755 (executable)
@@ -1356,11 +1356,12 @@ test_expect_success PERL '--batch-command info is unbuffered by default' '
 test_expect_success 'setup for objects filter' '
        git init repo &&
        (
-               # Seed the repository with three different sets of objects:
+               # Seed the repository with four different sets of objects:
                #
                #   - The first set is fully packed and has a bitmap.
                #   - The second set is packed, but has no bitmap.
                #   - The third set is loose.
+               #   - The fourth set is loose and contains big objects.
                #
                # This ensures that we cover all these types as expected.
                cd repo &&
@@ -1368,7 +1369,14 @@ test_expect_success 'setup for objects filter' '
                git repack -Adb &&
                test_commit second &&
                git repack -d &&
-               test_commit third
+               test_commit third &&
+
+               for n in 1000 10000
+               do
+                       printf "%"$n"s" X >large.$n || return 1
+               done &&
+               git add large.* &&
+               git commit -m fourth
        )
 '
 
@@ -1380,7 +1388,7 @@ test_expect_success 'objects filter with unknown option' '
        test_cmp expect err
 '
 
-for option in blob:limit=1 object:type=tag sparse:oid=1234 tree:1 sparse:path=x
+for option in object:type=tag sparse:oid=1234 tree:1 sparse:path=x
 do
        test_expect_success "objects filter with unsupported option $option" '
                case "$option" in
@@ -1435,5 +1443,9 @@ test_objects_filter () {
 }
 
 test_objects_filter "blob:none"
+test_objects_filter "blob:limit=1"
+test_objects_filter "blob:limit=500"
+test_objects_filter "blob:limit=1000"
+test_objects_filter "blob:limit=1k"
 
 test_done