Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2021-06-15 09:04:30 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2021-06-21 08:49:55 +0300
commit7a33a3366d9b6b67dadec40e64b15f57e45bce04 (patch)
tree069a49b392c776f74035e35d2955d2986a92ba86
parent0d53150dceed1c90dd2119291add50d86b6a4702 (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.go28
-rw-r--r--internal/gitaly/service/blob/pipeline_test.go98
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()