From e86ad248c3c1e5da366dd6d79847aabd840ad4bb Mon Sep 17 00:00:00 2001 From: xu0o0 Date: Thu, 8 Jun 2023 17:20:11 +0800 Subject: [PATCH] fix(cli): fix import path with `--nomod` (#2775) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 包子 --- cmd/kratos/internal/project/new.go | 2 +- cmd/kratos/internal/project/project.go | 11 +- cmd/kratos/internal/project/project_test.go | 144 ++++++++++++++++++++ 3 files changed, 154 insertions(+), 3 deletions(-) create mode 100644 cmd/kratos/internal/project/project_test.go diff --git a/cmd/kratos/internal/project/new.go b/cmd/kratos/internal/project/new.go index 73c01986c..038b22049 100644 --- a/cmd/kratos/internal/project/new.go +++ b/cmd/kratos/internal/project/new.go @@ -39,7 +39,7 @@ func (p *Project) New(ctx context.Context, dir string, layout string, branch str } fmt.Printf("🚀 Creating service %s, layout repo is %s, please wait a moment.\n\n", p.Name, layout) repo := base.NewRepo(layout, branch) - if err := repo.CopyTo(ctx, to, p.Path, []string{".git", ".github"}); err != nil { + if err := repo.CopyTo(ctx, to, p.Name, []string{".git", ".github"}); err != nil { return err } e := os.Rename( diff --git a/cmd/kratos/internal/project/project.go b/cmd/kratos/internal/project/project.go index 44d3ead91..ef3bcad80 100644 --- a/cmd/kratos/internal/project/project.go +++ b/cmd/kratos/internal/project/project.go @@ -66,7 +66,7 @@ func run(_ *cobra.Command, args []string) { name = args[0] } projectName, workingDir := processProjectParams(name, wd) - p := &Project{Name: projectName, Path: projectName} + p := &Project{Name: projectName} done := make(chan error, 1) go func() { if !nomod { @@ -79,9 +79,16 @@ func run(_ *cobra.Command, args []string) { return } + p.Path, err = filepath.Rel(projectRoot, filepath.Join(workingDir, projectName)) + if err != nil { + done <- fmt.Errorf("🚫 failed to get relative path: %v", err) + return + } + mod, e := base.ModulePath(filepath.Join(projectRoot, "go.mod")) if e != nil { - panic(e) + done <- fmt.Errorf("🚫 failed to parse `go.mod`: %v", e) + return } // Get the relative path for adding a project based on Go modules p.Path = filepath.Join(strings.TrimPrefix(workingDir, projectRoot+"/"), p.Name) diff --git a/cmd/kratos/internal/project/project_test.go b/cmd/kratos/internal/project/project_test.go new file mode 100644 index 000000000..b11ab48bc --- /dev/null +++ b/cmd/kratos/internal/project/project_test.go @@ -0,0 +1,144 @@ +package project + +import ( + "fmt" + "go/parser" + "go/token" + "os" + "path/filepath" + "testing" + + "github.com/go-kratos/kratos/cmd/kratos/v2/internal/base" +) + +// TestCmdNew tests the `kratos new` command. +func TestCmdNew(t *testing.T) { + cwd := changeCurrentDir(t) + projectName := "helloworld" + + // create a new project + CmdNew.SetArgs([]string{projectName}) + if err := CmdNew.Execute(); err != nil { + t.Fatalf("executing command: %v", err) + } + + // check that the expected files were created + for _, file := range []string{ + "go.mod", + "go.sum", + "README.md", + "cmd/helloworld/main.go", + } { + if _, err := os.Stat(filepath.Join(cwd, projectName, file)); err != nil { + t.Errorf("expected file %s to exist", file) + } + } + + // check that the go.mod file contains the expected module name + assertGoMod(t, filepath.Join(cwd, projectName, "go.mod"), projectName) + + assertImportsInclude(t, filepath.Join(cwd, projectName, "cmd", projectName, "wire.go"), fmt.Sprintf(`"%s/internal/biz"`, projectName)) +} + +// TestCmdNewNoMod tests the `kratos new` command with the --nomod flag. +func TestCmdNewNoMod(t *testing.T) { + cwd := changeCurrentDir(t) + + // create a new project + CmdNew.SetArgs([]string{"project"}) + if err := CmdNew.Execute(); err != nil { + t.Fatalf("executing command: %v", err) + } + + // add new app with --nomod flag + CmdNew.SetArgs([]string{"--nomod", "project/app/user"}) + if err := CmdNew.Execute(); err != nil { + t.Fatalf("executing command: %v", err) + } + + // check that the expected files were created + for _, file := range []string{ + "go.mod", + "go.sum", + "README.md", + "cmd/project/main.go", + "app/user/cmd/user/main.go", + } { + if _, err := os.Stat(filepath.Join(cwd, "project", file)); err != nil { + t.Errorf("expected file %s to exist", file) + } + } + + assertImportsInclude(t, filepath.Join(cwd, "project/app/user/cmd/user/wire.go"), `"project/app/user/internal/biz"`) +} + +// assertImportsInclude checks that the file at path contains the expected import. +func assertImportsInclude(t *testing.T, path, expected string) { + t.Helper() + + got, err := imports(path) + if err != nil { + t.Fatalf("getting imports: %v", err) + } + + for _, imp := range got { + if imp == expected { + return + } + } + + t.Errorf("expected imports to include %s, got %v", expected, got) +} + +// imports returns the imports in the file at path. +func imports(path string) ([]string, error) { + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, path, nil, parser.ImportsOnly) + if err != nil { + return nil, err + } + + imports := make([]string, 0, len(f.Imports)) + for _, s := range f.Imports { + imports = append(imports, s.Path.Value) + } + + return imports, nil +} + +// assertGoMod checks that the go.mod file contains the expected module name. +func assertGoMod(t *testing.T, path, expected string) { + t.Helper() + + got, err := base.ModulePath(path) + if err != nil { + t.Fatalf("getting module path: %v", err) + } + + if got != expected { + t.Errorf("expected module name %s, got %s", expected, got) + } +} + +// change the working directory to the tempdir +func changeCurrentDir(t *testing.T) string { + t.Helper() + + tmp := t.TempDir() + + oldCWD, err := os.Getwd() + if err != nil { + t.Fatalf("getting working directory: %v", err) + } + + if err := os.Chdir(tmp); err != nil { + t.Fatalf("changing working directory: %v", err) + } + t.Cleanup(func() { + if err := os.Chdir(oldCWD); err != nil { + t.Fatalf("restoring working directory: %v", err) + } + }) + + return tmp +}