From 3c1efd33e2ad8a5d2477c3dae21a487d8b89e82c Mon Sep 17 00:00:00 2001 From: Norwin Date: Mon, 1 Mar 2021 06:29:26 +0800 Subject: [PATCH] InitCommand() robustness (#327) fixes #320 Co-authored-by: Norwin Roosen Reviewed-on: https://gitea.com/gitea/tea/pulls/327 Reviewed-by: Andrew Thornton Reviewed-by: 6543 <6543@obermui.de> Co-authored-by: Norwin Co-committed-by: Norwin --- modules/context/context.go | 43 ++++++++++++++++++++++---------------- modules/utils/path.go | 22 ++++++++++++++++--- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/modules/context/context.go b/modules/context/context.go index d7b3cb3..80c8c92 100644 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -75,13 +75,16 @@ func InitCommand(ctx *cli.Context) *TeaContext { loginFlag := ctx.String("login") remoteFlag := ctx.String("remote") - var repoSlug string - var repoPath string // empty means PWD - var repoFlagPathExists bool + 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 { - repoFlagPathExists, err := utils.PathExists(repoFlag) + repoFlagPathExists, err = utils.DirExists(repoFlag) if err != nil { log.Fatal(err.Error()) } @@ -90,38 +93,42 @@ func InitCommand(ctx *cli.Context) *TeaContext { } } - // try to read git repo & extract context, ignoring if PWD is not a repo - localRepo, login, repoSlug, err := contextFromLocalRepo(repoPath, remoteFlag) - if err != nil && err != gogit.ErrRepositoryNotExists { - log.Fatal(err.Error()) + if len(repoFlag) == 0 || repoFlagPathExists { + // try to read git repo & extract context, ignoring if PWD is not a repo + c.LocalRepo, c.Login, c.RepoSlug, err = contextFromLocalRepo(repoPath, remoteFlag) + if err != nil && err != gogit.ErrRepositoryNotExists { + log.Fatal(err.Error()) + } } - // if repoFlag is not a path, use it to override repoSlug 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 if len(loginFlag) != 0 { - login = config.GetLoginByName(loginFlag) - if login == nil { + c.Login = config.GetLoginByName(loginFlag) + if c.Login == nil { log.Fatalf("Login name '%s' does not exist", loginFlag) } - } else if login == nil { - if login, err = config.GetDefaultLogin(); err != nil { + } else if c.Login == nil { + if c.Login, err = config.GetDefaultLogin(); err != nil { log.Fatal(err.Error()) } } // 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 -func contextFromLocalRepo(repoValue, remoteValue string) (*git.TeaRepo, *config.Login, string, error) { - repo, err := git.RepoFromPath(repoValue) +func contextFromLocalRepo(repoPath, remoteValue string) (*git.TeaRepo, *config.Login, string, error) { + repo, err := git.RepoFromPath(repoPath) if err != nil { return nil, nil, "", err } diff --git a/modules/utils/path.go b/modules/utils/path.go index 4963093..a7ebecb 100644 --- a/modules/utils/path.go +++ b/modules/utils/path.go @@ -26,15 +26,31 @@ func PathExists(path string) (bool, error) { // FileExist returns whether the given file exists or not 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 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, err } - if f.IsDir() { + isDir := f.IsDir() + if isDir && !expectDir { 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 }