diff options
author | Paul Okstad <pokstad@gitlab.com> | 2019-02-19 09:55:53 +0300 |
---|---|---|
committer | Paul Okstad <pokstad@gitlab.com> | 2019-02-19 09:55:53 +0300 |
commit | 08cf43fbc9617048aabdbf13a155afa867c3e90e (patch) | |
tree | a72bae49a760003112aa3eba12559b27c78e62a5 | |
parent | b1acee114bc120a525d04dd10a695fb7f5964d9c (diff) | |
parent | c83a6ff9db683806f60e5b3a23064535d66d0b1e (diff) |
Merge branch 'zj-delete-ref-go' into 'master'
Reimplement DeleteRefs in Go
See merge request gitlab-org/gitaly!1069
-rw-r--r-- | changelogs/unreleased/zj-delete-ref-go.yml | 5 | ||||
-rw-r--r-- | internal/service/ref/delete_refs.go | 73 | ||||
-rw-r--r-- | internal/service/ref/delete_refs_test.go | 3 | ||||
-rw-r--r-- | ruby/lib/gitaly_server/ref_service.rb | 1 |
4 files changed, 75 insertions, 7 deletions
diff --git a/changelogs/unreleased/zj-delete-ref-go.yml b/changelogs/unreleased/zj-delete-ref-go.yml new file mode 100644 index 000000000..a46ac3e18 --- /dev/null +++ b/changelogs/unreleased/zj-delete-ref-go.yml @@ -0,0 +1,5 @@ +--- +title: Reimplement DeleteRefs in Go +merge_request: 1069 +author: +type: performance diff --git a/internal/service/ref/delete_refs.go b/internal/service/ref/delete_refs.go index 34fc0c2aa..e47764f94 100644 --- a/internal/service/ref/delete_refs.go +++ b/internal/service/ref/delete_refs.go @@ -1,11 +1,15 @@ package ref import ( + "bufio" "context" "fmt" + "strings" "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" - "gitlab.com/gitlab-org/gitaly/internal/rubyserver" + "gitlab.com/gitlab-org/gitaly/internal/git" + "gitlab.com/gitlab-org/gitaly/internal/git/updateref" + "gitlab.com/gitlab-org/gitaly/internal/helper" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) @@ -15,17 +19,74 @@ func (s *server) DeleteRefs(ctx context.Context, in *gitalypb.DeleteRefsRequest) return nil, status.Errorf(codes.InvalidArgument, "DeleteRefs: %v", err) } - client, err := s.RefServiceClient(ctx) + updater, err := updateref.New(ctx, in.GetRepository()) if err != nil { - return nil, err + return nil, helper.ErrInternal(err) } - clientCtx, err := rubyserver.SetHeaders(ctx, in.GetRepository()) + refnames, err := refsToRemove(ctx, in) if err != nil { - return nil, err + return nil, helper.ErrInternal(err) } - return client.DeleteRefs(clientCtx, in) + for _, ref := range refnames { + if err := updater.Delete(ref); err != nil { + return &gitalypb.DeleteRefsResponse{GitError: err.Error()}, nil + } + } + + if err := updater.Wait(); err != nil { + return &gitalypb.DeleteRefsResponse{GitError: fmt.Sprintf("unable to delete refs: %s", err.Error())}, nil + } + + return &gitalypb.DeleteRefsResponse{}, nil +} + +func refsToRemove(ctx context.Context, req *gitalypb.DeleteRefsRequest) ([]string, error) { + var refs []string + if len(req.Refs) > 0 { + for _, ref := range req.Refs { + refs = append(refs, string(ref)) + } + return refs, nil + } + + cmd, err := git.Command(ctx, req.GetRepository(), "for-each-ref", "--format=%(refname)") + if err != nil { + return nil, fmt.Errorf("error setting up for-each-ref command: %v", err) + } + + var prefixes []string + for _, prefix := range req.ExceptWithPrefix { + prefixes = append(prefixes, string(prefix)) + } + + scanner := bufio.NewScanner(cmd) + for scanner.Scan() { + refName := scanner.Text() + + if hasAnyPrefix(refName, prefixes) { + continue + } + + refs = append(refs, string(refName)) + } + + if err != nil { + return nil, fmt.Errorf("error listing refs: %v", cmd.Wait()) + } + + return refs, nil +} + +func hasAnyPrefix(s string, prefixes []string) bool { + for _, prefix := range prefixes { + if strings.HasPrefix(s, prefix) { + return true + } + } + + return false } func validateDeleteRefRequest(req *gitalypb.DeleteRefsRequest) error { diff --git a/internal/service/ref/delete_refs_test.go b/internal/service/ref/delete_refs_test.go index a87318cf0..294073d67 100644 --- a/internal/service/ref/delete_refs_test.go +++ b/internal/service/ref/delete_refs_test.go @@ -3,6 +3,7 @@ package ref import ( "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/gitlab-org/gitaly-proto/go/gitalypb" "gitlab.com/gitlab-org/gitaly/internal/testhelper" @@ -83,7 +84,7 @@ func TestFailedDeleteRefsRequestDueToGitError(t *testing.T) { response, err := client.DeleteRefs(ctx, request) require.NoError(t, err) - require.Contains(t, response.GitError, "Could not delete refs") + assert.Contains(t, response.GitError, "unable to delete refs") } func TestFailedDeleteRefsDueToValidation(t *testing.T) { diff --git a/ruby/lib/gitaly_server/ref_service.rb b/ruby/lib/gitaly_server/ref_service.rb index 9b3fa036c..b6fd4e5da 100644 --- a/ruby/lib/gitaly_server/ref_service.rb +++ b/ruby/lib/gitaly_server/ref_service.rb @@ -76,6 +76,7 @@ module GitalyServer end end + # Post 11.10 this method can be removed def delete_refs(request, call) repo = Gitlab::Git::Repository.from_gitaly(request.repository, call) |