diff --git a/Documentation/git-pack-objects.adoc b/Documentation/git-pack-objects.adoc index f2852ebd31..8a27aa19fd 100644 --- a/Documentation/git-pack-objects.adoc +++ b/Documentation/git-pack-objects.adoc @@ -405,7 +405,8 @@ will be automatically changed to version `1`. Incompatible with `--delta-islands`. The `--use-bitmap-index` option is ignored in the presence of `--path-walk`. The `--path-walk` option supports the `--filter=` forms `blob:none`, `blob:limit=`, -`tree:0`, `object:type=`, and `sparse:`. +`tree:0`, `object:type=`, and `sparse:`. These supported filter +types can be combined with the `combine:+` form. DELTA ISLANDS diff --git a/path-walk.c b/path-walk.c index 418972e753..94ff90bd15 100644 --- a/path-walk.c +++ b/path-walk.c @@ -571,8 +571,8 @@ static int setup_pending_objects(struct path_walk_info *info, return 0; } -static int prepare_filters(struct path_walk_info *info, - struct list_objects_filter_options *options) +static int prepare_filters_one(struct path_walk_info *info, + struct list_objects_filter_options *options) { switch (options->choice) { case LOFC_DISABLED: @@ -589,7 +589,8 @@ static int prepare_filters(struct path_walk_info *info, if (info) { if (!options->blob_limit_value) info->blobs = 0; - else + else if (!info->blob_limit || + info->blob_limit > options->blob_limit_value) info->blob_limit = options->blob_limit_value; list_objects_filter_release(options); } @@ -604,7 +605,6 @@ static int prepare_filters(struct path_walk_info *info, if (info) { info->trees = 0; info->blobs = 0; - list_objects_filter_release(options); } return 1; @@ -656,8 +656,13 @@ static int prepare_filters(struct path_walk_info *info, warning(_("sparse filter is not cone-mode compatible")); return 0; } + } + return 1; - list_objects_filter_release(options); + case LOFC_COMBINE: + for (size_t i = 0; i < options->sub_nr; i++) { + if (!prepare_filters_one(info, &options->sub[i])) + return 0; } return 1; @@ -668,6 +673,16 @@ static int prepare_filters(struct path_walk_info *info, } } +static int prepare_filters(struct path_walk_info *info, + struct list_objects_filter_options *options) +{ + if (!prepare_filters_one(info, options)) + return 0; + if (info) + list_objects_filter_release(options); + return 1; +} + int path_walk_filter_compatible(struct list_objects_filter_options *options) { return prepare_filters(NULL, options); diff --git a/t/t6601-path-walk.sh b/t/t6601-path-walk.sh index 0fd8e61c76..e9fcd85e75 100755 --- a/t/t6601-path-walk.sh +++ b/t/t6601-path-walk.sh @@ -727,6 +727,77 @@ test_expect_success 'all, object:type=blob filter' ' test_cmp_sorted expect out ' +test_expect_success 'all, combine:blob:none+tree:0 filter' ' + test-tool path-walk \ + --filter=combine:blob:none+tree:0 -- --all >out && + + cat >expect <<-EOF && + 0:commit::$(git rev-parse topic) + 0:commit::$(git rev-parse base) + 0:commit::$(git rev-parse base~1) + 0:commit::$(git rev-parse base~2) + 1:tag:/tags:$(git rev-parse refs/tags/first) + 1:tag:/tags:$(git rev-parse refs/tags/second.1) + 1:tag:/tags:$(git rev-parse refs/tags/second.2) + 1:tag:/tags:$(git rev-parse refs/tags/third) + 1:tag:/tags:$(git rev-parse refs/tags/fourth) + 1:tag:/tags:$(git rev-parse refs/tags/tree-tag) + 1:tag:/tags:$(git rev-parse refs/tags/blob-tag) + 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) + 2:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) + 3:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag^{tree}) + 3:tree:/tagged-trees:$(git rev-parse refs/tags/tree-tag2) + blobs:2 + commits:4 + tags:7 + trees:2 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'all, combine:object:type=blob+blob:limit=3 filter' ' + test-tool path-walk \ + --filter=combine:object:type=blob+blob:limit=3 \ + -- --all >out && + + cat >expect <<-EOF && + 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag^{}) + 0:blob:/tagged-blobs:$(git rev-parse refs/tags/blob-tag2^{}) + 1:blob:a:$(git rev-parse base~2:a) + 2:blob:left/b:$(git rev-parse base~2:left/b) + 3:blob:right/c:$(git rev-parse base~2:right/c) + 4:blob:right/d:$(git rev-parse base~1:right/d) + blobs:6 + commits:0 + tags:0 + trees:0 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'all, combine of disjoint object:types is empty' ' + test-tool path-walk \ + --filter=combine:object:type=blob+object:type=tree \ + -- --all >out && + + cat >expect <<-EOF && + blobs:0 + commits:0 + tags:0 + trees:0 + EOF + + test_cmp_sorted expect out +' + +test_expect_success 'combine: rejects unsupported subfilters' ' + test_must_fail test-tool path-walk \ + --filter=combine:tree:1+blob:none -- --all 2>err && + test_grep "tree:1 filter not supported by the path-walk API" err +' + test_expect_success 'setup sparse filter blob' ' # Cone-mode patterns: include root, exclude all dirs, include left/ cat >patterns <<-\EOF &&