diff --git a/cmd/args/appdir.go b/cmd/args/appdir.go index dc395f1..2ac0991 100644 --- a/cmd/args/appdir.go +++ b/cmd/args/appdir.go @@ -2,6 +2,7 @@ package args import ( "errors" + "path/filepath" "github.com/spf13/cobra" "numerous.com/cli/cmd/output" @@ -10,7 +11,7 @@ import ( var ErrOptionalAppDirArgCount = errors.New("there must be at most 1 argument for optional app directory") // Returns an arguments handler, which checks an optional app dir positional -// argument, and writes it into the given string reference. +// argument, and writes the absolute path into the given string reference. func OptionalAppDir(appDir *string) func(cmd *cobra.Command, args []string) error { return func(cmd *cobra.Command, args []string) error { if len(args) > 1 { @@ -21,10 +22,20 @@ func OptionalAppDir(appDir *string) func(cmd *cobra.Command, args []string) erro return ErrOptionalAppDirArgCount } - if len(args) == 1 { - *appDir = args[0] + // default to empty string + appDirArg := "" + if len(args) != 0 { + appDirArg = args[0] } + // find the absolute path - current working directory if appDirArg is empty + absAppDir, err := filepath.Abs(appDirArg) + if err != nil { + return err + } + + *appDir = absAppDir + return nil } } diff --git a/cmd/args/appdir_test.go b/cmd/args/appdir_test.go index 23fefe6..bf91e84 100644 --- a/cmd/args/appdir_test.go +++ b/cmd/args/appdir_test.go @@ -1,29 +1,54 @@ package args import ( + "os" + "path/filepath" "testing" "github.com/spf13/cobra" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestOptionalAppDir(t *testing.T) { t.Run("given single argument then it updates the variable", func(t *testing.T) { - var appDir string + wd := tempChdir(t) + type testCase struct { + arg string + expected string + } - err := OptionalAppDir(&appDir)(nil, []string{"some-app-dir"}) + for _, tc := range []testCase{ + { + arg: "relative-dir", + expected: filepath.Join(wd, "relative-dir"), + }, + { + arg: "relative/nested/dir", + expected: filepath.Join(wd, "relative", "nested", "dir"), + }, + { + arg: "/some/absolute/path", + expected: "/some/absolute/path", + }, + } { + var appDir string - assert.NoError(t, err) - assert.Equal(t, "some-app-dir", appDir) + err := OptionalAppDir(&appDir)(nil, []string{tc.arg}) + + assert.NoError(t, err) + assert.Equal(t, tc.expected, appDir) + } }) - t.Run("given zero arguments then it does not update the variable", func(t *testing.T) { + t.Run("given zero arguments then it updates to the current directory", func(t *testing.T) { + wd := tempChdir(t) appDir := "some-preexisting-value" err := OptionalAppDir(&appDir)(nil, []string{}) assert.NoError(t, err) - assert.Equal(t, "some-preexisting-value", appDir) + assert.Equal(t, wd, appDir) }) t.Run("given more than one argument then it returns an error", func(t *testing.T) { @@ -34,3 +59,22 @@ func TestOptionalAppDir(t *testing.T) { assert.ErrorIs(t, err, ErrOptionalAppDirArgCount) }) } + +// Create a temporary directory, change directory to it, return to the original +// working directory on test cleanup. Returns the temporary directory that the +// current directory is changed to. +func tempChdir(t *testing.T) string { + t.Helper() + + testWd := t.TempDir() + prevWd, err := os.Getwd() + require.NoError(t, err) + + t.Cleanup(func() { + _ = os.Chdir(prevWd) + }) + + require.NoError(t, os.Chdir(testWd)) + + return testWd +} diff --git a/cmd/init/cmd.go b/cmd/init/cmd.go index d4bb3b9..2680380 100644 --- a/cmd/init/cmd.go +++ b/cmd/init/cmd.go @@ -3,9 +3,10 @@ package init import ( "errors" "fmt" - "os" - "strings" + "path/filepath" + "numerous.com/cli/cmd/args" + "numerous.com/cli/cmd/errorhandling" "numerous.com/cli/cmd/group" "numerous.com/cli/cmd/output" "numerous.com/cli/internal/manifest" @@ -15,12 +16,12 @@ import ( ) var Cmd = &cobra.Command{ - Use: "init [flags]", + Use: "init [app directory]", Aliases: []string{"initialize"}, GroupID: group.AppCommandsGroupID, Short: "Initialize a Numerous project", Long: `Helps the user bootstrap a python project as a numerous project.`, - Args: cobra.MaximumNArgs(1), + Args: args.OptionalAppDir(&cmdArgs.appDir), RunE: run, } @@ -33,6 +34,7 @@ var cmdArgs struct { dockerfilePath string dockerContextPath string dockerPort uint + appDir string } var ( @@ -41,17 +43,13 @@ var ( ) func run(cmd *cobra.Command, args []string) error { - appDir, err := os.Getwd() + absAppDir, err := filepath.Abs(cmdArgs.appDir) if err != nil { return ErrGetWorkDir } - if len(args) != 0 { - appDir = PathArgumentHandler(args[0], appDir) - } - params := InitializeParams{ - AppDir: appDir, + AppDir: absAppDir, Name: cmdArgs.name, Desc: cmdArgs.description, LibraryKey: cmdArgs.libraryKey, @@ -65,7 +63,7 @@ func run(cmd *cobra.Command, args []string) error { if errors.Is(err, wizard.ErrStopInit) { return nil } else if err != nil { - return err + return errorhandling.ErrAlreadyPrinted } printSuccess() @@ -103,19 +101,3 @@ func init() { Cmd.Flags().StringVar(&cmdArgs.dockerContextPath, "docker-context", "", "Path used as the context for building the app Dockerfile") Cmd.Flags().UintVar(&cmdArgs.dockerPort, "docker-port", 0, "The port exposed in the Dockerfile") } - -func PathArgumentHandler(providedPath string, currentPath string) string { - appPath := providedPath - if providedPath != "." { - pathBegin := string([]rune(providedPath)[0:2]) - if pathBegin == "./" || pathBegin == ".\\" { - appPath = strings.Replace(appPath, ".", currentPath, 1) - } else { - appPath = providedPath - } - } else { - appPath = currentPath - } - - return appPath -} diff --git a/cmd/legacy/initialize/cmd.go b/cmd/legacy/initialize/cmd.go index a7cc1db..600221a 100644 --- a/cmd/legacy/initialize/cmd.go +++ b/cmd/legacy/initialize/cmd.go @@ -2,8 +2,9 @@ package initialize import ( "fmt" - "os" + "path/filepath" + "numerous.com/cli/cmd/args" cmdinit "numerous.com/cli/cmd/init" "numerous.com/cli/cmd/output" "numerous.com/cli/internal/dir" @@ -20,7 +21,7 @@ var InitCmd = &cobra.Command{ Aliases: []string{"initialize"}, Short: "Initialize a Numerous project", Long: `Helps the user bootstrap a python project as a Numerous project.`, - Args: cobra.MaximumNArgs(1), + Args: args.OptionalAppDir(&cmdArgs.appDir), Run: run, } @@ -30,18 +31,15 @@ var cmdArgs struct { libraryKey string appFile string requirementsFile string + appDir string } func run(cmd *cobra.Command, args []string) { - appDir, err := os.Getwd() + appDir, err := filepath.Abs(cmdArgs.appDir) if err != nil { return } - if len(args) != 0 { - appDir = cmdinit.PathArgumentHandler(args[0], appDir) - } - if exists, _ := dir.AppIDExists(appDir); exists { printAlreadyInitialized(appDir, fmt.Sprintf("Files %q or %q exists", dir.AppIDFileName, dir.ToolIDFileName)) return