diff --git a/internal/dependencies/aws_edit.go b/internal/dependencies/aws_edit.go index 7b4e4f7..5880d1f 100644 --- a/internal/dependencies/aws_edit.go +++ b/internal/dependencies/aws_edit.go @@ -44,6 +44,8 @@ func provideAWSEditFeature( awsServiceBuilderSet, awsViewableErrorBuilder, + loggerSet, + stepperSet, vscodeProcessManagerSet, diff --git a/internal/dependencies/aws_remove.go b/internal/dependencies/aws_remove.go index 54b8e7f..78eceac 100644 --- a/internal/dependencies/aws_remove.go +++ b/internal/dependencies/aws_remove.go @@ -44,6 +44,8 @@ func provideAWSRemoveFeature( awsServiceBuilderSet, awsViewableErrorBuilder, + loggerSet, + stepperSet, wire.Bind(new(features.RemoveOutputHandler), new(featuresCLI.RemoveOutputHandler)), diff --git a/internal/dependencies/aws_serve.go b/internal/dependencies/aws_serve.go index 6a9a60d..040bf15 100644 --- a/internal/dependencies/aws_serve.go +++ b/internal/dependencies/aws_serve.go @@ -44,6 +44,8 @@ func provideAWSServeFeature( awsServiceBuilderSet, awsViewableErrorBuilder, + loggerSet, + stepperSet, agentSet, diff --git a/internal/dependencies/aws_uninstall.go b/internal/dependencies/aws_uninstall.go index b46dc46..2ac97f0 100644 --- a/internal/dependencies/aws_uninstall.go +++ b/internal/dependencies/aws_uninstall.go @@ -44,6 +44,8 @@ func provideAWSUninstallFeature( awsServiceBuilderSet, awsViewableErrorBuilder, + loggerSet, + stepperSet, wire.Bind(new(features.UninstallOutputHandler), new(featuresCLI.UninstallOutputHandler)), diff --git a/internal/dependencies/aws_unserve.go b/internal/dependencies/aws_unserve.go index 9fc470c..f6354dc 100644 --- a/internal/dependencies/aws_unserve.go +++ b/internal/dependencies/aws_unserve.go @@ -44,6 +44,8 @@ func provideAWSUnserveFeature( awsServiceBuilderSet, awsViewableErrorBuilder, + loggerSet, + stepperSet, agentSet, diff --git a/internal/dependencies/hetzner_edit.go b/internal/dependencies/hetzner_edit.go index a41bd00..36e83b5 100644 --- a/internal/dependencies/hetzner_edit.go +++ b/internal/dependencies/hetzner_edit.go @@ -48,6 +48,8 @@ func provideHetznerEditFeature( hetznerServiceBuilderSet, hetznerViewableErrorBuilder, + loggerSet, + stepperSet, vscodeProcessManagerSet, diff --git a/internal/dependencies/hetzner_remove.go b/internal/dependencies/hetzner_remove.go index 4f1b9fb..a51559d 100644 --- a/internal/dependencies/hetzner_remove.go +++ b/internal/dependencies/hetzner_remove.go @@ -48,6 +48,8 @@ func provideHetznerRemoveFeature( hetznerServiceBuilderSet, hetznerViewableErrorBuilder, + loggerSet, + stepperSet, wire.Bind(new(features.RemoveOutputHandler), new(featuresCLI.RemoveOutputHandler)), diff --git a/internal/dependencies/hetzner_serve.go b/internal/dependencies/hetzner_serve.go index 8ddb6a3..09026ad 100644 --- a/internal/dependencies/hetzner_serve.go +++ b/internal/dependencies/hetzner_serve.go @@ -48,6 +48,8 @@ func provideHetznerServeFeature( hetznerServiceBuilderSet, hetznerViewableErrorBuilder, + loggerSet, + stepperSet, agentSet, diff --git a/internal/dependencies/hetzner_uninstall.go b/internal/dependencies/hetzner_uninstall.go index 8e412bc..6d1ccb5 100644 --- a/internal/dependencies/hetzner_uninstall.go +++ b/internal/dependencies/hetzner_uninstall.go @@ -48,6 +48,8 @@ func provideHetznerUninstallFeature( hetznerServiceBuilderSet, hetznerViewableErrorBuilder, + loggerSet, + stepperSet, wire.Bind(new(features.UninstallOutputHandler), new(featuresCLI.UninstallOutputHandler)), diff --git a/internal/dependencies/hetzner_unserve.go b/internal/dependencies/hetzner_unserve.go index 47713a9..2ce3a6c 100644 --- a/internal/dependencies/hetzner_unserve.go +++ b/internal/dependencies/hetzner_unserve.go @@ -48,6 +48,8 @@ func provideHetznerUnserveFeature( hetznerServiceBuilderSet, hetznerViewableErrorBuilder, + loggerSet, + stepperSet, agentSet, diff --git a/internal/dependencies/wire_gen.go b/internal/dependencies/wire_gen.go index 558388a..8180781 100644 --- a/internal/dependencies/wire_gen.go +++ b/internal/dependencies/wire_gen.go @@ -36,7 +36,8 @@ import ( // Injectors from aws_edit.go: func provideAWSEditFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig.FilesResolverOpts, userConfigLocalResolverOpts aws.UserConfigLocalResolverOpts) features.EditFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) awsAWSViewableErrorBuilder := aws.NewAWSViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -60,7 +61,8 @@ func provideAWSEditFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResol // Injectors from aws_init.go: func provideAWSInitFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig.FilesResolverOpts, userConfigLocalResolverOpts aws.UserConfigLocalResolverOpts) features.InitFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) userConfig := config2.NewUserConfig() awsAWSViewableErrorBuilder := aws.NewAWSViewableErrorBuilder() displayer := system.NewDisplayer() @@ -69,7 +71,6 @@ func provideAWSInitFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResol initPresenter := presenters.NewInitPresenter(awsAWSViewableErrorBuilder, initView) defaultClientBuilder := agent.NewDefaultClientBuilder() githubService := github.NewService() - logger := system.NewLogger() sshConfig := ssh.NewConfigWithDefaultConfigFilePath() keys := ssh.NewKeysWithDefaultDir() knownHosts := ssh.NewKnownHostsWithDefaultKnownHostsFilePath() @@ -89,7 +90,8 @@ func provideAWSInitFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResol // Injectors from aws_remove.go: func provideAWSRemoveFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig.FilesResolverOpts, userConfigLocalResolverOpts aws.UserConfigLocalResolverOpts) features.RemoveFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) awsAWSViewableErrorBuilder := aws.NewAWSViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -111,7 +113,8 @@ func provideAWSRemoveFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsRes // Injectors from aws_serve.go: func provideAWSServeFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig.FilesResolverOpts, userConfigLocalResolverOpts aws.UserConfigLocalResolverOpts) features.ServeFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) awsAWSViewableErrorBuilder := aws.NewAWSViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -134,7 +137,8 @@ func provideAWSServeFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsReso // Injectors from aws_uninstall.go: func provideAWSUninstallFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig.FilesResolverOpts, userConfigLocalResolverOpts aws.UserConfigLocalResolverOpts) features.UninstallFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) awsAWSViewableErrorBuilder := aws.NewAWSViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -156,7 +160,8 @@ func provideAWSUninstallFeature(userConfigEnvVarsResolverOpts userconfig.EnvVars // Injectors from aws_unserve.go: func provideAWSUnserveFeature(userConfigEnvVarsResolverOpts userconfig.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig.FilesResolverOpts, userConfigLocalResolverOpts aws.UserConfigLocalResolverOpts) features.UnserveFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) awsAWSViewableErrorBuilder := aws.NewAWSViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -189,7 +194,8 @@ func ProvideEnvRepositoriesResolver() entities.EnvRepositoriesResolver { // Injectors from hetzner_edit.go: func provideHetznerEditFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig2.FilesResolverOpts, userConfigLocalResolverOpts hetzner.UserConfigLocalResolverOpts, serviceBuilderOpts service2.BuilderOpts) features.EditFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) hetznerHetznerViewableErrorBuilder := hetzner.NewHetznerViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -212,7 +218,8 @@ func provideHetznerEditFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVars // Injectors from hetzner_init.go: func provideHetznerInitFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig2.FilesResolverOpts, userConfigLocalResolverOpts hetzner.UserConfigLocalResolverOpts, serviceBuilderOpts service2.BuilderOpts) features.InitFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) userConfig := config2.NewUserConfig() hetznerHetznerViewableErrorBuilder := hetzner.NewHetznerViewableErrorBuilder() displayer := system.NewDisplayer() @@ -221,7 +228,6 @@ func provideHetznerInitFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVars initPresenter := presenters.NewInitPresenter(hetznerHetznerViewableErrorBuilder, initView) defaultClientBuilder := agent.NewDefaultClientBuilder() githubService := github.NewService() - logger := system.NewLogger() sshConfig := ssh.NewConfigWithDefaultConfigFilePath() keys := ssh.NewKeysWithDefaultDir() knownHosts := ssh.NewKnownHostsWithDefaultKnownHostsFilePath() @@ -240,7 +246,8 @@ func provideHetznerInitFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVars // Injectors from hetzner_remove.go: func provideHetznerRemoveFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig2.FilesResolverOpts, userConfigLocalResolverOpts hetzner.UserConfigLocalResolverOpts, serviceBuilderOpts service2.BuilderOpts) features.RemoveFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) hetznerHetznerViewableErrorBuilder := hetzner.NewHetznerViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -261,7 +268,8 @@ func provideHetznerRemoveFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVa // Injectors from hetzner_serve.go: func provideHetznerServeFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig2.FilesResolverOpts, userConfigLocalResolverOpts hetzner.UserConfigLocalResolverOpts, serviceBuilderOpts service2.BuilderOpts) features.ServeFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) hetznerHetznerViewableErrorBuilder := hetzner.NewHetznerViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -283,7 +291,8 @@ func provideHetznerServeFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVar // Injectors from hetzner_uninstall.go: func provideHetznerUninstallFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig2.FilesResolverOpts, userConfigLocalResolverOpts hetzner.UserConfigLocalResolverOpts, serviceBuilderOpts service2.BuilderOpts) features.UninstallFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) hetznerHetznerViewableErrorBuilder := hetzner.NewHetznerViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) @@ -304,7 +313,8 @@ func provideHetznerUninstallFeature(userConfigEnvVarsResolverOpts userconfig2.En // Injectors from hetzner_unserve.go: func provideHetznerUnserveFeature(userConfigEnvVarsResolverOpts userconfig2.EnvVarsResolverOpts, userConfigFilesResolverOpts userconfig2.FilesResolverOpts, userConfigLocalResolverOpts hetzner.UserConfigLocalResolverOpts, serviceBuilderOpts service2.BuilderOpts) features.UnserveFeature { - stepperStepper := stepper.NewStepper() + logger := system.NewLogger() + stepperStepper := stepper.NewStepper(logger) hetznerHetznerViewableErrorBuilder := hetzner.NewHetznerViewableErrorBuilder() displayer := system.NewDisplayer() baseView := views.NewBaseView(displayer) diff --git a/internal/exceptions/cmd.go b/internal/exceptions/cmd.go index af74f00..fa7e949 100644 --- a/internal/exceptions/cmd.go +++ b/internal/exceptions/cmd.go @@ -21,3 +21,12 @@ type ErrMissingRequirements struct { func (ErrMissingRequirements) Error() string { return "ErrMissingRequirements" } + +type ErrVSCodeError struct { + Logs string + ErrorMessage string +} + +func (ErrVSCodeError) Error() string { + return "ErrVSCodeError" +} diff --git a/internal/features/init.go b/internal/features/init.go index 3d37368..307b7d4 100644 --- a/internal/features/init.go +++ b/internal/features/init.go @@ -2,7 +2,6 @@ package features import ( "encoding/json" - "fmt" "io" "strconv" @@ -218,7 +217,8 @@ func (i InitOutputHandler) HandleOutput(output features.InitOutput) error { if err != nil { stepper.StopCurrentStep() - return fmt.Errorf(logs + "\n\n" + err.Error()) + i.logger.Log(logs) + return err } if len(reply.LogLineHeader) > 0 { diff --git a/internal/features/login.go b/internal/features/login.go index 10cfd56..38be59d 100644 --- a/internal/features/login.go +++ b/internal/features/login.go @@ -165,17 +165,17 @@ func (l LoginFeature) Execute(input LoginInput) error { l.logger.Log(bold("\nYou will be taken to your browser to connect your GitHub account...\n")) l.logger.Info("If your browser doesn't open automatically, go to the following link:\n") - l.logger.Log("%s", gitHubOAuthAuthorizeURL) + l.logger.Log("%s\n", gitHubOAuthAuthorizeURL) l.sleeper.Sleep(4 * time.Second) if err := l.browser.OpenURL(gitHubOAuthAuthorizeURL); err != nil { l.logger.Error( - "\nCannot open browser! Please visit above URL ↑", + "Cannot open browser! Please visit above URL ↑\n", ) } - l.logger.Warning("\nWaiting for GitHub authorization... (Press Ctrl-C to quit)\n") + l.logger.Warning("Waiting for GitHub authorization... (Press Ctrl-C to quit)\n") select { case httpServerServeError := <-httpServerServeErrorChan: diff --git a/internal/presenters/errors.go b/internal/presenters/errors.go index d5e383e..2aa26fa 100644 --- a/internal/presenters/errors.go +++ b/internal/presenters/errors.go @@ -260,6 +260,14 @@ func (ElevenViewableErrorBuilder) Build(err error) (viewableError *views.Viewabl return } + if typedError, ok := err.(exceptions.ErrVSCodeError); ok { + viewableError.Title = "Visual Studio Code CLI error" + viewableError.Logs = typedError.Logs + viewableError.Message = typedError.ErrorMessage + + return + } + if typedError, ok := err.(entities.ErrUnresolvableDomain); ok { viewableError.Title = "Unresolvable domain name" viewableError.Message = fmt.Sprintf( diff --git a/internal/stepper/step.go b/internal/stepper/step.go index 78b6e64..f8518c2 100644 --- a/internal/stepper/step.go +++ b/internal/stepper/step.go @@ -1,12 +1,12 @@ package stepper import ( - "fmt" - "github.com/briandowns/spinner" + "github.com/eleven-sh/cli/internal/interfaces" ) type Step struct { + logger interfaces.Logger spin *spinner.Spinner removeAfterDone bool } @@ -15,6 +15,6 @@ func (s *Step) Done() { s.spin.Stop() if !s.removeAfterDone { - fmt.Println(s.spin.Prefix + "... done") + s.logger.Log(s.spin.Prefix + "... done") } } diff --git a/internal/stepper/stepper.go b/internal/stepper/stepper.go index dd4feeb..be2f6a7 100644 --- a/internal/stepper/stepper.go +++ b/internal/stepper/stepper.go @@ -1,20 +1,27 @@ package stepper import ( - "fmt" "time" "github.com/briandowns/spinner" "github.com/eleven-sh/cli/internal/config" + "github.com/eleven-sh/cli/internal/interfaces" "github.com/eleven-sh/eleven/stepper" ) var currentStep *Step -type Stepper struct{} +type Stepper struct { + logger interfaces.Logger +} + +func NewStepper( + logger interfaces.Logger, +) Stepper { -func NewStepper() Stepper { - return Stepper{} + return Stepper{ + logger: logger, + } } func (s Stepper) startStep( @@ -24,7 +31,7 @@ func (s Stepper) startStep( ) stepper.Step { if currentStep == nil && !noNewLineAtStart { - fmt.Println("") + s.logger.Log("") } if currentStep != nil { @@ -39,6 +46,7 @@ func (s Stepper) startStep( spin.Start() currentStep = &Step{ + logger: s.logger, spin: spin, removeAfterDone: removeAfterDone, } diff --git a/internal/system/displayer.go b/internal/system/displayer.go index 0252a03..12c0d72 100644 --- a/internal/system/displayer.go +++ b/internal/system/displayer.go @@ -12,5 +12,9 @@ func NewDisplayer() Displayer { } func (Displayer) Display(w io.Writer, format string, args ...interface{}) { - fmt.Fprintf(w, format, args...) + toDisplay := replaceNewLinesForOS( + fmt.Sprintf(format, args...), + ) + + fmt.Fprint(w, toDisplay) } diff --git a/internal/system/logger.go b/internal/system/logger.go index 090b9e0..6a57ddf 100644 --- a/internal/system/logger.go +++ b/internal/system/logger.go @@ -14,23 +14,43 @@ func NewLogger() Logger { } func (Logger) Info(format string, v ...interface{}) { - fmt.Fprintf(os.Stderr, config.ColorsCyan(format)+"\n", v...) + toDisplay := replaceNewLinesForOS( + fmt.Sprintf(format+"\n", v...), + ) + + fmt.Fprint(os.Stderr, config.ColorsCyan(toDisplay)) } func (Logger) Warning(format string, v ...interface{}) { - fmt.Fprintf(os.Stderr, config.ColorsYellow(format)+"\n", v...) + toDisplay := replaceNewLinesForOS( + fmt.Sprintf(format+"\n", v...), + ) + + fmt.Fprint(os.Stderr, config.ColorsYellow(toDisplay)) } func (Logger) Error(format string, v ...interface{}) { - fmt.Fprintf(os.Stderr, config.ColorsRed(format)+"\n", v...) + toDisplay := replaceNewLinesForOS( + fmt.Sprintf(format+"\n", v...), + ) + + fmt.Fprint(os.Stderr, config.ColorsRed(toDisplay)) } func (Logger) Log(format string, v ...interface{}) { - fmt.Fprintf(os.Stderr, format+"\n", v...) + toDisplay := replaceNewLinesForOS( + fmt.Sprintf(format+"\n", v...), + ) + + fmt.Fprint(os.Stderr, toDisplay) } func (Logger) LogNoNewline(format string, v ...interface{}) { - fmt.Fprintf(os.Stderr, format, v...) + toDisplay := replaceNewLinesForOS( + fmt.Sprintf(format, v...), + ) + + fmt.Fprint(os.Stderr, toDisplay) } func (l Logger) Write(p []byte) (n int, err error) { diff --git a/internal/system/new_line.go b/internal/system/new_line.go index c46c44f..b533581 100644 --- a/internal/system/new_line.go +++ b/internal/system/new_line.go @@ -1,6 +1,9 @@ package system -import "runtime" +import ( + "runtime" + "strings" +) var NewLineChar = "\n" @@ -9,3 +12,7 @@ func init() { NewLineChar = "\r\n" } } + +func replaceNewLinesForOS(s string) string { + return strings.ReplaceAll(s, "\n", NewLineChar) +} diff --git a/internal/vscode/cli.go b/internal/vscode/cli.go index 765ed0a..c071851 100644 --- a/internal/vscode/cli.go +++ b/internal/vscode/cli.go @@ -6,10 +6,9 @@ import ( "os" "os/exec" "path/filepath" - "regexp" "runtime" - "strings" + "github.com/eleven-sh/cli/internal/exceptions" "github.com/eleven-sh/cli/internal/system" ) @@ -32,27 +31,21 @@ func (c CLI) Exec(arg ...string) (string, error) { cmd := exec.Command(CLIPath, arg...) - var stdout bytes.Buffer - var stderr bytes.Buffer + var stdBuf bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr + cmd.Stdout = &stdBuf + cmd.Stderr = &stdBuf err = cmd.Run() if err != nil { - newLineRegExp := regexp.MustCompile(`\n+`) - - return "", fmt.Errorf( - "Error while calling the Visual Studio Code CLI:\n\n%s\n\n%s", - strings.TrimSpace( - newLineRegExp.ReplaceAllLiteralString(stderr.String(), " "), - ), - err.Error(), - ) + return "", exceptions.ErrVSCodeError{ + Logs: stdBuf.String(), + ErrorMessage: err.Error(), + } } - return stdout.String(), nil + return stdBuf.String(), nil } func (c CLI) LookupPath(operatingSystem string) (string, error) {