1// 2// Copyright 2021, Sander van Harmelen 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15// 16 17package gitlab 18 19import ( 20 "bytes" 21 "fmt" 22 "io" 23 "mime/multipart" 24 "net/http" 25 "os" 26 "path/filepath" 27 "strconv" 28) 29 30// GroupImportExportService handles communication with the group import export 31// related methods of the GitLab API. 32// 33// GitLab API docs: https://docs.gitlab.com/ce/api/group_import_export.html 34type GroupImportExportService struct { 35 client *Client 36} 37 38// ScheduleExport starts a new group export. 39// 40// GitLab API docs: 41// https://docs.gitlab.com/ce/api/group_import_export.html#schedule-new-export 42func (s *GroupImportExportService) ScheduleExport(gid interface{}, options ...RequestOptionFunc) (*Response, error) { 43 group, err := parseID(gid) 44 if err != nil { 45 return nil, err 46 } 47 u := fmt.Sprintf("groups/%s/export", pathEscape(group)) 48 49 req, err := s.client.NewRequest(http.MethodPost, u, nil, options) 50 if err != nil { 51 return nil, err 52 } 53 54 return s.client.Do(req, nil) 55} 56 57// ExportDownload downloads the finished export. 58// 59// GitLab API docs: 60// https://docs.gitlab.com/ce/api/group_import_export.html#export-download 61func (s *GroupImportExportService) ExportDownload(gid interface{}, options ...RequestOptionFunc) (*bytes.Reader, *Response, error) { 62 group, err := parseID(gid) 63 if err != nil { 64 return nil, nil, err 65 } 66 u := fmt.Sprintf("groups/%s/export/download", pathEscape(group)) 67 68 req, err := s.client.NewRequest(http.MethodGet, u, nil, options) 69 if err != nil { 70 return nil, nil, err 71 } 72 73 exportDownload := new(bytes.Buffer) 74 resp, err := s.client.Do(req, exportDownload) 75 if err != nil { 76 return nil, resp, err 77 } 78 79 return bytes.NewReader(exportDownload.Bytes()), resp, err 80} 81 82// GroupImportFileOptions represents the available ImportFile() options. 83// 84// GitLab API docs: 85// https://docs.gitlab.com/ce/api/group_import_export.html#import-a-file 86type GroupImportFileOptions struct { 87 Name *string `url:"name,omitempty" json:"name,omitempty"` 88 Path *string `url:"path,omitempty" json:"path,omitempty"` 89 File *string `url:"file,omitempty" json:"file,omitempty"` 90 ParentID *int `url:"parent_id,omitempty" json:"parent_id,omitempty"` 91} 92 93// ImportFile imports a file. 94// 95// GitLab API docs: 96// https://docs.gitlab.com/ce/api/group_import_export.html#import-a-file 97func (s *GroupImportExportService) ImportFile(opt *GroupImportFileOptions, options ...RequestOptionFunc) (*Response, error) { 98 // First check if we got all required options. 99 if opt.Name == nil || *opt.Name == "" { 100 return nil, fmt.Errorf("Missing required option: Name") 101 } 102 if opt.Path == nil || *opt.Path == "" { 103 return nil, fmt.Errorf("Missing required option: Path") 104 } 105 if opt.File == nil || *opt.File == "" { 106 return nil, fmt.Errorf("Missing required option: File") 107 } 108 109 f, err := os.Open(*opt.File) 110 if err != nil { 111 return nil, err 112 } 113 defer f.Close() 114 115 b := &bytes.Buffer{} 116 w := multipart.NewWriter(b) 117 118 _, filename := filepath.Split(*opt.File) 119 fw, err := w.CreateFormFile("file", filename) 120 if err != nil { 121 return nil, err 122 } 123 124 _, err = io.Copy(fw, f) 125 if err != nil { 126 return nil, err 127 } 128 129 // Populate the additional fields. 130 fw, err = w.CreateFormField("name") 131 if err != nil { 132 return nil, err 133 } 134 135 _, err = fw.Write([]byte(*opt.Name)) 136 if err != nil { 137 return nil, err 138 } 139 140 fw, err = w.CreateFormField("path") 141 if err != nil { 142 return nil, err 143 } 144 145 _, err = fw.Write([]byte(*opt.Path)) 146 if err != nil { 147 return nil, err 148 } 149 150 if opt.ParentID != nil { 151 fw, err = w.CreateFormField("parent_id") 152 if err != nil { 153 return nil, err 154 } 155 156 _, err = fw.Write([]byte(strconv.Itoa(*opt.ParentID))) 157 if err != nil { 158 return nil, err 159 } 160 } 161 162 if err = w.Close(); err != nil { 163 return nil, err 164 } 165 166 req, err := s.client.NewRequest(http.MethodPost, "groups/import", nil, options) 167 if err != nil { 168 return nil, err 169 } 170 171 // Set the buffer as the request body. 172 if err = req.SetBody(b); err != nil { 173 return nil, err 174 } 175 176 // Overwrite the default content type. 177 req.Header.Set("Content-Type", w.FormDataContentType()) 178 179 return s.client.Do(req, nil) 180} 181