Loading repository_files.go +22 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package gitlab import ( "bytes" "io" "net/http" "strconv" "time" Loading @@ -29,6 +30,7 @@ type ( GetFileMetaData(pid any, fileName string, opt *GetFileMetaDataOptions, options ...RequestOptionFunc) (*File, *Response, error) GetFileBlame(pid any, file string, opt *GetFileBlameOptions, options ...RequestOptionFunc) ([]*FileBlameRange, *Response, error) GetRawFile(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) ([]byte, *Response, error) GetRawFileReader(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) (io.ReadCloser, *Response, error) GetRawFileMetaData(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) (*File, *Response, error) CreateFile(pid any, fileName string, opt *CreateFileOptions, options ...RequestOptionFunc) (*FileInfo, *Response, error) UpdateFile(pid any, fileName string, opt *UpdateFileOptions, options ...RequestOptionFunc) (*FileInfo, *Response, error) Loading Loading @@ -227,6 +229,26 @@ func (s *RepositoryFilesService) GetRawFile(pid any, fileName string, opt *GetRa return buf.Bytes(), resp, nil } // GetRawFileReader gets the contents of a raw file from a repository as a // stream, which avoids buffering the whole file in memory. // // The returned io.ReadCloser must be closed by the caller to avoid // leaking the underlying response body. // // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-raw-file-from-repository func (s *RepositoryFilesService) GetRawFileReader(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) (io.ReadCloser, *Response, error) { r, resp, err := do[bodyReader](s.client, withPath("projects/%s/repository/files/%s/raw", ProjectID{pid}, fileName), withAPIOpts(opt), withRequestOpts(options...), ) if err != nil { return nil, resp, err } return &r, resp, nil } // GetRawFileMetaData gets the metadata of a raw file from a repository. // // GitLab API docs: Loading repository_files_test.go +272 −26 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package gitlab import ( "fmt" "io" "net/http" "testing" Loading Loading @@ -49,18 +50,37 @@ func TestRepositoryFilesService_GetFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, f) } func TestRepositoryFilesService_GetFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetFile(13083.01, "app/models/key.rb?ref=master", nil) f, resp, err := client.RepositoryFiles.GetFile(13083.01, "app/models/key.rb?ref=master", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, f) } func TestRepositoryFilesService_GetFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetFile(13083, "app/models/key.rb?ref=master", nil, errorOption) f, resp, err := client.RepositoryFiles.GetFile(13083, "app/models/key.rb?ref=master", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, f) } f, resp, err = client.RepositoryFiles.GetFile(13084, "app/models/key.rb?ref=master", nil) func TestRepositoryFilesService_GetFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) f, resp, err := client.RepositoryFiles.GetFile(13084, "app/models/key.rb?ref=master", nil) assert.Error(t, err) assert.Nil(t, f) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -101,18 +121,37 @@ func TestRepositoryFilesService_GetFileMetaData(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, f) } f, resp, err = client.RepositoryFiles.GetFileMetaData(13083.01, "app/models/key.rb?ref=master", nil) func TestRepositoryFilesService_GetFileMetaData_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err := client.RepositoryFiles.GetFileMetaData(13083.01, "app/models/key.rb?ref=master", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, f) } f, resp, err = client.RepositoryFiles.GetFileMetaData(13083, "app/models/key.rb?ref=master", nil, errorOption) func TestRepositoryFilesService_GetFileMetaData_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err := client.RepositoryFiles.GetFileMetaData(13083, "app/models/key.rb?ref=master", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, f) } func TestRepositoryFilesService_GetFileMetaData_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) f, resp, err = client.RepositoryFiles.GetFileMetaData(13084, "app/models/key.rb?ref=master", nil) f, resp, err := client.RepositoryFiles.GetFileMetaData(13084, "app/models/key.rb?ref=master", nil) assert.Error(t, err) assert.Nil(t, f) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -166,18 +205,37 @@ func TestRepositoryFilesService_GetFileBlame(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fbr) } func TestRepositoryFilesService_GetFileBlame_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) fbr, resp, err = client.RepositoryFiles.GetFileBlame(13083.01, "path/to/file.rb", nil) fbr, resp, err := client.RepositoryFiles.GetFileBlame(13083.01, "path/to/file.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, fbr) } func TestRepositoryFilesService_GetFileBlame_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) fbr, resp, err = client.RepositoryFiles.GetFileBlame(13083, "path/to/file.rb", nil, errorOption) fbr, resp, err := client.RepositoryFiles.GetFileBlame(13083, "path/to/file.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, fbr) } fbr, resp, err = client.RepositoryFiles.GetFileBlame(13084, "path/to/file.rb", nil) func TestRepositoryFilesService_GetFileBlame_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/path%2Fto%2Ffile.rb/blame", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) fbr, resp, err := client.RepositoryFiles.GetFileBlame(13084, "path/to/file.rb", nil) assert.Error(t, err) assert.Nil(t, fbr) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -221,23 +279,95 @@ func TestRepositoryFilesService_GetRawFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, b) } b, resp, err = client.RepositoryFiles.GetRawFile(13083.01, "app/models/key.rb", nil) func TestRepositoryFilesService_GetRawFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) b, resp, err := client.RepositoryFiles.GetRawFile(13083.01, "app/models/key.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, b) } func TestRepositoryFilesService_GetRawFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) b, resp, err = client.RepositoryFiles.GetRawFile(13083, "app/models/key.rb", nil, errorOption) b, resp, err := client.RepositoryFiles.GetRawFile(13083, "app/models/key.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, b) } func TestRepositoryFilesService_GetRawFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) b, resp, err = client.RepositoryFiles.GetRawFile(13084, "app/models/key.rb", nil) b, resp, err := client.RepositoryFiles.GetRawFile(13084, "app/models/key.rb", nil) assert.Error(t, err) assert.Nil(t, b) assert.Equal(t, http.StatusNotFound, resp.StatusCode) } func TestRepositoryFilesService_GetRawFileReader(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) fmt.Fprint(w, "raw file contents") }) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13083, "app/models/key.rb", nil) assert.NoError(t, err) assert.NotNil(t, resp) defer reader.Close() got, err := io.ReadAll(reader) assert.NoError(t, err) assert.Equal(t, []byte("raw file contents"), got) } func TestRepositoryFilesService_GetRawFileReader_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13083.01, "app/models/key.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, reader) } func TestRepositoryFilesService_GetRawFileReader_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13083, "app/models/key.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, reader) } func TestRepositoryFilesService_GetRawFileReader_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13084, "app/models/key.rb", nil) assert.Error(t, err) assert.Nil(t, reader) assert.Equal(t, http.StatusNotFound, resp.StatusCode) } func TestRepositoryFilesService_GetRawFileMetaData(t *testing.T) { t.Parallel() mux, client := setup(t) Loading Loading @@ -273,18 +403,37 @@ func TestRepositoryFilesService_GetRawFileMetaData(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, f) } func TestRepositoryFilesService_GetRawFileMetaData_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetRawFileMetaData(13083.01, "app/models/key.rb", nil) f, resp, err := client.RepositoryFiles.GetRawFileMetaData(13083.01, "app/models/key.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, f) } func TestRepositoryFilesService_GetRawFileMetaData_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetRawFileMetaData(13083, "app/models/key.rb", nil, errorOption) f, resp, err := client.RepositoryFiles.GetRawFileMetaData(13083, "app/models/key.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, f) } f, resp, err = client.RepositoryFiles.GetRawFileMetaData(13084, "app/models/key.rb", nil) func TestRepositoryFilesService_GetRawFileMetaData_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) f, resp, err := client.RepositoryFiles.GetRawFileMetaData(13084, "app/models/key.rb", nil) assert.Error(t, err) assert.Nil(t, f) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -313,23 +462,62 @@ func TestRepositoryFilesService_CreateFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } func TestRepositoryFilesService_CreateFile_WithExecuteFilemode(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13083/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodPost) fmt.Fprintf(w, ` { "file_path": "app/project.rb", "branch": "master" } `) }) fi, resp, err = client.RepositoryFiles.CreateFile(13083, "app/project.rb", &CreateFileOptions{ExecuteFilemode: Ptr(true)}) want := &FileInfo{ FilePath: "app/project.rb", Branch: "master", } fi, resp, err := client.RepositoryFiles.CreateFile(13083, "app/project.rb", &CreateFileOptions{ExecuteFilemode: Ptr(true)}) assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } func TestRepositoryFilesService_CreateFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.CreateFile(13083.01, "app/project.rb", nil) fi, resp, err := client.RepositoryFiles.CreateFile(13083.01, "app/project.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, fi) } func TestRepositoryFilesService_CreateFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.CreateFile(13083, "app/project.rb", nil, errorOption) fi, resp, err := client.RepositoryFiles.CreateFile(13083, "app/project.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, fi) } func TestRepositoryFilesService_CreateFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) fi, resp, err = client.RepositoryFiles.CreateFile(13084, "app/project.rb", nil) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) fi, resp, err := client.RepositoryFiles.CreateFile(13084, "app/project.rb", nil) assert.Error(t, err) assert.Nil(t, fi) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -358,23 +546,62 @@ func TestRepositoryFilesService_UpdateFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } fi, resp, err = client.RepositoryFiles.UpdateFile(13083, "app/project.rb", &UpdateFileOptions{ExecuteFilemode: Ptr(true)}) func TestRepositoryFilesService_UpdateFile_WithExecuteFilemode(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13083/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodPut) fmt.Fprintf(w, ` { "file_path": "app/project.rb", "branch": "master" } `) }) want := &FileInfo{ FilePath: "app/project.rb", Branch: "master", } fi, resp, err := client.RepositoryFiles.UpdateFile(13083, "app/project.rb", &UpdateFileOptions{ExecuteFilemode: Ptr(true)}) assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } func TestRepositoryFilesService_UpdateFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.UpdateFile(13083.01, "app/project.rb", nil) fi, resp, err := client.RepositoryFiles.UpdateFile(13083.01, "app/project.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, fi) } func TestRepositoryFilesService_UpdateFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.UpdateFile(13083, "app/project.rb", nil, errorOption) fi, resp, err := client.RepositoryFiles.UpdateFile(13083, "app/project.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, fi) } fi, resp, err = client.RepositoryFiles.UpdateFile(13084, "app/project.rb", nil) func TestRepositoryFilesService_UpdateFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) fi, resp, err := client.RepositoryFiles.UpdateFile(13084, "app/project.rb", nil) assert.Error(t, err) assert.Nil(t, fi) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading @@ -391,16 +618,35 @@ func TestRepositoryFilesService_DeleteFile(t *testing.T) { resp, err := client.RepositoryFiles.DeleteFile(13083, "app/project.rb", nil) assert.NoError(t, err) assert.NotNil(t, resp) } resp, err = client.RepositoryFiles.DeleteFile(13083.01, "app/project.rb", nil) func TestRepositoryFilesService_DeleteFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) resp, err := client.RepositoryFiles.DeleteFile(13083.01, "app/project.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) } resp, err = client.RepositoryFiles.DeleteFile(13083, "app/project.rb", nil, errorOption) func TestRepositoryFilesService_DeleteFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) resp, err := client.RepositoryFiles.DeleteFile(13083, "app/project.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) } func TestRepositoryFilesService_DeleteFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) resp, err = client.RepositoryFiles.DeleteFile(13084, "app/project.rb", nil) resp, err := client.RepositoryFiles.DeleteFile(13084, "app/project.rb", nil) assert.Error(t, err) assert.Equal(t, http.StatusNotFound, resp.StatusCode) } testing/repository_files_mock.go +46 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ package testing import ( io "io" reflect "reflect" gitlab "gitlab.com/gitlab-org/api/client-go/v2" Loading Loading @@ -353,6 +354,51 @@ func (c *MockRepositoryFilesServiceInterfaceGetRawFileMetaDataCall) DoAndReturn( return c } // GetRawFileReader mocks base method. func (m *MockRepositoryFilesServiceInterface) GetRawFileReader(pid any, fileName string, opt *gitlab.GetRawFileOptions, options ...gitlab.RequestOptionFunc) (io.ReadCloser, *gitlab.Response, error) { m.ctrl.T.Helper() varargs := []any{pid, fileName, opt} for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "GetRawFileReader", varargs...) ret0, _ := ret[0].(io.ReadCloser) ret1, _ := ret[1].(*gitlab.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetRawFileReader indicates an expected call of GetRawFileReader. func (mr *MockRepositoryFilesServiceInterfaceMockRecorder) GetRawFileReader(pid, fileName, opt any, options ...any) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { mr.mock.ctrl.T.Helper() varargs := append([]any{pid, fileName, opt}, options...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRawFileReader", reflect.TypeOf((*MockRepositoryFilesServiceInterface)(nil).GetRawFileReader), varargs...) return &MockRepositoryFilesServiceInterfaceGetRawFileReaderCall{Call: call} } // MockRepositoryFilesServiceInterfaceGetRawFileReaderCall wrap *gomock.Call type MockRepositoryFilesServiceInterfaceGetRawFileReaderCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return func (c *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall) Return(arg0 io.ReadCloser, arg1 *gitlab.Response, arg2 error) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { c.Call = c.Call.Return(arg0, arg1, arg2) return c } // Do rewrite *gomock.Call.Do func (c *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall) Do(f func(any, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) (io.ReadCloser, *gitlab.Response, error)) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn func (c *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall) DoAndReturn(f func(any, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) (io.ReadCloser, *gitlab.Response, error)) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { c.Call = c.Call.DoAndReturn(f) return c } // UpdateFile mocks base method. func (m *MockRepositoryFilesServiceInterface) UpdateFile(pid any, fileName string, opt *gitlab.UpdateFileOptions, options ...gitlab.RequestOptionFunc) (*gitlab.FileInfo, *gitlab.Response, error) { m.ctrl.T.Helper() Loading Loading
repository_files.go +22 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package gitlab import ( "bytes" "io" "net/http" "strconv" "time" Loading @@ -29,6 +30,7 @@ type ( GetFileMetaData(pid any, fileName string, opt *GetFileMetaDataOptions, options ...RequestOptionFunc) (*File, *Response, error) GetFileBlame(pid any, file string, opt *GetFileBlameOptions, options ...RequestOptionFunc) ([]*FileBlameRange, *Response, error) GetRawFile(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) ([]byte, *Response, error) GetRawFileReader(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) (io.ReadCloser, *Response, error) GetRawFileMetaData(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) (*File, *Response, error) CreateFile(pid any, fileName string, opt *CreateFileOptions, options ...RequestOptionFunc) (*FileInfo, *Response, error) UpdateFile(pid any, fileName string, opt *UpdateFileOptions, options ...RequestOptionFunc) (*FileInfo, *Response, error) Loading Loading @@ -227,6 +229,26 @@ func (s *RepositoryFilesService) GetRawFile(pid any, fileName string, opt *GetRa return buf.Bytes(), resp, nil } // GetRawFileReader gets the contents of a raw file from a repository as a // stream, which avoids buffering the whole file in memory. // // The returned io.ReadCloser must be closed by the caller to avoid // leaking the underlying response body. // // GitLab API docs: // https://docs.gitlab.com/api/repository_files/#get-raw-file-from-repository func (s *RepositoryFilesService) GetRawFileReader(pid any, fileName string, opt *GetRawFileOptions, options ...RequestOptionFunc) (io.ReadCloser, *Response, error) { r, resp, err := do[bodyReader](s.client, withPath("projects/%s/repository/files/%s/raw", ProjectID{pid}, fileName), withAPIOpts(opt), withRequestOpts(options...), ) if err != nil { return nil, resp, err } return &r, resp, nil } // GetRawFileMetaData gets the metadata of a raw file from a repository. // // GitLab API docs: Loading
repository_files_test.go +272 −26 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ package gitlab import ( "fmt" "io" "net/http" "testing" Loading Loading @@ -49,18 +50,37 @@ func TestRepositoryFilesService_GetFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, f) } func TestRepositoryFilesService_GetFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetFile(13083.01, "app/models/key.rb?ref=master", nil) f, resp, err := client.RepositoryFiles.GetFile(13083.01, "app/models/key.rb?ref=master", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, f) } func TestRepositoryFilesService_GetFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetFile(13083, "app/models/key.rb?ref=master", nil, errorOption) f, resp, err := client.RepositoryFiles.GetFile(13083, "app/models/key.rb?ref=master", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, f) } f, resp, err = client.RepositoryFiles.GetFile(13084, "app/models/key.rb?ref=master", nil) func TestRepositoryFilesService_GetFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) f, resp, err := client.RepositoryFiles.GetFile(13084, "app/models/key.rb?ref=master", nil) assert.Error(t, err) assert.Nil(t, f) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -101,18 +121,37 @@ func TestRepositoryFilesService_GetFileMetaData(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, f) } f, resp, err = client.RepositoryFiles.GetFileMetaData(13083.01, "app/models/key.rb?ref=master", nil) func TestRepositoryFilesService_GetFileMetaData_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err := client.RepositoryFiles.GetFileMetaData(13083.01, "app/models/key.rb?ref=master", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, f) } f, resp, err = client.RepositoryFiles.GetFileMetaData(13083, "app/models/key.rb?ref=master", nil, errorOption) func TestRepositoryFilesService_GetFileMetaData_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err := client.RepositoryFiles.GetFileMetaData(13083, "app/models/key.rb?ref=master", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, f) } func TestRepositoryFilesService_GetFileMetaData_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) f, resp, err = client.RepositoryFiles.GetFileMetaData(13084, "app/models/key.rb?ref=master", nil) f, resp, err := client.RepositoryFiles.GetFileMetaData(13084, "app/models/key.rb?ref=master", nil) assert.Error(t, err) assert.Nil(t, f) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -166,18 +205,37 @@ func TestRepositoryFilesService_GetFileBlame(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fbr) } func TestRepositoryFilesService_GetFileBlame_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) fbr, resp, err = client.RepositoryFiles.GetFileBlame(13083.01, "path/to/file.rb", nil) fbr, resp, err := client.RepositoryFiles.GetFileBlame(13083.01, "path/to/file.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, fbr) } func TestRepositoryFilesService_GetFileBlame_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) fbr, resp, err = client.RepositoryFiles.GetFileBlame(13083, "path/to/file.rb", nil, errorOption) fbr, resp, err := client.RepositoryFiles.GetFileBlame(13083, "path/to/file.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, fbr) } fbr, resp, err = client.RepositoryFiles.GetFileBlame(13084, "path/to/file.rb", nil) func TestRepositoryFilesService_GetFileBlame_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/path%2Fto%2Ffile.rb/blame", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) fbr, resp, err := client.RepositoryFiles.GetFileBlame(13084, "path/to/file.rb", nil) assert.Error(t, err) assert.Nil(t, fbr) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -221,23 +279,95 @@ func TestRepositoryFilesService_GetRawFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, b) } b, resp, err = client.RepositoryFiles.GetRawFile(13083.01, "app/models/key.rb", nil) func TestRepositoryFilesService_GetRawFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) b, resp, err := client.RepositoryFiles.GetRawFile(13083.01, "app/models/key.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, b) } func TestRepositoryFilesService_GetRawFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) b, resp, err = client.RepositoryFiles.GetRawFile(13083, "app/models/key.rb", nil, errorOption) b, resp, err := client.RepositoryFiles.GetRawFile(13083, "app/models/key.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, b) } func TestRepositoryFilesService_GetRawFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) b, resp, err = client.RepositoryFiles.GetRawFile(13084, "app/models/key.rb", nil) b, resp, err := client.RepositoryFiles.GetRawFile(13084, "app/models/key.rb", nil) assert.Error(t, err) assert.Nil(t, b) assert.Equal(t, http.StatusNotFound, resp.StatusCode) } func TestRepositoryFilesService_GetRawFileReader(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodGet) fmt.Fprint(w, "raw file contents") }) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13083, "app/models/key.rb", nil) assert.NoError(t, err) assert.NotNil(t, resp) defer reader.Close() got, err := io.ReadAll(reader) assert.NoError(t, err) assert.Equal(t, []byte("raw file contents"), got) } func TestRepositoryFilesService_GetRawFileReader_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13083.01, "app/models/key.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, reader) } func TestRepositoryFilesService_GetRawFileReader_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13083, "app/models/key.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, reader) } func TestRepositoryFilesService_GetRawFileReader_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) reader, resp, err := client.RepositoryFiles.GetRawFileReader(13084, "app/models/key.rb", nil) assert.Error(t, err) assert.Nil(t, reader) assert.Equal(t, http.StatusNotFound, resp.StatusCode) } func TestRepositoryFilesService_GetRawFileMetaData(t *testing.T) { t.Parallel() mux, client := setup(t) Loading Loading @@ -273,18 +403,37 @@ func TestRepositoryFilesService_GetRawFileMetaData(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, f) } func TestRepositoryFilesService_GetRawFileMetaData_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetRawFileMetaData(13083.01, "app/models/key.rb", nil) f, resp, err := client.RepositoryFiles.GetRawFileMetaData(13083.01, "app/models/key.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, f) } func TestRepositoryFilesService_GetRawFileMetaData_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) f, resp, err = client.RepositoryFiles.GetRawFileMetaData(13083, "app/models/key.rb", nil, errorOption) f, resp, err := client.RepositoryFiles.GetRawFileMetaData(13083, "app/models/key.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, f) } f, resp, err = client.RepositoryFiles.GetRawFileMetaData(13084, "app/models/key.rb", nil) func TestRepositoryFilesService_GetRawFileMetaData_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fmodels%2Fkey%2Erb/raw", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) f, resp, err := client.RepositoryFiles.GetRawFileMetaData(13084, "app/models/key.rb", nil) assert.Error(t, err) assert.Nil(t, f) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -313,23 +462,62 @@ func TestRepositoryFilesService_CreateFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } func TestRepositoryFilesService_CreateFile_WithExecuteFilemode(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13083/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodPost) fmt.Fprintf(w, ` { "file_path": "app/project.rb", "branch": "master" } `) }) fi, resp, err = client.RepositoryFiles.CreateFile(13083, "app/project.rb", &CreateFileOptions{ExecuteFilemode: Ptr(true)}) want := &FileInfo{ FilePath: "app/project.rb", Branch: "master", } fi, resp, err := client.RepositoryFiles.CreateFile(13083, "app/project.rb", &CreateFileOptions{ExecuteFilemode: Ptr(true)}) assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } func TestRepositoryFilesService_CreateFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.CreateFile(13083.01, "app/project.rb", nil) fi, resp, err := client.RepositoryFiles.CreateFile(13083.01, "app/project.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, fi) } func TestRepositoryFilesService_CreateFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.CreateFile(13083, "app/project.rb", nil, errorOption) fi, resp, err := client.RepositoryFiles.CreateFile(13083, "app/project.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, fi) } func TestRepositoryFilesService_CreateFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) fi, resp, err = client.RepositoryFiles.CreateFile(13084, "app/project.rb", nil) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) fi, resp, err := client.RepositoryFiles.CreateFile(13084, "app/project.rb", nil) assert.Error(t, err) assert.Nil(t, fi) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading Loading @@ -358,23 +546,62 @@ func TestRepositoryFilesService_UpdateFile(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } fi, resp, err = client.RepositoryFiles.UpdateFile(13083, "app/project.rb", &UpdateFileOptions{ExecuteFilemode: Ptr(true)}) func TestRepositoryFilesService_UpdateFile_WithExecuteFilemode(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13083/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, http.MethodPut) fmt.Fprintf(w, ` { "file_path": "app/project.rb", "branch": "master" } `) }) want := &FileInfo{ FilePath: "app/project.rb", Branch: "master", } fi, resp, err := client.RepositoryFiles.UpdateFile(13083, "app/project.rb", &UpdateFileOptions{ExecuteFilemode: Ptr(true)}) assert.NoError(t, err) assert.NotNil(t, resp) assert.Equal(t, want, fi) } func TestRepositoryFilesService_UpdateFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.UpdateFile(13083.01, "app/project.rb", nil) fi, resp, err := client.RepositoryFiles.UpdateFile(13083.01, "app/project.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) assert.Nil(t, fi) } func TestRepositoryFilesService_UpdateFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) fi, resp, err = client.RepositoryFiles.UpdateFile(13083, "app/project.rb", nil, errorOption) fi, resp, err := client.RepositoryFiles.UpdateFile(13083, "app/project.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) assert.Nil(t, fi) } fi, resp, err = client.RepositoryFiles.UpdateFile(13084, "app/project.rb", nil) func TestRepositoryFilesService_UpdateFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) fi, resp, err := client.RepositoryFiles.UpdateFile(13084, "app/project.rb", nil) assert.Error(t, err) assert.Nil(t, fi) assert.Equal(t, http.StatusNotFound, resp.StatusCode) Loading @@ -391,16 +618,35 @@ func TestRepositoryFilesService_DeleteFile(t *testing.T) { resp, err := client.RepositoryFiles.DeleteFile(13083, "app/project.rb", nil) assert.NoError(t, err) assert.NotNil(t, resp) } resp, err = client.RepositoryFiles.DeleteFile(13083.01, "app/project.rb", nil) func TestRepositoryFilesService_DeleteFile_InvalidProjectIDType(t *testing.T) { t.Parallel() _, client := setup(t) resp, err := client.RepositoryFiles.DeleteFile(13083.01, "app/project.rb", nil) assert.ErrorIs(t, err, ErrInvalidIDType) assert.Nil(t, resp) } resp, err = client.RepositoryFiles.DeleteFile(13083, "app/project.rb", nil, errorOption) func TestRepositoryFilesService_DeleteFile_RequestOptionError(t *testing.T) { t.Parallel() _, client := setup(t) resp, err := client.RepositoryFiles.DeleteFile(13083, "app/project.rb", nil, errorOption) assert.ErrorIs(t, err, errRequestOptionFunc) assert.Nil(t, resp) } func TestRepositoryFilesService_DeleteFile_NonExistentProject(t *testing.T) { t.Parallel() mux, client := setup(t) mux.HandleFunc("/api/v4/projects/13084/repository/files/app%2Fproject%2Erb", func(w http.ResponseWriter, r *http.Request) { http.Error(w, "Not Found", http.StatusNotFound) }) resp, err = client.RepositoryFiles.DeleteFile(13084, "app/project.rb", nil) resp, err := client.RepositoryFiles.DeleteFile(13084, "app/project.rb", nil) assert.Error(t, err) assert.Equal(t, http.StatusNotFound, resp.StatusCode) }
testing/repository_files_mock.go +46 −0 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ package testing import ( io "io" reflect "reflect" gitlab "gitlab.com/gitlab-org/api/client-go/v2" Loading Loading @@ -353,6 +354,51 @@ func (c *MockRepositoryFilesServiceInterfaceGetRawFileMetaDataCall) DoAndReturn( return c } // GetRawFileReader mocks base method. func (m *MockRepositoryFilesServiceInterface) GetRawFileReader(pid any, fileName string, opt *gitlab.GetRawFileOptions, options ...gitlab.RequestOptionFunc) (io.ReadCloser, *gitlab.Response, error) { m.ctrl.T.Helper() varargs := []any{pid, fileName, opt} for _, a := range options { varargs = append(varargs, a) } ret := m.ctrl.Call(m, "GetRawFileReader", varargs...) ret0, _ := ret[0].(io.ReadCloser) ret1, _ := ret[1].(*gitlab.Response) ret2, _ := ret[2].(error) return ret0, ret1, ret2 } // GetRawFileReader indicates an expected call of GetRawFileReader. func (mr *MockRepositoryFilesServiceInterfaceMockRecorder) GetRawFileReader(pid, fileName, opt any, options ...any) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { mr.mock.ctrl.T.Helper() varargs := append([]any{pid, fileName, opt}, options...) call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRawFileReader", reflect.TypeOf((*MockRepositoryFilesServiceInterface)(nil).GetRawFileReader), varargs...) return &MockRepositoryFilesServiceInterfaceGetRawFileReaderCall{Call: call} } // MockRepositoryFilesServiceInterfaceGetRawFileReaderCall wrap *gomock.Call type MockRepositoryFilesServiceInterfaceGetRawFileReaderCall struct { *gomock.Call } // Return rewrite *gomock.Call.Return func (c *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall) Return(arg0 io.ReadCloser, arg1 *gitlab.Response, arg2 error) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { c.Call = c.Call.Return(arg0, arg1, arg2) return c } // Do rewrite *gomock.Call.Do func (c *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall) Do(f func(any, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) (io.ReadCloser, *gitlab.Response, error)) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn func (c *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall) DoAndReturn(f func(any, string, *gitlab.GetRawFileOptions, ...gitlab.RequestOptionFunc) (io.ReadCloser, *gitlab.Response, error)) *MockRepositoryFilesServiceInterfaceGetRawFileReaderCall { c.Call = c.Call.DoAndReturn(f) return c } // UpdateFile mocks base method. func (m *MockRepositoryFilesServiceInterface) UpdateFile(pid any, fileName string, opt *gitlab.UpdateFileOptions, options ...gitlab.RequestOptionFunc) (*gitlab.FileInfo, *gitlab.Response, error) { m.ctrl.T.Helper() Loading