mirror of
				https://gitea.com/gitea/tea.git
				synced 2025-10-31 09:15:26 +01:00 
			
		
		
		
	When there is no login detected, list all possible logins to select
This commit is contained in:
		| @@ -6,7 +6,6 @@ package context | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"log" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"strconv" | ||||
| @@ -16,15 +15,11 @@ import ( | ||||
| 	"code.gitea.io/tea/modules/config" | ||||
| 	"code.gitea.io/tea/modules/debug" | ||||
| 	"code.gitea.io/tea/modules/git" | ||||
| 	"code.gitea.io/tea/modules/theme" | ||||
| 	"code.gitea.io/tea/modules/utils" | ||||
|  | ||||
| 	"github.com/charmbracelet/huh" | ||||
| 	gogit "github.com/go-git/go-git/v5" | ||||
| 	"github.com/urfave/cli/v3" | ||||
| ) | ||||
|  | ||||
| var errNotAGiteaRepo = errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository") | ||||
| var ErrNotAGiteaRepo = errors.New("No Gitea login found. You might want to specify --repo (and --login) to work outside of a repository") | ||||
|  | ||||
| // TeaContext contains all context derived during command initialization and wraps cli.Context | ||||
| type TeaContext struct { | ||||
| @@ -65,108 +60,8 @@ type CtxRequirement struct { | ||||
| 	RemoteRepo bool | ||||
| } | ||||
|  | ||||
| // InitCommand resolves the application context, and returns the active login, and if | ||||
| // available the repo slug. It does this by reading the config file for logins, parsing | ||||
| // the remotes of the .git repo specified in repoFlag or $PWD, and using overrides from | ||||
| // command flags. If a local git repo can't be found, repo slug values are unset. | ||||
| func InitCommand(cmd *cli.Command) *TeaContext { | ||||
| 	// these flags are used as overrides to the context detection via local git repo | ||||
| 	repoFlag := cmd.String("repo") | ||||
| 	loginFlag := cmd.String("login") | ||||
| 	remoteFlag := cmd.String("remote") | ||||
|  | ||||
| 	var ( | ||||
| 		c                  TeaContext | ||||
| 		err                error | ||||
| 		repoPath           string // empty means PWD | ||||
| 		repoFlagPathExists bool | ||||
| 	) | ||||
|  | ||||
| 	// check if repoFlag can be interpreted as path to local repo. | ||||
| 	if len(repoFlag) != 0 { | ||||
| 		if repoFlagPathExists, err = utils.DirExists(repoFlag); err != nil { | ||||
| 			log.Fatal(err.Error()) | ||||
| 		} | ||||
| 		if repoFlagPathExists { | ||||
| 			repoPath = repoFlag | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(remoteFlag) == 0 { | ||||
| 		remoteFlag = config.GetPreferences().FlagDefaults.Remote | ||||
| 	} | ||||
|  | ||||
| 	if repoPath == "" { | ||||
| 		if repoPath, err = os.Getwd(); err != nil { | ||||
| 			log.Fatal(err.Error()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// try to read local git repo & extract context: if repoFlag specifies a valid path, read repo in that dir, | ||||
| 	// otherwise attempt PWD. if no repo is found, continue with default login | ||||
| 	if c.LocalRepo, c.Login, c.RepoSlug, err = contextFromLocalRepo(repoPath, remoteFlag); err != nil { | ||||
| 		if err == errNotAGiteaRepo || err == gogit.ErrRepositoryNotExists { | ||||
| 			// we can deal with that, commands needing the optional values use ctx.Ensure() | ||||
| 		} else { | ||||
| 			log.Fatal(err.Error()) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if len(repoFlag) != 0 && !repoFlagPathExists { | ||||
| 		// if repoFlag is not a valid path, use it to override repoSlug | ||||
| 		c.RepoSlug = repoFlag | ||||
| 	} | ||||
|  | ||||
| 	// override config user with env variable | ||||
| 	envLogin := GetLoginByEnvVar() | ||||
| 	if envLogin != nil { | ||||
| 		_, err := utils.ValidateAuthenticationMethod(envLogin.URL, envLogin.Token, "", "", false, "", "") | ||||
| 		if err != nil { | ||||
| 			log.Fatal(err.Error()) | ||||
| 		} | ||||
| 		c.Login = envLogin | ||||
| 	} | ||||
|  | ||||
| 	// override login from flag, or use default login if repo based detection failed | ||||
| 	if len(loginFlag) != 0 { | ||||
| 		c.Login = config.GetLoginByName(loginFlag) | ||||
| 		if c.Login == nil { | ||||
| 			log.Fatalf("Login name '%s' does not exist", loginFlag) | ||||
| 		} | ||||
| 	} else if c.Login == nil { | ||||
| 		if c.Login, err = config.GetDefaultLogin(); err != nil { | ||||
| 			if err.Error() == "No available login" { | ||||
| 				// TODO: maybe we can directly start interact.CreateLogin() (only if | ||||
| 				// we're sure we can interactively!), as gh cli does. | ||||
| 				fmt.Println(`No gitea login configured. To start using tea, first run | ||||
|   tea login add | ||||
| and then run your command again.`) | ||||
| 			} | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
|  | ||||
| 		fallback := false | ||||
| 		if err := huh.NewConfirm(). | ||||
| 			Title(fmt.Sprintf("NOTE: no gitea login detected, whether falling back to login '%s'?", c.Login.Name)). | ||||
| 			Value(&fallback). | ||||
| 			WithTheme(theme.GetTheme()). | ||||
| 			Run(); err != nil { | ||||
| 			log.Fatalf("Get confirm failed: %v", err) | ||||
| 		} | ||||
| 		if !fallback { | ||||
| 			os.Exit(1) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// parse reposlug (owner falling back to login owner if reposlug contains only repo name) | ||||
| 	c.Owner, c.Repo = utils.GetOwnerAndRepo(c.RepoSlug, c.Login.User) | ||||
| 	c.Command = cmd | ||||
| 	c.Output = cmd.String("output") | ||||
| 	return &c | ||||
| } | ||||
|  | ||||
| // contextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo | ||||
| func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.Login, string, error) { | ||||
| // ContextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo | ||||
| func ContextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.Login, string, error) { | ||||
| 	repo, err := git.RepoFromPath(repoPath) | ||||
| 	if err != nil { | ||||
| 		return nil, nil, "", err | ||||
| @@ -178,7 +73,7 @@ func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.L | ||||
| 	debug.Printf("Get git config %v of %s in repo %s", gitConfig, remoteValue, repoPath) | ||||
|  | ||||
| 	if len(gitConfig.Remotes) == 0 { | ||||
| 		return repo, nil, "", errNotAGiteaRepo | ||||
| 		return repo, nil, "", ErrNotAGiteaRepo | ||||
| 	} | ||||
|  | ||||
| 	// When no preferred value is given, choose a remote to find a | ||||
| @@ -229,7 +124,7 @@ func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.L | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return repo, nil, "", errNotAGiteaRepo | ||||
| 	return repo, nil, "", ErrNotAGiteaRepo | ||||
| } | ||||
|  | ||||
| // MatchLogins matches the given remoteURL against the provided logins and returns | ||||
| @@ -274,7 +169,7 @@ func MatchLogins(remoteURL string, logins []config.Login) (*config.Login, string | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, "", errNotAGiteaRepo | ||||
| 	return nil, "", ErrNotAGiteaRepo | ||||
| } | ||||
|  | ||||
| // GetLoginByEnvVar returns a login based on environment variables, or nil if no login can be created | ||||
|   | ||||
| @@ -306,3 +306,39 @@ var tokenScopeOpts = []string{ | ||||
| 	string(gitea.AccessTokenScopeReadApplication), | ||||
| 	string(gitea.AccessTokenScopeSudo), | ||||
| } | ||||
|  | ||||
| func LoginSelect() (*config.Login, error) { | ||||
| 	logins, err := config.GetLogins() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(logins) == 0 { | ||||
| 		return nil, errors.New("no gitea login configured") | ||||
| 	} | ||||
| 	if len(logins) == 1 { | ||||
| 		return &logins[0], nil | ||||
| 	} | ||||
|  | ||||
| 	loginNames := make([]string, 0, len(logins)) | ||||
| 	for _, l := range logins { | ||||
| 		loginNames = append(loginNames, l.Name) | ||||
| 	} | ||||
|  | ||||
| 	defaultLogin, _ := config.GetDefaultLogin() | ||||
| 	var defaultValue string | ||||
| 	if defaultLogin != nil { | ||||
| 		defaultValue = defaultLogin.Name | ||||
| 	} | ||||
|  | ||||
| 	loginName, err := promptSelect("Select gitea login: ", loginNames, "", "", defaultValue) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| 	for _, l := range logins { | ||||
| 		if l.Name == loginName { | ||||
| 			return &l, nil | ||||
| 		} | ||||
| 	} | ||||
| 	return nil, fmt.Errorf("login name '%s' does not exist", loginName) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Lunny Xiao
					Lunny Xiao