github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/gits/git_repo.go (about) 1 package gits 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/jenkins-x/jx-logging/pkg/log" 8 "github.com/olli-ai/jx/v2/pkg/auth" 9 "github.com/olli-ai/jx/v2/pkg/util" 10 "gopkg.in/AlecAivazis/survey.v1" 11 ) 12 13 type CreateRepoData struct { 14 Organisation string 15 RepoName string 16 FullName string 17 Public bool 18 User *auth.UserAuth 19 GitProvider GitProvider 20 GitServer *auth.AuthServer 21 } 22 23 type GitRepositoryOptions struct { 24 ServerURL string 25 ServerKind string 26 Username string 27 ApiToken string 28 Owner string 29 RepoName string 30 Public bool 31 IgnoreExistingRepository bool 32 } 33 34 // GetRepository returns the repository if it already exists 35 func (d *CreateRepoData) GetRepository() (*GitRepository, error) { 36 return d.GitProvider.GetRepository(d.Organisation, d.RepoName) 37 } 38 39 // CreateRepository creates the repository - failing if it already exists 40 func (d *CreateRepoData) CreateRepository() (*GitRepository, error) { 41 return d.GitProvider.CreateRepository(d.Organisation, d.RepoName, !d.Public) 42 } 43 44 func PickNewOrExistingGitRepository(batchMode bool, authConfigSvc auth.ConfigService, defaultRepoName string, 45 repoOptions *GitRepositoryOptions, server *auth.AuthServer, userAuth *auth.UserAuth, git Gitter, allowExistingRepo bool, handles util.IOFileHandles) (*CreateRepoData, error) { 46 config := authConfigSvc.Config() 47 48 var err error 49 if server == nil { 50 if repoOptions.ServerURL != "" { 51 server = config.GetOrCreateServer(repoOptions.ServerURL) 52 } else { 53 if batchMode { 54 if len(config.Servers) == 0 { 55 return nil, fmt.Errorf("No Git servers are configured!") 56 } 57 // lets assume the first for now 58 server = config.Servers[0] 59 currentServer := config.CurrentServer 60 if currentServer != "" { 61 for _, s := range config.Servers { 62 if s.Name == currentServer || s.URL == currentServer { 63 server = s 64 break 65 } 66 } 67 } 68 } else { 69 server, err = config.PickServer("Which Git service?", batchMode, handles) 70 if err != nil { 71 return nil, err 72 } 73 } 74 repoOptions.ServerURL = server.URL 75 } 76 } 77 78 log.Logger().Infof("Using Git provider %s", util.ColorInfo(server.Description())) 79 url := server.URL 80 81 if userAuth == nil { 82 if repoOptions.Username != "" { 83 userAuth = config.GetOrCreateUserAuth(url, repoOptions.Username) 84 log.Logger().Infof(util.QuestionAnswer("Using Git user name", repoOptions.Username)) 85 } else { 86 if batchMode { 87 if len(server.Users) == 0 { 88 return nil, fmt.Errorf("Server %s has no user auths defined", url) 89 } 90 var ua *auth.UserAuth 91 if server.CurrentUser != "" { 92 ua = config.FindUserAuth(url, server.CurrentUser) 93 } 94 if ua == nil { 95 ua = server.Users[0] 96 } 97 userAuth = ua 98 } else { 99 userAuth, err = config.PickServerUserAuth(server, "Git user name?", batchMode, "", handles) 100 if err != nil { 101 return nil, err 102 } 103 } 104 } 105 } 106 107 if userAuth.IsInvalid() && repoOptions.ApiToken != "" { 108 userAuth.ApiToken = repoOptions.ApiToken 109 } 110 111 if userAuth.IsInvalid() { 112 f := func(username string) error { 113 git.PrintCreateRepositoryGenerateAccessToken(server, username, handles.Out) 114 return nil 115 } 116 117 // TODO could we guess this based on the users ~/.git for github? 118 defaultUserName := "" 119 err = config.EditUserAuth(server.Label(), userAuth, defaultUserName, true, batchMode, f, handles) 120 if err != nil { 121 return nil, err 122 } 123 124 // TODO lets verify the auth works 125 126 err = authConfigSvc.SaveUserAuth(url, userAuth) 127 if err != nil { 128 return nil, fmt.Errorf("Failed to store git auth configuration %s", err) 129 } 130 if userAuth.IsInvalid() { 131 return nil, fmt.Errorf("You did not properly define the user authentication") 132 } 133 } 134 135 gitUsername := userAuth.Username 136 log.Logger().Debugf("About to create repository %s on server %s with user %s", util.ColorInfo(defaultRepoName), util.ColorInfo(url), util.ColorInfo(gitUsername)) 137 138 provider, err := CreateProvider(server, userAuth, git) 139 if err != nil { 140 return nil, err 141 } 142 143 owner := repoOptions.Owner 144 if owner == "" { 145 owner, err = GetOwner(batchMode, provider, gitUsername, handles) 146 if err != nil { 147 return nil, err 148 } 149 } else { 150 log.Logger().Infof(util.QuestionAnswer("Using organisation", owner)) 151 } 152 153 repoName := repoOptions.RepoName 154 if repoName == "" { 155 repoName, err = GetRepoName(batchMode, allowExistingRepo, provider, defaultRepoName, owner, handles) 156 if err != nil { 157 return nil, err 158 } 159 } else { 160 if !repoOptions.IgnoreExistingRepository { 161 err := provider.ValidateRepositoryName(owner, repoName) 162 if err != nil { 163 return nil, err 164 } 165 log.Logger().Infof(util.QuestionAnswer("Using repository", repoName)) 166 } 167 } 168 169 fullName := git.RepoName(owner, repoName) 170 log.Logger().Infof("Creating repository %s", util.ColorInfo(fullName)) 171 172 return &CreateRepoData{ 173 Organisation: owner, 174 RepoName: repoName, 175 FullName: fullName, 176 Public: repoOptions.Public, 177 User: userAuth, 178 GitProvider: provider, 179 GitServer: server, 180 }, err 181 } 182 183 func GetRepoName(batchMode, allowExistingRepo bool, provider GitProvider, defaultRepoName, owner string, handles util.IOFileHandles) (string, error) { 184 surveyOpts := survey.WithStdio(handles.In, handles.Out, handles.Err) 185 repoName := "" 186 if batchMode { 187 repoName = defaultRepoName 188 if repoName == "" { 189 repoName = "dummy" 190 } 191 } else { 192 prompt := &survey.Input{ 193 Message: "Enter the new repository name: ", 194 Default: defaultRepoName, 195 } 196 validator := func(val interface{}) error { 197 str, ok := val.(string) 198 if !ok { 199 return fmt.Errorf("Expected string value") 200 } 201 if strings.TrimSpace(str) == "" { 202 return fmt.Errorf("Repository name is required") 203 } 204 if allowExistingRepo { 205 return nil 206 } 207 return provider.ValidateRepositoryName(owner, str) 208 } 209 err := survey.AskOne(prompt, &repoName, validator, surveyOpts) 210 if err != nil { 211 return "", err 212 } 213 if repoName == "" { 214 return "", fmt.Errorf("No repository name specified") 215 } 216 } 217 return repoName, nil 218 } 219 220 func GetOwner(batchMode bool, provider OrganisationLister, gitUsername string, handles util.IOFileHandles) (string, error) { 221 owner := "" 222 if batchMode { 223 owner = gitUsername 224 } else { 225 org, err := PickOwner(provider, gitUsername, handles) 226 if err != nil { 227 return "", err 228 } 229 owner = org 230 if org == "" { 231 owner = gitUsername 232 } 233 } 234 return owner, nil 235 } 236 237 func PickNewGitRepository(batchMode bool, authConfigSvc auth.ConfigService, defaultRepoName string, 238 repoOptions *GitRepositoryOptions, server *auth.AuthServer, userAuth *auth.UserAuth, git Gitter, handles util.IOFileHandles) (*CreateRepoData, error) { 239 return PickNewOrExistingGitRepository(batchMode, authConfigSvc, defaultRepoName, repoOptions, server, userAuth, git, false, handles) 240 }