From 8c27ef08646d1ed1a1f3493955d4f3c5e6912e88 Mon Sep 17 00:00:00 2001 From: Eric Ju Date: Thu, 11 Jan 2024 23:46:34 -0400 Subject: [PATCH] repository: GetFileAttributes supports get all attributes for a path During the processing of replacing GetInfoAttributes by GitFileAttributes in Rails.We come across a function, attributes(path) in lib/gitlab/git/repository.rb. It queries all the attributes for a given path. This MR add the ability to query all the attributes for a given path. --- internal/git/gitattributes/check_attr.go | 31 ++++++++++++------- .../repository/file_attributes_test.go | 27 ++++++++++++++++ 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/internal/git/gitattributes/check_attr.go b/internal/git/gitattributes/check_attr.go index 8596efaa31..f8e1bb232e 100644 --- a/internal/git/gitattributes/check_attr.go +++ b/internal/git/gitattributes/check_attr.go @@ -20,8 +20,6 @@ type CheckAttrCmd struct { stdout *bufio.Reader stdin *bufio.Writer - count int - m *sync.Mutex } @@ -31,14 +29,22 @@ func CheckAttr(ctx context.Context, repo git.RepositoryExecutor, revision git.Re return nil, nil, structerr.NewInvalidArgument("empty list of attribute names") } + flags := []git.Option{ + git.Flag{Name: "--stdin"}, + git.Flag{Name: "-z"}, + git.ValueFlag{Name: "--source", Value: revision.String()}, + } + + // Special attribute "*" retrieves all attributes + if len(names) == 1 && names[0] == "*" { + flags = append(flags, git.Flag{Name: "-a"}) + names = nil + } + cmd, err := repo.Exec(ctx, git.Command{ - Name: "check-attr", - Flags: []git.Option{ - git.Flag{Name: "--stdin"}, - git.Flag{Name: "-z"}, - git.ValueFlag{Name: "--source", Value: revision.String()}, - }, - Args: names, + Name: "check-attr", + Flags: flags, + Args: names, }, git.WithSetupStdin(), git.WithSetupStdout(), @@ -51,7 +57,6 @@ func CheckAttr(ctx context.Context, repo git.RepositoryExecutor, revision git.Re cmd: cmd, stdout: bufio.NewReader(cmd), stdin: bufio.NewWriter(cmd), - count: len(names), m: &sync.Mutex{}, } @@ -79,7 +84,7 @@ func (c CheckAttrCmd) Check(path string) (Attributes, error) { // Using git-check-attr(1) with -z will return data in the format: // NUL NUL NUL ... - for i := 0; i < c.count; { + for { word, err := c.stdout.ReadBytes('\000') if err != nil { return nil, fmt.Errorf("read line: %w", err) @@ -98,8 +103,10 @@ func (c CheckAttrCmd) Check(path string) (Attributes, error) { attrs = append(attrs, Attribute{Name: buf[1], State: buf[2]}) } - i++ buf = buf[:0] + if c.stdout.Buffered() == 0 { + break + } } return attrs, nil diff --git a/internal/gitaly/service/repository/file_attributes_test.go b/internal/gitaly/service/repository/file_attributes_test.go index 7472634373..4d55c36ea8 100644 --- a/internal/gitaly/service/repository/file_attributes_test.go +++ b/internal/gitaly/service/repository/file_attributes_test.go @@ -93,6 +93,33 @@ func TestGetFileAttributes(t *testing.T) { } }, }, + { + desc: "returns multiple attributes for a file successfully", + setup: func(t *testing.T) setupData { + return setupData{ + request: &gitalypb.GetFileAttributesRequest{ + Repository: repoProto, + Revision: []byte("main"), + Attributes: []string{"*"}, + Paths: []string{"example.go"}, + }, + expectedResponse: &gitalypb.GetFileAttributesResponse{ + AttributeInfos: []*gitalypb.GetFileAttributesResponse_AttributeInfo{ + { + Path: string("example.go"), + Attribute: string("diff"), + Value: string("go"), + }, + { + Path: string("example.go"), + Attribute: string("text"), + Value: string("set"), + }, + }, + }, + } + }, + }, { desc: "returns empty response when there are no matching attributes for the given path", setup: func(t *testing.T) setupData { -- GitLab