InitCommand() robustness (#327)

fixes #320

Co-authored-by: Norwin Roosen <git@nroo.de>
Reviewed-on: https://gitea.com/gitea/tea/pulls/327
Reviewed-by: Andrew Thornton <art27@cantab.net>
Reviewed-by: 6543 <6543@obermui.de>
Co-authored-by: Norwin <noerw@noreply.gitea.io>
Co-committed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
Norwin 2021-03-01 06:29:26 +08:00 committed by 6543
parent 9c8321f2e0
commit 3c1efd33e2
2 changed files with 44 additions and 21 deletions

View File

@ -75,13 +75,16 @@ func InitCommand(ctx *cli.Context) *TeaContext {
loginFlag := ctx.String("login") loginFlag := ctx.String("login")
remoteFlag := ctx.String("remote") remoteFlag := ctx.String("remote")
var repoSlug string var (
var repoPath string // empty means PWD c TeaContext
var repoFlagPathExists bool err error
repoPath string // empty means PWD
repoFlagPathExists bool
)
// check if repoFlag can be interpreted as path to local repo. // check if repoFlag can be interpreted as path to local repo.
if len(repoFlag) != 0 { if len(repoFlag) != 0 {
repoFlagPathExists, err := utils.PathExists(repoFlag) repoFlagPathExists, err = utils.DirExists(repoFlag)
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }
@ -90,38 +93,42 @@ func InitCommand(ctx *cli.Context) *TeaContext {
} }
} }
if len(repoFlag) == 0 || repoFlagPathExists {
// try to read git repo & extract context, ignoring if PWD is not a repo // try to read git repo & extract context, ignoring if PWD is not a repo
localRepo, login, repoSlug, err := contextFromLocalRepo(repoPath, remoteFlag) c.LocalRepo, c.Login, c.RepoSlug, err = contextFromLocalRepo(repoPath, remoteFlag)
if err != nil && err != gogit.ErrRepositoryNotExists { if err != nil && err != gogit.ErrRepositoryNotExists {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }
}
// if repoFlag is not a path, use it to override repoSlug
if len(repoFlag) != 0 && !repoFlagPathExists { if len(repoFlag) != 0 && !repoFlagPathExists {
repoSlug = repoFlag // if repoFlag is not a valid path, use it to override repoSlug
c.RepoSlug = repoFlag
} }
// override login from flag, or use default login if repo based detection failed // override login from flag, or use default login if repo based detection failed
if len(loginFlag) != 0 { if len(loginFlag) != 0 {
login = config.GetLoginByName(loginFlag) c.Login = config.GetLoginByName(loginFlag)
if login == nil { if c.Login == nil {
log.Fatalf("Login name '%s' does not exist", loginFlag) log.Fatalf("Login name '%s' does not exist", loginFlag)
} }
} else if login == nil { } else if c.Login == nil {
if login, err = config.GetDefaultLogin(); err != nil { if c.Login, err = config.GetDefaultLogin(); err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }
} }
// parse reposlug (owner falling back to login owner if reposlug contains only repo name) // parse reposlug (owner falling back to login owner if reposlug contains only repo name)
owner, reponame := utils.GetOwnerAndRepo(repoSlug, login.User) c.Owner, c.Repo = utils.GetOwnerAndRepo(c.RepoSlug, c.Login.User)
return &TeaContext{ctx, login, repoSlug, owner, reponame, ctx.String("output"), localRepo} c.Context = ctx
c.Output = ctx.String("output")
return &c
} }
// contextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo // contextFromLocalRepo discovers login & repo slug from the default branch remote of the given local repo
func contextFromLocalRepo(repoValue, remoteValue string) (*git.TeaRepo, *config.Login, string, error) { func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.Login, string, error) {
repo, err := git.RepoFromPath(repoValue) repo, err := git.RepoFromPath(repoPath)
if err != nil { if err != nil {
return nil, nil, "", err return nil, nil, "", err
} }

View File

@ -26,15 +26,31 @@ func PathExists(path string) (bool, error) {
// FileExist returns whether the given file exists or not // FileExist returns whether the given file exists or not
func FileExist(fileName string) (bool, error) { func FileExist(fileName string) (bool, error) {
f, err := os.Stat(fileName) return exists(fileName, false)
}
// DirExists returns whether the given file exists or not
func DirExists(path string) (bool, error) {
return exists(path, true)
}
func exists(path string, expectDir bool) (bool, error) {
f, err := os.Stat(path)
if err != nil { if err != nil {
if os.IsNotExist(err) { if errors.Is(err, os.ErrNotExist) {
return false, nil
} else if err.(*os.PathError).Err.Error() == "not a directory" {
// some middle segment of path is a file, cannot traverse
// FIXME: catches error on linux; go does not provide a way to catch this properly..
return false, nil return false, nil
} }
return false, err return false, err
} }
if f.IsDir() { isDir := f.IsDir()
if isDir && !expectDir {
return false, errors.New("A directory with the same name exists") return false, errors.New("A directory with the same name exists")
} else if !isDir && expectDir {
return false, errors.New("A file with the same name exists")
} }
return true, nil return true, nil
} }