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-10-13 14:34:54 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2021-10-20 09:09:21 +0300
commit4ee94b7552c87bab24244c76ce9e6a858b56772c (patch)
tree25f948327094479c19e09ca994159b6560a0800b
parent3e33398fb41596f2db0d9621f6d0b902dee468cb (diff)
gitpipe: Allow specifying revisions in `ForEachRef()` step
Add a new option which allows the caller to specify the format to be used by git-for-each-ref(1). While the actual format must always be in the format '%(objectname) %(refname)', the caller can play some tricks to inject additional lines into the format via conditional format items or may change the refname, if he intends to. The new option is not yet used.
-rw-r--r--internal/git/gitpipe/revision.go35
-rw-r--r--internal/git/gitpipe/revision_test.go35
2 files changed, 55 insertions, 15 deletions
diff --git a/internal/git/gitpipe/revision.go b/internal/git/gitpipe/revision.go
index 87d688f62..a21cbcfda 100644
--- a/internal/git/gitpipe/revision.go
+++ b/internal/git/gitpipe/revision.go
@@ -311,6 +311,22 @@ func Revlist(
}
}
+type forEachRefConfig struct {
+ format string
+}
+
+// ForEachRefOption is an option that can be passed to ForEachRef.
+type ForEachRefOption func(cfg *forEachRefConfig)
+
+// WithForEachRefFormat is the format used by git-for-each-ref. Note that each line _must_ be of
+// format "%(objectname) %(refname)" such that the pipeline can parse it correctly. You may use
+// conditional format statements though to potentially produce multiple such lines.
+func WithForEachRefFormat(format string) ForEachRefOption {
+ return func(cfg *forEachRefConfig) {
+ cfg.format = format
+ }
+}
+
// ForEachRef runs git-for-each-ref(1) with the given patterns and returns a RevisionIterator for
// found references. Patterns must always refer to fully qualified reference names. Patterns for
// which no branch is found do not result in an error. The iterator's object name is set to the
@@ -321,18 +337,25 @@ func ForEachRef(
repo *localrepo.Repo,
patterns []string,
sortField string,
+ opts ...ForEachRefOption,
) RevisionIterator {
- resultChan := make(chan RevisionResult)
+ cfg := forEachRefConfig{
+ // The default format also includes the object type, which requires us to read the
+ // referenced commit's object. It would thus be about 2-3x slower to use the
+ // default format, and instead we move the burden into the next pipeline step by
+ // default.
+ format: "%(objectname) %(refname)",
+ }
+ for _, opt := range opts {
+ opt(&cfg)
+ }
+ resultChan := make(chan RevisionResult)
go func() {
defer close(resultChan)
flags := []git.Option{
- // The default format also includes the object type, which requires
- // us to read the referenced commit's object. It would thus be about
- // 2-3x slower to use the default format, and instead we move the
- // burden into the next pipeline step.
- git.ValueFlag{Name: "--format", Value: "%(objectname) %(refname)"},
+ git.ValueFlag{Name: "--format", Value: cfg.format},
}
if sortField != "" {
flags = append(flags, git.ValueFlag{Name: "--sort", Value: sortField})
diff --git a/internal/git/gitpipe/revision_test.go b/internal/git/gitpipe/revision_test.go
index ee942328b..9c56f806c 100644
--- a/internal/git/gitpipe/revision_test.go
+++ b/internal/git/gitpipe/revision_test.go
@@ -503,8 +503,8 @@ func TestForEachRef(t *testing.T) {
ctx, cancel := testhelper.Context()
defer cancel()
- readRefs := func(t *testing.T, repo *localrepo.Repo, patterns ...string) []RevisionResult {
- it := ForEachRef(ctx, repo, patterns, "")
+ readRefs := func(t *testing.T, repo *localrepo.Repo, patterns []string, opts ...ForEachRefOption) []RevisionResult {
+ it := ForEachRef(ctx, repo, patterns, "", opts...)
var results []RevisionResult
for it.Next() {
@@ -532,11 +532,11 @@ func TestForEachRef(t *testing.T) {
ObjectName: []byte("refs/heads/master"),
OID: revisions["refs/heads/master"],
},
- }, readRefs(t, repo, "refs/heads/master"))
+ }, readRefs(t, repo, []string{"refs/heads/master"}))
})
t.Run("unqualified branch name", func(t *testing.T) {
- require.Nil(t, readRefs(t, repo, "master"))
+ require.Nil(t, readRefs(t, repo, []string{"master"}))
})
t.Run("multiple branches", func(t *testing.T) {
@@ -549,11 +549,11 @@ func TestForEachRef(t *testing.T) {
ObjectName: []byte("refs/heads/master"),
OID: revisions["refs/heads/master"],
},
- }, readRefs(t, repo, "refs/heads/master", "refs/heads/feature"))
+ }, readRefs(t, repo, []string{"refs/heads/master", "refs/heads/feature"}))
})
t.Run("branches pattern", func(t *testing.T) {
- refs := readRefs(t, repo, "refs/heads/*")
+ refs := readRefs(t, repo, []string{"refs/heads/*"})
require.Greater(t, len(refs), 90)
require.Subset(t, refs, []RevisionResult{
@@ -568,17 +568,34 @@ func TestForEachRef(t *testing.T) {
})
})
+ t.Run("tag with format", func(t *testing.T) {
+ refs := readRefs(t, repo, []string{"refs/tags/v1.0.0"},
+ WithForEachRefFormat("%(objectname) tag\n%(*objectname) peeled"),
+ )
+
+ require.Equal(t, refs, []RevisionResult{
+ {
+ ObjectName: []byte("tag"),
+ OID: "f4e6814c3e4e7a0de82a9e7cd20c626cc963a2f8",
+ },
+ {
+ ObjectName: []byte("peeled"),
+ OID: "6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9",
+ },
+ })
+ })
+
t.Run("multiple patterns", func(t *testing.T) {
- refs := readRefs(t, repo, "refs/heads/*", "refs/tags/*")
+ refs := readRefs(t, repo, []string{"refs/heads/*", "refs/tags/*"})
require.Greater(t, len(refs), 90)
})
t.Run("nonexisting branch", func(t *testing.T) {
- require.Nil(t, readRefs(t, repo, "refs/heads/idontexist"))
+ require.Nil(t, readRefs(t, repo, []string{"refs/heads/idontexist"}))
})
t.Run("nonexisting pattern", func(t *testing.T) {
- require.Nil(t, readRefs(t, repo, "refs/idontexist/*"))
+ require.Nil(t, readRefs(t, repo, []string{"refs/idontexist/*"}))
})
}