1// Copyright 2020 The Gitea Authors. All rights reserved. 2// Use of this source code is governed by a MIT-style 3// license that can be found in the LICENSE file. 4 5package gitea 6 7import ( 8 "bytes" 9 "encoding/json" 10 "fmt" 11) 12 13// GitServiceType represents a git service 14type GitServiceType string 15 16const ( 17 // GitServicePlain represents a plain git service 18 GitServicePlain GitServiceType = "git" 19 //GitServiceGithub represents github.com 20 GitServiceGithub GitServiceType = "github" 21 // GitServiceGitlab represents a gitlab service 22 GitServiceGitlab GitServiceType = "gitlab" 23 // GitServiceGitea represents a gitea service 24 GitServiceGitea GitServiceType = "gitea" 25 // GitServiceGogs represents a gogs service 26 GitServiceGogs GitServiceType = "gogs" 27) 28 29// MigrateRepoOption options for migrating a repository from an external service 30type MigrateRepoOption struct { 31 RepoName string `json:"repo_name"` 32 RepoOwner string `json:"repo_owner"` 33 // deprecated use RepoOwner 34 RepoOwnerID int64 `json:"uid"` 35 CloneAddr string `json:"clone_addr"` 36 Service GitServiceType `json:"service"` 37 AuthUsername string `json:"auth_username"` 38 AuthPassword string `json:"auth_password"` 39 AuthToken string `json:"auth_token"` 40 Mirror bool `json:"mirror"` 41 Private bool `json:"private"` 42 Description string `json:"description"` 43 Wiki bool `json:"wiki"` 44 Milestones bool `json:"milestones"` 45 Labels bool `json:"labels"` 46 Issues bool `json:"issues"` 47 PullRequests bool `json:"pull_requests"` 48 Releases bool `json:"releases"` 49 MirrorInterval string `json:"mirror_interval"` 50 LFS bool `json:"lfs"` 51 LFSEndpoint string `json:"lfs_endpoint"` 52} 53 54// Validate the MigrateRepoOption struct 55func (opt *MigrateRepoOption) Validate(c *Client) error { 56 // check user options 57 if len(opt.CloneAddr) == 0 { 58 return fmt.Errorf("CloneAddr required") 59 } 60 if len(opt.RepoName) == 0 { 61 return fmt.Errorf("RepoName required") 62 } else if len(opt.RepoName) > 100 { 63 return fmt.Errorf("RepoName to long") 64 } 65 if len(opt.Description) > 255 { 66 return fmt.Errorf("Description to long") 67 } 68 switch opt.Service { 69 case GitServiceGithub: 70 if len(opt.AuthToken) == 0 { 71 return fmt.Errorf("github requires token authentication") 72 } 73 case GitServiceGitlab, GitServiceGitea: 74 if len(opt.AuthToken) == 0 { 75 return fmt.Errorf("%s requires token authentication", opt.Service) 76 } 77 // Gitlab is supported since 1.12.0 but api cant handle it until 1.13.0 78 // https://github.com/go-gitea/gitea/pull/12672 79 if c.checkServerVersionGreaterThanOrEqual(version1_13_0) != nil { 80 return fmt.Errorf("migrate from service %s need gitea >= 1.13.0", opt.Service) 81 } 82 case GitServiceGogs: 83 if len(opt.AuthToken) == 0 { 84 return fmt.Errorf("gogs requires token authentication") 85 } 86 if c.checkServerVersionGreaterThanOrEqual(version1_14_0) != nil { 87 return fmt.Errorf("migrate from service gogs need gitea >= 1.14.0") 88 } 89 } 90 return nil 91} 92 93// MigrateRepo migrates a repository from other Git hosting sources for the authenticated user. 94// 95// To migrate a repository for a organization, the authenticated user must be a 96// owner of the specified organization. 97func (c *Client) MigrateRepo(opt MigrateRepoOption) (*Repository, *Response, error) { 98 if err := opt.Validate(c); err != nil { 99 return nil, nil, err 100 } 101 102 if err := c.checkServerVersionGreaterThanOrEqual(version1_13_0); err != nil { 103 if len(opt.AuthToken) != 0 { 104 // gitea <= 1.12 dont understand AuthToken 105 opt.AuthUsername = opt.AuthToken 106 opt.AuthPassword, opt.AuthToken = "", "" 107 } 108 if len(opt.RepoOwner) != 0 { 109 // gitea <= 1.12 dont understand RepoOwner 110 u, _, err := c.GetUserInfo(opt.RepoOwner) 111 if err != nil { 112 return nil, nil, err 113 } 114 opt.RepoOwnerID = u.ID 115 } else if opt.RepoOwnerID == 0 { 116 // gitea <= 1.12 require RepoOwnerID 117 u, _, err := c.GetMyUserInfo() 118 if err != nil { 119 return nil, nil, err 120 } 121 opt.RepoOwnerID = u.ID 122 } 123 } 124 125 body, err := json.Marshal(&opt) 126 if err != nil { 127 return nil, nil, err 128 } 129 repo := new(Repository) 130 resp, err := c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo) 131 return repo, resp, err 132} 133