From d12864e7acf277f3a2bd8b6b98a4069a4db8bb23 Mon Sep 17 00:00:00 2001 From: Mitar Date: Wed, 15 Dec 2021 11:23:10 +0100 Subject: [PATCH] Added UploadAvatar. Fixes #229. --- projects.go | 47 +++++++++++++++++++++++++++++++++++++++++ projects_test.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/projects.go b/projects.go index cfc31d9b6..58a43ec9b 100644 --- a/projects.go +++ b/projects.go @@ -1808,3 +1808,50 @@ func (s *ProjectsService) TransferProject(pid interface{}, opt *TransferProjectO return p, resp, err } + +// UploadAvatar uploads an avatar for the project +// +// GitLab API docs: https://docs.gitlab.com/ee/api/projects.html#upload-a-project-avatar +func (s *ProjectsService) UploadAvatar(pid interface{}, avatar io.Reader, filename string, options ...RequestOptionFunc) (*Project, *Response, error) { + project, err := parseID(pid) + if err != nil { + return nil, nil, err + } + u := fmt.Sprintf("projects/%s", PathEscape(project)) + + b := &bytes.Buffer{} + w := multipart.NewWriter(b) + + _, filename = filepath.Split(filename) + fw, err := w.CreateFormFile("avatar", filename) + if err != nil { + return nil, nil, err + } + + _, err = io.Copy(fw, avatar) + if err != nil { + return nil, nil, err + } + w.Close() + + req, err := s.client.NewRequest(http.MethodPut, u, nil, options) + if err != nil { + return nil, nil, err + } + + // Set the buffer as the request body. + if err = req.SetBody(b); err != nil { + return nil, nil, err + } + + // Overwrite the default content type. + req.Header.Set("Content-Type", w.FormDataContentType()) + + p := new(Project) + resp, err := s.client.Do(req, p) + if err != nil { + return nil, resp, err + } + + return p, resp, err +} diff --git a/projects_test.go b/projects_test.go index c4a091d2b..56bd363b7 100644 --- a/projects_test.go +++ b/projects_test.go @@ -17,6 +17,7 @@ package gitlab import ( + "bytes" "fmt" "io/ioutil" "net/http" @@ -463,6 +464,59 @@ func TestUploadFile_Retry(t *testing.T) { } } +func TestUploadAvatar(t *testing.T) { + mux, server, client := setup(t) + defer teardown(server) + + mux.HandleFunc("/api/v4/projects/1", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPut) + if false == strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data;") { + t.Fatalf("Projects.UploadAvatar request content-type %+v want multipart/form-data;", r.Header.Get("Content-Type")) + } + if r.ContentLength == -1 { + t.Fatalf("Projects.UploadAvatar request content-length is -1") + } + fmt.Fprint(w, `{}`) + }) + + b := bytes.Buffer{} + + _, _, err := client.Projects.UploadAvatar(1, &b, "image.png") + + if err != nil { + t.Fatalf("Projects.UploadAvatar returns an error: %v", err) + } +} + +func TestUploadAvatar_Retry(t *testing.T) { + mux, server, client := setup(t) + defer teardown(server) + + isFirstRequest := true + mux.HandleFunc("/api/v4/projects/1", func(w http.ResponseWriter, r *http.Request) { + if isFirstRequest { + http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) + isFirstRequest = false + return + } + if false == strings.Contains(r.Header.Get("Content-Type"), "multipart/form-data;") { + t.Fatalf("Projects.UploadAvatar request content-type %+v want multipart/form-data;", r.Header.Get("Content-Type")) + } + if r.ContentLength == -1 { + t.Fatalf("Projects.UploadAvatar request content-length is -1") + } + fmt.Fprint(w, `{}`) + }) + + b := bytes.Buffer{} + + _, _, err := client.Projects.UploadAvatar(1, &b, "image.png") + + if err != nil { + t.Fatalf("Projects.UploadAvatar returns an error: %v", err) + } +} + func TestListProjectForks(t *testing.T) { mux, server, client := setup(t) defer teardown(server)