diff options
author | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-06-15 09:04:30 +0300 |
---|---|---|
committer | Patrick Steinhardt <psteinhardt@gitlab.com> | 2021-06-21 08:49:55 +0300 |
commit | 7a33a3366d9b6b67dadec40e64b15f57e45bce04 (patch) | |
tree | 069a49b392c776f74035e35d2955d2986a92ba86 | |
parent | 0d53150dceed1c90dd2119291add50d86b6a4702 (diff) |
blob: Implement support for object type filters
Implement support for object type filters in the revlist pipeline step.
In combination with `--filter-provided-objects`, this filter will cause
git-rev-list(1) to only print objects which match the filtered type.
This option is not used yet, but will be used in the subsequent commit
which implements object type filters for LFS pointers.
-rw-r--r-- | internal/gitaly/service/blob/pipeline.go | 28 | ||||
-rw-r--r-- | internal/gitaly/service/blob/pipeline_test.go | 98 |
2 files changed, 125 insertions, 1 deletions
diff --git a/internal/gitaly/service/blob/pipeline.go b/internal/gitaly/service/blob/pipeline.go index 1ccc251f6..52500b401 100644 --- a/internal/gitaly/service/blob/pipeline.go +++ b/internal/gitaly/service/blob/pipeline.go @@ -28,9 +28,19 @@ type revlistResult struct { objectName []byte } +type objectType string + +const ( + objectTypeCommit = objectType("commit") + objectTypeBlob = objectType("blob") + objectTypeTree = objectType("tree") + objectTypeTag = objectType("tag") +) + // revlistConfig is configuration for the revlist pipeline step. type revlistConfig struct { - blobLimit int + blobLimit int + objectType objectType } // revlistOption is an option for the revlist pipeline step. @@ -44,6 +54,16 @@ func withBlobLimit(limit int) revlistOption { } } +// withObjectTypeFilter will set up a `--filter=object:type=` filter for git-rev-list(1). This will +// cause it to filter out any objects which do not match the given type. Because git-rev-list(1) by +// default never filters provided arguments, this option also sets up the `--filter-provided` flag. +// Note that this option is only supported starting with Git v2.32.0 or later. +func withObjectTypeFilter(t objectType) revlistOption { + return func(cfg *revlistConfig) { + cfg.objectType = t + } +} + // revlist runs git-rev-list(1) with objects and object names enabled. The returned channel will // contain all object IDs listed by this command. Cancelling the context will cause the pipeline to // be cancelled, too. @@ -81,6 +101,12 @@ func revlist( Name: fmt.Sprintf("--filter=blob:limit=%d", cfg.blobLimit), }) } + if cfg.objectType != "" { + flags = append(flags, + git.Flag{Name: fmt.Sprintf("--filter=object:type=%s", cfg.objectType)}, + git.Flag{Name: "--filter-provided-objects"}, + ) + } revlist, err := repo.Exec(ctx, git.SubCmd{ Name: "rev-list", diff --git a/internal/gitaly/service/blob/pipeline_test.go b/internal/gitaly/service/blob/pipeline_test.go index 92469b0c8..96c071d13 100644 --- a/internal/gitaly/service/blob/pipeline_test.go +++ b/internal/gitaly/service/blob/pipeline_test.go @@ -9,6 +9,7 @@ import ( "testing" "github.com/stretchr/testify/require" + "gitlab.com/gitlab-org/gitaly/v14/internal/git" "gitlab.com/gitlab-org/gitaly/v14/internal/git/catfile" "gitlab.com/gitlab-org/gitaly/v14/internal/git/gittest" "gitlab.com/gitlab-org/gitaly/v14/internal/git/localrepo" @@ -23,8 +24,21 @@ func TestRevlist(t *testing.T) { defer cleanup() repo := localrepo.NewTestRepo(t, cfg, repoProto) + needsObjectTypeFilters := func(t *testing.T) { + ctx, cancel := testhelper.Context() + defer cancel() + + gitVersion, err := git.CurrentVersion(ctx, git.NewExecCommandFactory(cfg)) + require.NoError(t, err) + + if !gitVersion.SupportsObjectTypeFilter() { + t.Skip("Git does not support object type filters") + } + } + for _, tc := range []struct { desc string + precondition func(t *testing.T) revisions []string options []revlistOption expectedResults []revlistResult @@ -131,6 +145,86 @@ func TestRevlist(t *testing.T) { }, }, { + desc: "tree with blob object type filter", + precondition: needsObjectTypeFilters, + revisions: []string{ + "79d5f98270ad677c86a7e1ab2baa922958565135", + }, + options: []revlistOption{ + withObjectTypeFilter(objectTypeBlob), + }, + expectedResults: []revlistResult{ + {oid: "8af7f880ce38649fc49f66e3f38857bfbec3f0b7", objectName: []byte("feature-1.txt")}, + {oid: "16ca0b267f82cd2f5ca1157dd162dae98745eab8", objectName: []byte("feature-2.txt")}, + {oid: "0fb47f093f769008049a0b0976ac3fa6d6125033", objectName: []byte("hotfix-1.txt")}, + {oid: "4ae6c5e14452a35d04156277ae63e8356eb17cae", objectName: []byte("hotfix-2.txt")}, + {oid: "b988ffed90cb6a9b7f98a3686a933edb3c5d70c0", objectName: []byte("iso8859.txt")}, + {oid: "570f8e1dfe8149c1d17002712310d43dfeb43159", objectName: []byte("russian.rb")}, + {oid: "7a17968582c21c9153ec24c6a9d5f33592ad9103", objectName: []byte("test.txt")}, + {oid: "f3064a3aa9c14277483f690250072e987e2c8356", objectName: []byte("\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt")}, + {oid: "3a26c18b02e843b459732e7ade7ab9a154a1002b", objectName: []byte("\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.xls")}, + }, + }, + { + desc: "tree with tag object type filter", + precondition: needsObjectTypeFilters, + revisions: []string{ + "--all", + }, + options: []revlistOption{ + withObjectTypeFilter(objectTypeTag), + }, + expectedResults: []revlistResult{ + {oid: "f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8", objectName: []byte("v1.0.0")}, + {oid: "8a2a6eb295bb170b34c24c76c49ed0e9b2eaf34b", objectName: []byte("v1.1.0")}, + {oid: "8f03acbcd11c53d9c9468078f32a2622005a4841", objectName: []byte("v1.1.1")}, + }, + }, + { + desc: "tree with commit object type filter", + precondition: needsObjectTypeFilters, + revisions: []string{ + "79d5f98270ad677c86a7e1ab2baa922958565135", + }, + options: []revlistOption{ + withObjectTypeFilter(objectTypeTree), + }, + expectedResults: []revlistResult{ + {oid: "79d5f98270ad677c86a7e1ab2baa922958565135"}, + }, + }, + { + desc: "tree with commit object type filter", + precondition: needsObjectTypeFilters, + revisions: []string{ + "^refs/heads/master~", + "refs/heads/master", + }, + options: []revlistOption{ + withObjectTypeFilter(objectTypeCommit), + }, + expectedResults: []revlistResult{ + {oid: "1e292f8fedd741b75372e19097c76d327140c312"}, + {oid: "c1c67abbaf91f624347bb3ae96eabe3a1b742478"}, + }, + }, + { + desc: "tree with object type and blob size filter", + precondition: needsObjectTypeFilters, + revisions: []string{ + "79d5f98270ad677c86a7e1ab2baa922958565135", + }, + options: []revlistOption{ + withBlobLimit(10), + withObjectTypeFilter(objectTypeBlob), + }, + expectedResults: []revlistResult{ + {oid: "0fb47f093f769008049a0b0976ac3fa6d6125033", objectName: []byte("hotfix-1.txt")}, + {oid: "4ae6c5e14452a35d04156277ae63e8356eb17cae", objectName: []byte("hotfix-2.txt")}, + {oid: "b988ffed90cb6a9b7f98a3686a933edb3c5d70c0", objectName: []byte("iso8859.txt")}, + }, + }, + { desc: "invalid revision", revisions: []string{ "refs/heads/does-not-exist", @@ -151,6 +245,10 @@ func TestRevlist(t *testing.T) { }, } { t.Run(tc.desc, func(t *testing.T) { + if tc.precondition != nil { + tc.precondition(t) + } + ctx, cancel := testhelper.Context() defer cancel() |